AugmentationData.java 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. /*
  2. * Copyright (C) 2004-2013 L2J Server
  3. *
  4. * This file is part of L2J Server.
  5. *
  6. * L2J Server is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J Server is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.l2jserver.gameserver.datatables;
  20. import java.io.File;
  21. import java.util.ArrayList;
  22. import java.util.HashMap;
  23. import java.util.List;
  24. import java.util.Map;
  25. import java.util.logging.Level;
  26. import java.util.logging.Logger;
  27. import javax.xml.parsers.DocumentBuilderFactory;
  28. import org.w3c.dom.Document;
  29. import org.w3c.dom.NamedNodeMap;
  30. import org.w3c.dom.Node;
  31. import com.l2jserver.Config;
  32. import com.l2jserver.gameserver.model.L2Augmentation;
  33. import com.l2jserver.gameserver.model.holders.SkillHolder;
  34. import com.l2jserver.gameserver.model.items.L2Item;
  35. import com.l2jserver.gameserver.model.items.L2Weapon;
  36. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  37. import com.l2jserver.gameserver.model.options.Options;
  38. import com.l2jserver.gameserver.network.clientpackets.AbstractRefinePacket;
  39. import com.l2jserver.util.Rnd;
  40. /**
  41. * This class manages the augmentation data and can also create new augmentations.
  42. * @author durgus, Gigiikun, Sandro, UnAfraid
  43. */
  44. public class AugmentationData
  45. {
  46. private static final Logger _log = Logger.getLogger(AugmentationData.class.getName());
  47. // stats
  48. private static final int STAT_BLOCKSIZE = 3640;
  49. private static final int STAT_SUBBLOCKSIZE = 91;
  50. public static final int MIN_SKILL_ID = STAT_BLOCKSIZE * 4;
  51. // skills
  52. private static final int BLUE_START = 14561;
  53. private static final int SKILLS_BLOCKSIZE = 178;
  54. // basestats
  55. private static final int BASESTAT_STR = 16341;
  56. private static final int BASESTAT_MEN = 16344;
  57. // accessory
  58. private static final int ACC_START = 16669;
  59. private static final int ACC_BLOCKS_NUM = 10;
  60. private static final int ACC_STAT_SUBBLOCKSIZE = 21;
  61. private static final int ACC_RING_START = ACC_START;
  62. private static final int ACC_RING_SKILLS = 18;
  63. private static final int ACC_RING_BLOCKSIZE = ACC_RING_SKILLS + (4 * ACC_STAT_SUBBLOCKSIZE);
  64. private static final int ACC_RING_END = (ACC_RING_START + (ACC_BLOCKS_NUM * ACC_RING_BLOCKSIZE)) - 1;
  65. private static final int ACC_EAR_START = ACC_RING_END + 1;
  66. private static final int ACC_EAR_SKILLS = 18;
  67. private static final int ACC_EAR_BLOCKSIZE = ACC_EAR_SKILLS + (4 * ACC_STAT_SUBBLOCKSIZE);
  68. private static final int ACC_EAR_END = (ACC_EAR_START + (ACC_BLOCKS_NUM * ACC_EAR_BLOCKSIZE)) - 1;
  69. private static final int ACC_NECK_START = ACC_EAR_END + 1;
  70. private static final int ACC_NECK_SKILLS = 24;
  71. private static final int ACC_NECK_BLOCKSIZE = ACC_NECK_SKILLS + (4 * ACC_STAT_SUBBLOCKSIZE);
  72. private final List<List<Integer>> _blueSkills = new ArrayList<>(10);
  73. private final List<List<Integer>> _purpleSkills = new ArrayList<>(10);
  74. private final List<List<Integer>> _redSkills = new ArrayList<>(10);
  75. private final List<List<Integer>> _yellowSkills = new ArrayList<>(10);
  76. private final List<AugmentationChance> _augmentationChances = new ArrayList<>();
  77. private final List<augmentationChanceAcc> _augmentationChancesAcc = new ArrayList<>();
  78. private final Map<Integer, SkillHolder> _allSkills = new HashMap<>();
  79. protected AugmentationData()
  80. {
  81. for (int i = 0; i < 10; i++)
  82. {
  83. _blueSkills.add(new ArrayList<Integer>());
  84. _purpleSkills.add(new ArrayList<Integer>());
  85. _redSkills.add(new ArrayList<Integer>());
  86. _yellowSkills.add(new ArrayList<Integer>());
  87. }
  88. load();
  89. if (!Config.RETAIL_LIKE_AUGMENTATION)
  90. {
  91. for (int i = 0; i < 10; i++)
  92. {
  93. _log.info(getClass().getSimpleName() + ": Loaded: " + _blueSkills.get(i).size() + " blue, " + _purpleSkills.get(i).size() + " purple and " + _redSkills.get(i).size() + " red skills for lifeStoneLevel " + i);
  94. }
  95. }
  96. else
  97. {
  98. _log.log(Level.INFO, getClass().getSimpleName() + ": Loaded: " + _augmentationChances.size() + " augmentations.");
  99. _log.log(Level.INFO, getClass().getSimpleName() + ": Loaded: " + _augmentationChancesAcc.size() + " accessory augmentations.");
  100. }
  101. }
  102. public class AugmentationChance
  103. {
  104. private final String _WeaponType;
  105. private final int _StoneId;
  106. private final int _VariationId;
  107. private final int _CategoryChance;
  108. private final int _AugmentId;
  109. private final float _AugmentChance;
  110. public AugmentationChance(String WeaponType, int StoneId, int VariationId, int CategoryChance, int AugmentId, float AugmentChance)
  111. {
  112. _WeaponType = WeaponType;
  113. _StoneId = StoneId;
  114. _VariationId = VariationId;
  115. _CategoryChance = CategoryChance;
  116. _AugmentId = AugmentId;
  117. _AugmentChance = AugmentChance;
  118. }
  119. public String getWeaponType()
  120. {
  121. return _WeaponType;
  122. }
  123. public int getStoneId()
  124. {
  125. return _StoneId;
  126. }
  127. public int getVariationId()
  128. {
  129. return _VariationId;
  130. }
  131. public int getCategoryChance()
  132. {
  133. return _CategoryChance;
  134. }
  135. public int getAugmentId()
  136. {
  137. return _AugmentId;
  138. }
  139. public float getAugmentChance()
  140. {
  141. return _AugmentChance;
  142. }
  143. }
  144. public class augmentationChanceAcc
  145. {
  146. private final String _WeaponType;
  147. private final int _StoneId;
  148. private final int _VariationId;
  149. private final int _CategoryChance;
  150. private final int _AugmentId;
  151. private final float _AugmentChance;
  152. public augmentationChanceAcc(String WeaponType, int StoneId, int VariationId, int CategoryChance, int AugmentId, float AugmentChance)
  153. {
  154. _WeaponType = WeaponType;
  155. _StoneId = StoneId;
  156. _VariationId = VariationId;
  157. _CategoryChance = CategoryChance;
  158. _AugmentId = AugmentId;
  159. _AugmentChance = AugmentChance;
  160. }
  161. public String getWeaponType()
  162. {
  163. return _WeaponType;
  164. }
  165. public int getStoneId()
  166. {
  167. return _StoneId;
  168. }
  169. public int getVariationId()
  170. {
  171. return _VariationId;
  172. }
  173. public int getCategoryChance()
  174. {
  175. return _CategoryChance;
  176. }
  177. public int getAugmentId()
  178. {
  179. return _AugmentId;
  180. }
  181. public float getAugmentChance()
  182. {
  183. return _AugmentChance;
  184. }
  185. }
  186. private final void load()
  187. {
  188. // Load stats
  189. DocumentBuilderFactory factory2 = DocumentBuilderFactory.newInstance();
  190. factory2.setValidating(false);
  191. factory2.setIgnoringComments(true);
  192. // Load the skillmap
  193. // Note: the skillmap data is only used when generating new augmentations
  194. // the client expects a different id in order to display the skill in the
  195. // items description...
  196. if (!Config.RETAIL_LIKE_AUGMENTATION)
  197. {
  198. try
  199. {
  200. int badAugmantData = 0;
  201. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  202. factory.setValidating(false);
  203. factory.setIgnoringComments(true);
  204. File file = new File(Config.DATAPACK_ROOT + "/data/stats/augmentation/augmentation_skillmap.xml");
  205. if (!file.exists())
  206. {
  207. _log.log(Level.WARNING, getClass().getSimpleName() + ": ERROR The augmentation skillmap file is missing.");
  208. return;
  209. }
  210. Document doc = factory.newDocumentBuilder().parse(file);
  211. for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
  212. {
  213. if ("list".equalsIgnoreCase(n.getNodeName()))
  214. {
  215. for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
  216. {
  217. if ("augmentation".equalsIgnoreCase(d.getNodeName()))
  218. {
  219. NamedNodeMap attrs = d.getAttributes();
  220. int skillId = 0, augmentationId = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
  221. int skillLvL = 0;
  222. String type = "blue";
  223. for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
  224. {
  225. if ("skillId".equalsIgnoreCase(cd.getNodeName()))
  226. {
  227. attrs = cd.getAttributes();
  228. skillId = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
  229. }
  230. else if ("skillLevel".equalsIgnoreCase(cd.getNodeName()))
  231. {
  232. attrs = cd.getAttributes();
  233. skillLvL = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
  234. }
  235. else if ("type".equalsIgnoreCase(cd.getNodeName()))
  236. {
  237. attrs = cd.getAttributes();
  238. type = attrs.getNamedItem("val").getNodeValue();
  239. }
  240. }
  241. if (skillId == 0)
  242. {
  243. badAugmantData++;
  244. continue;
  245. }
  246. else if (skillLvL == 0)
  247. {
  248. badAugmantData++;
  249. continue;
  250. }
  251. int k = (augmentationId - BLUE_START) / SKILLS_BLOCKSIZE;
  252. if (type.equalsIgnoreCase("blue"))
  253. {
  254. _blueSkills.get(k).add(augmentationId);
  255. }
  256. else if (type.equalsIgnoreCase("purple"))
  257. {
  258. _purpleSkills.get(k).add(augmentationId);
  259. }
  260. else
  261. {
  262. _redSkills.get(k).add(augmentationId);
  263. }
  264. _allSkills.put(augmentationId, new SkillHolder(skillId, skillLvL));
  265. }
  266. }
  267. }
  268. }
  269. if (badAugmantData != 0)
  270. {
  271. _log.info(getClass().getSimpleName() + ": " + badAugmantData + " bad skill(s) were skipped.");
  272. }
  273. }
  274. catch (Exception e)
  275. {
  276. _log.log(Level.WARNING, getClass().getSimpleName() + ": ERROR parsing augmentation_skillmap.xml.", e);
  277. return;
  278. }
  279. }
  280. else
  281. {
  282. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  283. factory.setValidating(false);
  284. factory.setIgnoringComments(true);
  285. File aFile = new File(Config.DATAPACK_ROOT + "/data/stats/augmentation/retailchances.xml");
  286. if (aFile.exists())
  287. {
  288. Document aDoc = null;
  289. try
  290. {
  291. aDoc = factory.newDocumentBuilder().parse(aFile);
  292. }
  293. catch (Exception e)
  294. {
  295. e.printStackTrace();
  296. return;
  297. }
  298. String aWeaponType = null;
  299. int aStoneId = 0;
  300. int aVariationId = 0;
  301. int aCategoryChance = 0;
  302. int aAugmentId = 0;
  303. float aAugmentChance = 0;
  304. for (Node l = aDoc.getFirstChild(); l != null; l = l.getNextSibling())
  305. {
  306. if (l.getNodeName().equals("list"))
  307. {
  308. NamedNodeMap aNodeAttributes = null;
  309. // System.out.println("We're going through the list now.");
  310. for (Node n = l.getFirstChild(); n != null; n = n.getNextSibling())
  311. {
  312. if (n.getNodeName().equals("weapon"))
  313. {
  314. aNodeAttributes = n.getAttributes();
  315. aWeaponType = aNodeAttributes.getNamedItem("type").getNodeValue();
  316. // System.out.println("Now showing Augmentations for " + aWeaponType + " Weapons.");
  317. for (Node c = n.getFirstChild(); c != null; c = c.getNextSibling())
  318. {
  319. if (c.getNodeName().equals("stone"))
  320. {
  321. aNodeAttributes = c.getAttributes();
  322. aStoneId = Integer.parseInt(aNodeAttributes.getNamedItem("id").getNodeValue());
  323. for (Node v = c.getFirstChild(); v != null; v = v.getNextSibling())
  324. {
  325. if (v.getNodeName().equals("variation"))
  326. {
  327. aNodeAttributes = v.getAttributes();
  328. aVariationId = Integer.parseInt(aNodeAttributes.getNamedItem("id").getNodeValue());
  329. for (Node j = v.getFirstChild(); j != null; j = j.getNextSibling())
  330. {
  331. if (j.getNodeName().equals("category"))
  332. {
  333. aNodeAttributes = j.getAttributes();
  334. aCategoryChance = Integer.parseInt(aNodeAttributes.getNamedItem("probability").getNodeValue());
  335. // System.out.println("Stone Id: " + aStoneId + ", Variation Id: " + aVariationId + ", Category Chances: " + aCategoryChance);
  336. for (Node e = j.getFirstChild(); e != null; e = e.getNextSibling())
  337. {
  338. if (e.getNodeName().equals("augment"))
  339. {
  340. aNodeAttributes = e.getAttributes();
  341. aAugmentId = Integer.parseInt(aNodeAttributes.getNamedItem("id").getNodeValue());
  342. aAugmentChance = Float.parseFloat(aNodeAttributes.getNamedItem("chance").getNodeValue());
  343. _augmentationChances.add(new AugmentationChance(aWeaponType, aStoneId, aVariationId, aCategoryChance, aAugmentId, aAugmentChance));
  344. }
  345. }
  346. }
  347. }
  348. }
  349. }
  350. }
  351. }
  352. }
  353. }
  354. }
  355. }
  356. }
  357. else
  358. {
  359. _log.log(Level.WARNING, getClass().getSimpleName() + ": ERROR The retailchances.xml data file is missing.");
  360. return;
  361. }
  362. }
  363. if (Config.RETAIL_LIKE_AUGMENTATION_ACCESSORY)
  364. {
  365. DocumentBuilderFactory factory3 = DocumentBuilderFactory.newInstance();
  366. factory3.setValidating(false);
  367. factory3.setIgnoringComments(true);
  368. File aFile3 = new File(Config.DATAPACK_ROOT + "/data/stats/augmentation/retailchances_accessory.xml");
  369. if (aFile3.exists())
  370. {
  371. Document aDoc = null;
  372. try
  373. {
  374. aDoc = factory3.newDocumentBuilder().parse(aFile3);
  375. }
  376. catch (Exception e)
  377. {
  378. e.printStackTrace();
  379. return;
  380. }
  381. String aWeaponType = null;
  382. int aStoneId = 0;
  383. int aVariationId = 0;
  384. int aCategoryChance = 0;
  385. int aAugmentId = 0;
  386. float aAugmentChance = 0;
  387. for (Node l = aDoc.getFirstChild(); l != null; l = l.getNextSibling())
  388. {
  389. if (l.getNodeName().equals("list"))
  390. {
  391. NamedNodeMap aNodeAttributes = null;
  392. for (Node n = l.getFirstChild(); n != null; n = n.getNextSibling())
  393. {
  394. if (n.getNodeName().equals("weapon"))
  395. {
  396. aNodeAttributes = n.getAttributes();
  397. aWeaponType = aNodeAttributes.getNamedItem("type").getNodeValue();
  398. for (Node c = n.getFirstChild(); c != null; c = c.getNextSibling())
  399. {
  400. if (c.getNodeName().equals("stone"))
  401. {
  402. aNodeAttributes = c.getAttributes();
  403. aStoneId = Integer.parseInt(aNodeAttributes.getNamedItem("id").getNodeValue());
  404. for (Node v = c.getFirstChild(); v != null; v = v.getNextSibling())
  405. {
  406. if (v.getNodeName().equals("variation"))
  407. {
  408. aNodeAttributes = v.getAttributes();
  409. aVariationId = Integer.parseInt(aNodeAttributes.getNamedItem("id").getNodeValue());
  410. for (Node j = v.getFirstChild(); j != null; j = j.getNextSibling())
  411. {
  412. if (j.getNodeName().equals("category"))
  413. {
  414. aNodeAttributes = j.getAttributes();
  415. aCategoryChance = Integer.parseInt(aNodeAttributes.getNamedItem("probability").getNodeValue());
  416. for (Node e = j.getFirstChild(); e != null; e = e.getNextSibling())
  417. {
  418. if (e.getNodeName().equals("augment"))
  419. {
  420. aNodeAttributes = e.getAttributes();
  421. aAugmentId = Integer.parseInt(aNodeAttributes.getNamedItem("id").getNodeValue());
  422. aAugmentChance = Float.parseFloat(aNodeAttributes.getNamedItem("chance").getNodeValue());
  423. _augmentationChancesAcc.add(new augmentationChanceAcc(aWeaponType, aStoneId, aVariationId, aCategoryChance, aAugmentId, aAugmentChance));
  424. }
  425. }
  426. }
  427. }
  428. }
  429. }
  430. }
  431. }
  432. }
  433. }
  434. }
  435. }
  436. }
  437. else
  438. {
  439. _log.log(Level.WARNING, getClass().getSimpleName() + ": ERROR The retailchances_accessory.xml data file is missing.");
  440. return;
  441. }
  442. }
  443. }
  444. /**
  445. * Generate a new random augmentation
  446. * @param lifeStoneLevel
  447. * @param lifeStoneGrade
  448. * @param bodyPart
  449. * @param lifeStoneId
  450. * @param targetItem
  451. * @return
  452. */
  453. public L2Augmentation generateRandomAugmentation(int lifeStoneLevel, int lifeStoneGrade, int bodyPart, int lifeStoneId, L2ItemInstance targetItem)
  454. {
  455. switch (bodyPart)
  456. {
  457. case L2Item.SLOT_LR_FINGER:
  458. case L2Item.SLOT_LR_EAR:
  459. case L2Item.SLOT_NECK:
  460. return generateRandomAccessoryAugmentation(lifeStoneLevel, bodyPart, lifeStoneId);
  461. default:
  462. return generateRandomWeaponAugmentation(lifeStoneLevel, lifeStoneGrade, lifeStoneId, targetItem);
  463. }
  464. }
  465. private L2Augmentation generateRandomWeaponAugmentation(int lifeStoneLevel, int lifeStoneGrade, int lifeStoneId, L2ItemInstance item)
  466. {
  467. int stat12 = 0;
  468. int stat34 = 0;
  469. if (Config.RETAIL_LIKE_AUGMENTATION)
  470. {
  471. if (((L2Weapon) item.getItem()).isMagicWeapon())
  472. {
  473. List<AugmentationChance> _selectedChances12 = new ArrayList<>();
  474. List<AugmentationChance> _selectedChances34 = new ArrayList<>();
  475. for (AugmentationChance ac : _augmentationChances)
  476. {
  477. if (ac.getWeaponType().equals("mage") && (ac.getStoneId() == lifeStoneId))
  478. {
  479. if (ac.getVariationId() == 1)
  480. {
  481. _selectedChances12.add(ac);
  482. }
  483. else
  484. {
  485. _selectedChances34.add(ac);
  486. }
  487. }
  488. }
  489. int r = Rnd.get(10000);
  490. float s = 10000;
  491. for (AugmentationChance ac : _selectedChances12)
  492. {
  493. if (s > r)
  494. {
  495. s -= (ac.getAugmentChance() * 100);
  496. stat12 = ac.getAugmentId();
  497. }
  498. }
  499. int[] gradeChance = null;
  500. switch (lifeStoneGrade)
  501. {
  502. case AbstractRefinePacket.GRADE_NONE:
  503. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
  504. break;
  505. case AbstractRefinePacket.GRADE_MID:
  506. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_MID_CHANCE;
  507. break;
  508. case AbstractRefinePacket.GRADE_HIGH:
  509. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_HIGH_CHANCE;
  510. break;
  511. case AbstractRefinePacket.GRADE_TOP:
  512. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_TOP_CHANCE;
  513. break;
  514. default:
  515. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
  516. }
  517. int c = Rnd.get(100);
  518. if (c < gradeChance[0])
  519. {
  520. c = 55;
  521. }
  522. else if (c < (gradeChance[0] + gradeChance[1]))
  523. {
  524. c = 35;
  525. }
  526. else if (c < (gradeChance[0] + gradeChance[1] + gradeChance[2]))
  527. {
  528. c = 7;
  529. }
  530. else
  531. {
  532. c = 3;
  533. }
  534. List<AugmentationChance> _selectedChances34final = new ArrayList<>();
  535. for (AugmentationChance ac : _selectedChances34)
  536. {
  537. if (ac.getCategoryChance() == c)
  538. {
  539. _selectedChances34final.add(ac);
  540. }
  541. }
  542. r = Rnd.get(10000);
  543. s = 10000;
  544. for (AugmentationChance ac : _selectedChances34final)
  545. {
  546. if (s > r)
  547. {
  548. s -= (ac.getAugmentChance() * 100);
  549. stat34 = ac.getAugmentId();
  550. }
  551. }
  552. }
  553. else
  554. {
  555. List<AugmentationChance> _selectedChances12 = new ArrayList<>();
  556. List<AugmentationChance> _selectedChances34 = new ArrayList<>();
  557. for (AugmentationChance ac : _augmentationChances)
  558. {
  559. if (ac.getWeaponType().equals("warrior") && (ac.getStoneId() == lifeStoneId))
  560. {
  561. if (ac.getVariationId() == 1)
  562. {
  563. _selectedChances12.add(ac);
  564. }
  565. else
  566. {
  567. _selectedChances34.add(ac);
  568. }
  569. }
  570. }
  571. int r = Rnd.get(10000);
  572. float s = 10000;
  573. for (AugmentationChance ac : _selectedChances12)
  574. {
  575. if (s > r)
  576. {
  577. s -= (ac.getAugmentChance() * 100);
  578. stat12 = ac.getAugmentId();
  579. }
  580. }
  581. int[] gradeChance = null;
  582. switch (lifeStoneGrade)
  583. {
  584. case AbstractRefinePacket.GRADE_NONE:
  585. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
  586. break;
  587. case AbstractRefinePacket.GRADE_MID:
  588. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_MID_CHANCE;
  589. break;
  590. case AbstractRefinePacket.GRADE_HIGH:
  591. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_HIGH_CHANCE;
  592. break;
  593. case AbstractRefinePacket.GRADE_TOP:
  594. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_TOP_CHANCE;
  595. break;
  596. default:
  597. gradeChance = Config.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
  598. }
  599. int c = Rnd.get(100);
  600. if (c < gradeChance[0])
  601. {
  602. c = 55;
  603. }
  604. else if (c < (gradeChance[0] + gradeChance[1]))
  605. {
  606. c = 35;
  607. }
  608. else if (c < (gradeChance[0] + gradeChance[1] + gradeChance[2]))
  609. {
  610. c = 7;
  611. }
  612. else
  613. {
  614. c = 3;
  615. }
  616. List<AugmentationChance> _selectedChances34final = new ArrayList<>();
  617. for (AugmentationChance ac : _selectedChances34)
  618. {
  619. if (ac.getCategoryChance() == c)
  620. {
  621. _selectedChances34final.add(ac);
  622. }
  623. }
  624. r = Rnd.get(10000);
  625. s = 10000;
  626. for (AugmentationChance ac : _selectedChances34final)
  627. {
  628. if (s > r)
  629. {
  630. s -= (ac.getAugmentChance() * 100);
  631. stat34 = ac.getAugmentId();
  632. }
  633. }
  634. }
  635. return new L2Augmentation(((stat34 << 16) + stat12));
  636. }
  637. boolean generateSkill = false;
  638. boolean generateGlow = false;
  639. // life stone level is used for stat Id and skill level, but here the max level is 9
  640. lifeStoneLevel = Math.min(lifeStoneLevel, 9);
  641. switch (lifeStoneGrade)
  642. {
  643. case AbstractRefinePacket.GRADE_NONE:
  644. if (Rnd.get(1, 100) <= Config.AUGMENTATION_NG_SKILL_CHANCE)
  645. {
  646. generateSkill = true;
  647. }
  648. if (Rnd.get(1, 100) <= Config.AUGMENTATION_NG_GLOW_CHANCE)
  649. {
  650. generateGlow = true;
  651. }
  652. break;
  653. case AbstractRefinePacket.GRADE_MID:
  654. if (Rnd.get(1, 100) <= Config.AUGMENTATION_MID_SKILL_CHANCE)
  655. {
  656. generateSkill = true;
  657. }
  658. if (Rnd.get(1, 100) <= Config.AUGMENTATION_MID_GLOW_CHANCE)
  659. {
  660. generateGlow = true;
  661. }
  662. break;
  663. case AbstractRefinePacket.GRADE_HIGH:
  664. if (Rnd.get(1, 100) <= Config.AUGMENTATION_HIGH_SKILL_CHANCE)
  665. {
  666. generateSkill = true;
  667. }
  668. if (Rnd.get(1, 100) <= Config.AUGMENTATION_HIGH_GLOW_CHANCE)
  669. {
  670. generateGlow = true;
  671. }
  672. break;
  673. case AbstractRefinePacket.GRADE_TOP:
  674. if (Rnd.get(1, 100) <= Config.AUGMENTATION_TOP_SKILL_CHANCE)
  675. {
  676. generateSkill = true;
  677. }
  678. if (Rnd.get(1, 100) <= Config.AUGMENTATION_TOP_GLOW_CHANCE)
  679. {
  680. generateGlow = true;
  681. }
  682. break;
  683. case AbstractRefinePacket.GRADE_ACC:
  684. if (Rnd.get(1, 100) <= Config.AUGMENTATION_ACC_SKILL_CHANCE)
  685. {
  686. generateSkill = true;
  687. }
  688. }
  689. if (!generateSkill && (Rnd.get(1, 100) <= Config.AUGMENTATION_BASESTAT_CHANCE))
  690. {
  691. stat34 = Rnd.get(BASESTAT_STR, BASESTAT_MEN);
  692. }
  693. // Second: decide which grade the augmentation result is going to have:
  694. // 0:yellow, 1:blue, 2:purple, 3:red
  695. // The chances used here are most likely custom,
  696. // what's known is: you can't have yellow with skill(or baseStatModifier)
  697. // noGrade stone can not have glow, mid only with skill, high has a chance(custom), top allways glow
  698. int resultColor = Rnd.get(0, 100);
  699. if ((stat34 == 0) && !generateSkill)
  700. {
  701. if (resultColor <= ((15 * lifeStoneGrade) + 40))
  702. {
  703. resultColor = 1;
  704. }
  705. else
  706. {
  707. resultColor = 0;
  708. }
  709. }
  710. else
  711. {
  712. if ((resultColor <= ((10 * lifeStoneGrade) + 5)) || (stat34 != 0))
  713. {
  714. resultColor = 3;
  715. }
  716. else if (resultColor <= ((10 * lifeStoneGrade) + 10))
  717. {
  718. resultColor = 1;
  719. }
  720. else
  721. {
  722. resultColor = 2;
  723. }
  724. }
  725. // generate a skill if necessary
  726. if (generateSkill)
  727. {
  728. switch (resultColor)
  729. {
  730. case 1: // blue skill
  731. stat34 = _blueSkills.get(lifeStoneLevel).get(Rnd.get(0, _blueSkills.get(lifeStoneLevel).size() - 1));
  732. break;
  733. case 2: // purple skill
  734. stat34 = _purpleSkills.get(lifeStoneLevel).get(Rnd.get(0, _purpleSkills.get(lifeStoneLevel).size() - 1));
  735. break;
  736. case 3: // red skill
  737. stat34 = _redSkills.get(lifeStoneLevel).get(Rnd.get(0, _redSkills.get(lifeStoneLevel).size() - 1));
  738. break;
  739. }
  740. }
  741. // Third: Calculate the subblock offset for the chosen color,
  742. // and the level of the lifeStone
  743. // from large number of retail augmentations:
  744. // no skill part
  745. // Id for stat12:
  746. // A:1-910 B:911-1820 C:1821-2730 D:2731-3640 E:3641-4550 F:4551-5460 G:5461-6370 H:6371-7280
  747. // Id for stat34(this defines the color):
  748. // I:7281-8190(yellow) K:8191-9100(blue) L:10921-11830(yellow) M:11831-12740(blue)
  749. // you can combine I-K with A-D and L-M with E-H
  750. // using C-D or G-H Id you will get a glow effect
  751. // there seems no correlation in which grade use which Id except for the glowing restriction
  752. // skill part
  753. // Id for stat12:
  754. // same for no skill part
  755. // A same as E, B same as F, C same as G, D same as H
  756. // A - no glow, no grade LS
  757. // B - weak glow, mid grade LS?
  758. // C - glow, high grade LS?
  759. // D - strong glow, top grade LS?
  760. // is neither a skill nor basestat used for stat34? then generate a normal stat
  761. int offset;
  762. if (stat34 == 0)
  763. {
  764. int temp = Rnd.get(2, 3);
  765. int colorOffset = (resultColor * (10 * STAT_SUBBLOCKSIZE)) + (temp * STAT_BLOCKSIZE) + 1;
  766. offset = (lifeStoneLevel * STAT_SUBBLOCKSIZE) + colorOffset;
  767. stat34 = Rnd.get(offset, (offset + STAT_SUBBLOCKSIZE) - 1);
  768. if (generateGlow && (lifeStoneGrade >= 2))
  769. {
  770. offset = (lifeStoneLevel * STAT_SUBBLOCKSIZE) + ((temp - 2) * STAT_BLOCKSIZE) + (lifeStoneGrade * (10 * STAT_SUBBLOCKSIZE)) + 1;
  771. }
  772. else
  773. {
  774. offset = (lifeStoneLevel * STAT_SUBBLOCKSIZE) + ((temp - 2) * STAT_BLOCKSIZE) + (Rnd.get(0, 1) * (10 * STAT_SUBBLOCKSIZE)) + 1;
  775. }
  776. }
  777. else
  778. {
  779. if (!generateGlow)
  780. {
  781. offset = (lifeStoneLevel * STAT_SUBBLOCKSIZE) + (Rnd.get(0, 1) * STAT_BLOCKSIZE) + 1;
  782. }
  783. else
  784. {
  785. offset = (lifeStoneLevel * STAT_SUBBLOCKSIZE) + (Rnd.get(0, 1) * STAT_BLOCKSIZE) + (((lifeStoneGrade + resultColor) / 2) * (10 * STAT_SUBBLOCKSIZE)) + 1;
  786. }
  787. }
  788. stat12 = Rnd.get(offset, (offset + STAT_SUBBLOCKSIZE) - 1);
  789. if (Config.DEBUG)
  790. {
  791. _log.info(getClass().getSimpleName() + ": Augmentation success: stat12=" + stat12 + "; stat34=" + stat34 + "; resultColor=" + resultColor + "; level=" + lifeStoneLevel + "; grade=" + lifeStoneGrade);
  792. }
  793. return new L2Augmentation(((stat34 << 16) + stat12));
  794. }
  795. private L2Augmentation generateRandomAccessoryAugmentation(int lifeStoneLevel, int bodyPart, int lifeStoneId)
  796. {
  797. int stat12 = 0;
  798. int stat34 = 0;
  799. if (Config.RETAIL_LIKE_AUGMENTATION_ACCESSORY)
  800. {
  801. List<augmentationChanceAcc> _selectedChances12 = new ArrayList<>();
  802. List<augmentationChanceAcc> _selectedChances34 = new ArrayList<>();
  803. for (augmentationChanceAcc ac : _augmentationChancesAcc)
  804. {
  805. if (ac.getWeaponType().equals("warrior") && (ac.getStoneId() == lifeStoneId))
  806. {
  807. if (ac.getVariationId() == 1)
  808. {
  809. _selectedChances12.add(ac);
  810. }
  811. else
  812. {
  813. _selectedChances34.add(ac);
  814. }
  815. }
  816. }
  817. int r = Rnd.get(10000);
  818. float s = 10000;
  819. for (augmentationChanceAcc ac : _selectedChances12)
  820. {
  821. if (s > r)
  822. {
  823. s -= (ac.getAugmentChance() * 100);
  824. stat12 = ac.getAugmentId();
  825. }
  826. }
  827. int c = Rnd.get(100);
  828. if (c < 55)
  829. {
  830. c = 55;
  831. }
  832. else if (c < 90)
  833. {
  834. c = 35;
  835. }
  836. else if (c < 99)
  837. {
  838. c = 9;
  839. }
  840. else
  841. {
  842. c = 1;
  843. }
  844. List<augmentationChanceAcc> _selectedChances34final = new ArrayList<>();
  845. for (augmentationChanceAcc ac : _selectedChances34)
  846. {
  847. if (ac.getCategoryChance() == c)
  848. {
  849. _selectedChances34final.add(ac);
  850. }
  851. }
  852. r = Rnd.get(10000);
  853. s = 10000;
  854. for (augmentationChanceAcc ac : _selectedChances34final)
  855. {
  856. if (s > r)
  857. {
  858. s -= (ac.getAugmentChance() * 100);
  859. stat34 = ac.getAugmentId();
  860. }
  861. }
  862. return new L2Augmentation(((stat34 << 16) + stat12));
  863. }
  864. lifeStoneLevel = Math.min(lifeStoneLevel, 9);
  865. int base = 0;
  866. int skillsLength = 0;
  867. switch (bodyPart)
  868. {
  869. case L2Item.SLOT_LR_FINGER:
  870. base = ACC_RING_START + (ACC_RING_BLOCKSIZE * lifeStoneLevel);
  871. skillsLength = ACC_RING_SKILLS;
  872. break;
  873. case L2Item.SLOT_LR_EAR:
  874. base = ACC_EAR_START + (ACC_EAR_BLOCKSIZE * lifeStoneLevel);
  875. skillsLength = ACC_EAR_SKILLS;
  876. break;
  877. case L2Item.SLOT_NECK:
  878. base = ACC_NECK_START + (ACC_NECK_BLOCKSIZE * lifeStoneLevel);
  879. skillsLength = ACC_NECK_SKILLS;
  880. break;
  881. default:
  882. return null;
  883. }
  884. int resultColor = Rnd.get(0, 3);
  885. // first augmentation (stats only)
  886. stat12 = Rnd.get(ACC_STAT_SUBBLOCKSIZE);
  887. Options op = null;
  888. if (Rnd.get(1, 100) <= Config.AUGMENTATION_ACC_SKILL_CHANCE)
  889. {
  890. // second augmentation (skill)
  891. stat34 = base + Rnd.get(skillsLength);
  892. op = OptionsData.getInstance().getOptions(stat34);
  893. }
  894. if ((op == null) || (!op.hasActiveSkill() && !op.hasPassiveSkill() && !op.hasActivationSkills()))
  895. {
  896. // second augmentation (stats)
  897. // calculating any different from stat12 value inside sub-block
  898. // starting from next and wrapping over using remainder
  899. stat34 = (stat12 + 1 + Rnd.get(ACC_STAT_SUBBLOCKSIZE - 1)) % ACC_STAT_SUBBLOCKSIZE;
  900. // this is a stats - skipping skills
  901. stat34 = base + skillsLength + (ACC_STAT_SUBBLOCKSIZE * resultColor) + stat34;
  902. }
  903. // stat12 has stats only
  904. stat12 = base + skillsLength + (ACC_STAT_SUBBLOCKSIZE * resultColor) + stat12;
  905. if (Config.DEBUG)
  906. {
  907. _log.info(getClass().getSimpleName() + ": Accessory augmentation success: stat12=" + stat12 + "; stat34=" + stat34 + "; level=" + lifeStoneLevel);
  908. }
  909. return new L2Augmentation(((stat34 << 16) + stat12));
  910. }
  911. public static final AugmentationData getInstance()
  912. {
  913. return SingletonHolder._instance;
  914. }
  915. private static class SingletonHolder
  916. {
  917. protected static final AugmentationData _instance = new AugmentationData();
  918. }
  919. }