SkillTreesData.java 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  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.Arrays;
  23. import java.util.Collection;
  24. import java.util.HashMap;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Map.Entry;
  28. import java.util.Set;
  29. import org.w3c.dom.NamedNodeMap;
  30. import org.w3c.dom.Node;
  31. import com.l2jserver.Config;
  32. import com.l2jserver.gameserver.engines.DocumentParser;
  33. import com.l2jserver.gameserver.model.L2Clan;
  34. import com.l2jserver.gameserver.model.L2SkillLearn;
  35. import com.l2jserver.gameserver.model.L2SkillLearn.SubClassData;
  36. import com.l2jserver.gameserver.model.StatsSet;
  37. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  38. import com.l2jserver.gameserver.model.base.AcquireSkillType;
  39. import com.l2jserver.gameserver.model.base.ClassId;
  40. import com.l2jserver.gameserver.model.base.Race;
  41. import com.l2jserver.gameserver.model.base.SocialClass;
  42. import com.l2jserver.gameserver.model.base.SubClass;
  43. import com.l2jserver.gameserver.model.holders.ItemHolder;
  44. import com.l2jserver.gameserver.model.holders.PlayerSkillHolder;
  45. import com.l2jserver.gameserver.model.holders.SkillHolder;
  46. import com.l2jserver.gameserver.model.interfaces.ISkillsHolder;
  47. import com.l2jserver.gameserver.model.skills.L2Skill;
  48. import gnu.trove.map.hash.TIntObjectHashMap;
  49. /**
  50. * This class loads and manage the characters and pledges skills trees.<br>
  51. * Here can be found the following skill trees:<br>
  52. * <ul>
  53. * <li>Class skill trees: player skill trees for each class.</li>
  54. * <li>Transfer skill trees: player skill trees for each healer class.</lI>
  55. * <li>Collect skill tree: player skill tree for Gracia related skills.</li>
  56. * <li>Fishing skill tree: player skill tree for fishing related skills.</li>
  57. * <li>Transform skill tree: player skill tree for transformation related skills.</li>
  58. * <li>Sub-Class skill tree: player skill tree for sub-class related skills.</li>
  59. * <li>Noble skill tree: player skill tree for noblesse related skills.</li>
  60. * <li>Hero skill tree: player skill tree for heroes related skills.</li>
  61. * <li>GM skill tree: player skill tree for Game Master related skills.</li>
  62. * <li>Common skill tree: custom skill tree for players, skills in this skill tree will be available for all players.</li>
  63. * <li>Pledge skill tree: clan skill tree for main clan.</li>
  64. * <li>Sub-Pledge skill tree: clan skill tree for sub-clans.</li>
  65. * </ul>
  66. * For easy customization of player class skill trees, the parent Id of each class is taken from the XML data, this means you can use a different class parent Id than in the normal game play, for example all 3rd class dagger users will have Treasure Hunter skills as 1st and 2nd class skills.<br>
  67. * For XML schema please refer to skillTrees.xsd in datapack in xsd folder and for parameters documentation refer to documentation.txt in skillTrees folder.<br>
  68. * @author Zoey76
  69. */
  70. public final class SkillTreesData extends DocumentParser
  71. {
  72. // ClassId, FastMap of Skill Hash Code, L2SkillLearn
  73. private static final Map<ClassId, Map<Integer, L2SkillLearn>> _classSkillTrees = new HashMap<>();
  74. private static final Map<ClassId, Map<Integer, L2SkillLearn>> _transferSkillTrees = new HashMap<>();
  75. // Skill Hash Code, L2SkillLearn
  76. private static final Map<Integer, L2SkillLearn> _collectSkillTree = new HashMap<>();
  77. private static final Map<Integer, L2SkillLearn> _fishingSkillTree = new HashMap<>();
  78. private static final Map<Integer, L2SkillLearn> _pledgeSkillTree = new HashMap<>();
  79. private static final Map<Integer, L2SkillLearn> _subClassSkillTree = new HashMap<>();
  80. private static final Map<Integer, L2SkillLearn> _subPledgeSkillTree = new HashMap<>();
  81. private static final Map<Integer, L2SkillLearn> _transformSkillTree = new HashMap<>();
  82. private static final Map<Integer, L2SkillLearn> _commonSkillTree = new HashMap<>();
  83. // Other skill trees
  84. private static final Map<Integer, L2SkillLearn> _nobleSkillTree = new HashMap<>();
  85. private static final Map<Integer, L2SkillLearn> _heroSkillTree = new HashMap<>();
  86. private static final Map<Integer, L2SkillLearn> _gameMasterSkillTree = new HashMap<>();
  87. private static final Map<Integer, L2SkillLearn> _gameMasterAuraSkillTree = new HashMap<>();
  88. // Checker, sorted arrays of hash codes
  89. private TIntObjectHashMap<int[]> _skillsByClassIdHashCodes; // Occupation skills
  90. private TIntObjectHashMap<int[]> _skillsByRaceHashCodes; // Race-specific Transformations
  91. private int[] _allSkillsHashCodes; // Fishing, Collection, Transformations, Common Skills.
  92. private boolean _loading = true;
  93. /**
  94. * Parent class IDs are read from XML and stored in this map, to allow easy customization.
  95. */
  96. private static final Map<ClassId, ClassId> _parentClassMap = new HashMap<>();
  97. /**
  98. * Instantiates a new skill trees data.
  99. */
  100. protected SkillTreesData()
  101. {
  102. load();
  103. }
  104. @Override
  105. public void load()
  106. {
  107. _loading = true;
  108. _classSkillTrees.clear();
  109. _collectSkillTree.clear();
  110. _fishingSkillTree.clear();
  111. _pledgeSkillTree.clear();
  112. _subClassSkillTree.clear();
  113. _subPledgeSkillTree.clear();
  114. _transferSkillTrees.clear();
  115. _transformSkillTree.clear();
  116. _nobleSkillTree.clear();
  117. _heroSkillTree.clear();
  118. _gameMasterSkillTree.clear();
  119. _gameMasterAuraSkillTree.clear();
  120. // Load files.
  121. parseDirectory(new File(Config.DATAPACK_ROOT, "data/skillTrees/"));
  122. // Generate check arrays.
  123. generateCheckArrays();
  124. _loading = false;
  125. // Logs a report with skill trees info.
  126. report();
  127. }
  128. /**
  129. * Parse a skill tree file and store it into the correct skill tree.
  130. */
  131. @Override
  132. protected void parseDocument()
  133. {
  134. NamedNodeMap attrs;
  135. Node attr;
  136. String type = null;
  137. int cId = -1;
  138. int parentClassId = -1;
  139. ClassId classId = null;
  140. for (Node n = getCurrentDocument().getFirstChild(); n != null; n = n.getNextSibling())
  141. {
  142. if ("list".equalsIgnoreCase(n.getNodeName()))
  143. {
  144. for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
  145. {
  146. if ("skillTree".equalsIgnoreCase(d.getNodeName()))
  147. {
  148. final Map<Integer, L2SkillLearn> classSkillTree = new HashMap<>();
  149. final Map<Integer, L2SkillLearn> trasferSkillTree = new HashMap<>();
  150. type = d.getAttributes().getNamedItem("type").getNodeValue();
  151. attr = d.getAttributes().getNamedItem("classId");
  152. if (attr != null)
  153. {
  154. cId = Integer.parseInt(attr.getNodeValue());
  155. classId = ClassId.values()[cId];
  156. }
  157. else
  158. {
  159. cId = -1;
  160. }
  161. attr = d.getAttributes().getNamedItem("parentClassId");
  162. if (attr != null)
  163. {
  164. parentClassId = Integer.parseInt(attr.getNodeValue());
  165. if ((cId > -1) && (cId != parentClassId) && (parentClassId > -1) && !_parentClassMap.containsKey(classId))
  166. {
  167. _parentClassMap.put(classId, ClassId.values()[parentClassId]);
  168. }
  169. }
  170. for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
  171. {
  172. if ("skill".equalsIgnoreCase(c.getNodeName()))
  173. {
  174. final StatsSet learnSkillSet = new StatsSet();
  175. attrs = c.getAttributes();
  176. for (int i = 0; i < attrs.getLength(); i++)
  177. {
  178. attr = attrs.item(i);
  179. learnSkillSet.set(attr.getNodeName(), attr.getNodeValue());
  180. }
  181. final L2SkillLearn skillLearn = new L2SkillLearn(learnSkillSet);
  182. for (Node b = c.getFirstChild(); b != null; b = b.getNextSibling())
  183. {
  184. attrs = b.getAttributes();
  185. switch (b.getNodeName())
  186. {
  187. case "item":
  188. skillLearn.addRequiredItem(new ItemHolder(parseInt(attrs, "id"), parseInt(attrs, "count")));
  189. break;
  190. case "preRequisiteSkill":
  191. skillLearn.addPreReqSkill(new SkillHolder(parseInt(attrs, "id"), parseInt(attrs, "lvl")));
  192. break;
  193. case "race":
  194. skillLearn.addRace(Race.valueOf(b.getTextContent()));
  195. break;
  196. case "residenceId":
  197. skillLearn.addResidenceId(Integer.valueOf(b.getTextContent()));
  198. break;
  199. case "socialClass":
  200. skillLearn.setSocialClass(Enum.valueOf(SocialClass.class, b.getTextContent()));
  201. break;
  202. case "subClassConditions":
  203. skillLearn.addSubclassConditions(parseInt(attrs, "slot"), parseInt(attrs, "lvl"));
  204. break;
  205. }
  206. }
  207. final int skillHashCode = SkillTable.getSkillHashCode(skillLearn.getSkillId(), skillLearn.getSkillLevel());
  208. switch (type)
  209. {
  210. case "classSkillTree":
  211. {
  212. if (cId != -1)
  213. {
  214. classSkillTree.put(skillHashCode, skillLearn);
  215. }
  216. else
  217. {
  218. _commonSkillTree.put(skillHashCode, skillLearn);
  219. }
  220. break;
  221. }
  222. case "transferSkillTree":
  223. {
  224. trasferSkillTree.put(skillHashCode, skillLearn);
  225. break;
  226. }
  227. case "collectSkillTree":
  228. {
  229. _collectSkillTree.put(skillHashCode, skillLearn);
  230. break;
  231. }
  232. case "fishingSkillTree":
  233. {
  234. _fishingSkillTree.put(skillHashCode, skillLearn);
  235. break;
  236. }
  237. case "pledgeSkillTree":
  238. {
  239. _pledgeSkillTree.put(skillHashCode, skillLearn);
  240. break;
  241. }
  242. case "subClassSkillTree":
  243. {
  244. _subClassSkillTree.put(skillHashCode, skillLearn);
  245. break;
  246. }
  247. case "subPledgeSkillTree":
  248. {
  249. _subPledgeSkillTree.put(skillHashCode, skillLearn);
  250. break;
  251. }
  252. case "transformSkillTree":
  253. {
  254. _transformSkillTree.put(skillHashCode, skillLearn);
  255. break;
  256. }
  257. case "nobleSkillTree":
  258. {
  259. _nobleSkillTree.put(skillHashCode, skillLearn);
  260. break;
  261. }
  262. case "heroSkillTree":
  263. {
  264. _heroSkillTree.put(skillHashCode, skillLearn);
  265. break;
  266. }
  267. case "gameMasterSkillTree":
  268. {
  269. _gameMasterSkillTree.put(skillHashCode, skillLearn);
  270. break;
  271. }
  272. case "gameMasterAuraSkillTree":
  273. {
  274. _gameMasterAuraSkillTree.put(skillHashCode, skillLearn);
  275. break;
  276. }
  277. default:
  278. {
  279. _log.warning(getClass().getSimpleName() + ": Unknown Skill Tree type: " + type + "!");
  280. }
  281. }
  282. }
  283. }
  284. if (type.equals("transferSkillTree"))
  285. {
  286. _transferSkillTrees.put(classId, trasferSkillTree);
  287. }
  288. else if (type.equals("classSkillTree") && (cId > -1))
  289. {
  290. if (!_classSkillTrees.containsKey(classId))
  291. {
  292. _classSkillTrees.put(classId, classSkillTree);
  293. }
  294. else
  295. {
  296. _classSkillTrees.get(classId).putAll(classSkillTree);
  297. }
  298. }
  299. }
  300. }
  301. }
  302. }
  303. }
  304. /**
  305. * Method to get the complete skill tree for a given class id.<br>
  306. * Include all skills common to all classes.<br>
  307. * Includes all parent skill trees.
  308. * @param classId the class skill tree ID.
  309. * @return the complete Class Skill Tree including skill trees from parent class for a given {@code classId}.
  310. */
  311. public Map<Integer, L2SkillLearn> getCompleteClassSkillTree(ClassId classId)
  312. {
  313. final Map<Integer, L2SkillLearn> skillTree = new HashMap<>();
  314. // Add all skills that belong to all classes.
  315. skillTree.putAll(_commonSkillTree);
  316. while ((classId != null) && (_classSkillTrees.get(classId) != null))
  317. {
  318. skillTree.putAll(_classSkillTrees.get(classId));
  319. classId = _parentClassMap.get(classId);
  320. }
  321. return skillTree;
  322. }
  323. /**
  324. * Gets the transfer skill tree.<br>
  325. * If new classes are implemented over 3rd class, we use a recursive call.
  326. * @param classId the transfer skill tree ID.
  327. * @return the complete Transfer Skill Tree for a given {@code classId}.
  328. */
  329. public Map<Integer, L2SkillLearn> getTransferSkillTree(ClassId classId)
  330. {
  331. if (classId.level() >= 3)
  332. {
  333. return getTransferSkillTree(classId.getParent());
  334. }
  335. return _transferSkillTrees.get(classId);
  336. }
  337. /**
  338. * Gets the common skill tree.
  339. * @return the complete Common Skill Tree.
  340. */
  341. public Map<Integer, L2SkillLearn> getCommonSkillTree()
  342. {
  343. return _commonSkillTree;
  344. }
  345. /**
  346. * Gets the collect skill tree.
  347. * @return the complete Collect Skill Tree.
  348. */
  349. public Map<Integer, L2SkillLearn> getCollectSkillTree()
  350. {
  351. return _collectSkillTree;
  352. }
  353. /**
  354. * Gets the fishing skill tree.
  355. * @return the complete Fishing Skill Tree.
  356. */
  357. public Map<Integer, L2SkillLearn> getFishingSkillTree()
  358. {
  359. return _fishingSkillTree;
  360. }
  361. /**
  362. * Gets the pledge skill tree.
  363. * @return the complete Pledge Skill Tree.
  364. */
  365. public Map<Integer, L2SkillLearn> getPledgeSkillTree()
  366. {
  367. return _pledgeSkillTree;
  368. }
  369. /**
  370. * Gets the sub class skill tree.
  371. * @return the complete Sub-Class Skill Tree.
  372. */
  373. public Map<Integer, L2SkillLearn> getSubClassSkillTree()
  374. {
  375. return _subClassSkillTree;
  376. }
  377. /**
  378. * Gets the sub pledge skill tree.
  379. * @return the complete Sub-Pledge Skill Tree.
  380. */
  381. public Map<Integer, L2SkillLearn> getSubPledgeSkillTree()
  382. {
  383. return _subPledgeSkillTree;
  384. }
  385. /**
  386. * Gets the transform skill tree.
  387. * @return the complete Transform Skill Tree.
  388. */
  389. public Map<Integer, L2SkillLearn> getTransformSkillTree()
  390. {
  391. return _transformSkillTree;
  392. }
  393. /**
  394. * Gets the noble skill tree.
  395. * @return the complete Noble Skill Tree.
  396. */
  397. public Map<Integer, L2Skill> getNobleSkillTree()
  398. {
  399. final Map<Integer, L2Skill> tree = new HashMap<>();
  400. final SkillTable st = SkillTable.getInstance();
  401. for (Entry<Integer, L2SkillLearn> e : _nobleSkillTree.entrySet())
  402. {
  403. tree.put(e.getKey(), st.getInfo(e.getValue().getSkillId(), e.getValue().getSkillLevel()));
  404. }
  405. return tree;
  406. }
  407. /**
  408. * Gets the hero skill tree.
  409. * @return the complete Hero Skill Tree.
  410. */
  411. public Map<Integer, L2Skill> getHeroSkillTree()
  412. {
  413. final Map<Integer, L2Skill> tree = new HashMap<>();
  414. final SkillTable st = SkillTable.getInstance();
  415. for (Entry<Integer, L2SkillLearn> e : _heroSkillTree.entrySet())
  416. {
  417. tree.put(e.getKey(), st.getInfo(e.getValue().getSkillId(), e.getValue().getSkillLevel()));
  418. }
  419. return tree;
  420. }
  421. /**
  422. * Gets the gM skill tree.
  423. * @return the complete Game Master Skill Tree.
  424. */
  425. public Map<Integer, L2Skill> getGMSkillTree()
  426. {
  427. final Map<Integer, L2Skill> tree = new HashMap<>();
  428. final SkillTable st = SkillTable.getInstance();
  429. for (Entry<Integer, L2SkillLearn> e : _gameMasterSkillTree.entrySet())
  430. {
  431. tree.put(e.getKey(), st.getInfo(e.getValue().getSkillId(), e.getValue().getSkillLevel()));
  432. }
  433. return tree;
  434. }
  435. /**
  436. * Gets the gM aura skill tree.
  437. * @return the complete Game Master Aura Skill Tree.
  438. */
  439. public Map<Integer, L2Skill> getGMAuraSkillTree()
  440. {
  441. final Map<Integer, L2Skill> tree = new HashMap<>();
  442. final SkillTable st = SkillTable.getInstance();
  443. for (Entry<Integer, L2SkillLearn> e : _gameMasterAuraSkillTree.entrySet())
  444. {
  445. tree.put(e.getKey(), st.getInfo(e.getValue().getSkillId(), e.getValue().getSkillLevel()));
  446. }
  447. return tree;
  448. }
  449. /**
  450. * Gets the available skills.
  451. * @param player the learning skill player.
  452. * @param classId the learning skill class ID.
  453. * @param includeByFs if {@code true} skills from Forgotten Scroll will be included.
  454. * @param includeAutoGet if {@code true} Auto-Get skills will be included.
  455. * @return all available skills for a given {@code player}, {@code classId}, {@code includeByFs} and {@code includeAutoGet}.
  456. */
  457. public List<L2SkillLearn> getAvailableSkills(L2PcInstance player, ClassId classId, boolean includeByFs, boolean includeAutoGet)
  458. {
  459. return getAvailableSkills(player, classId, includeByFs, includeAutoGet, player);
  460. }
  461. /**
  462. * Gets the available skills.
  463. * @param player the learning skill player.
  464. * @param classId the learning skill class ID.
  465. * @param includeByFs if {@code true} skills from Forgotten Scroll will be included.
  466. * @param includeAutoGet if {@code true} Auto-Get skills will be included.
  467. * @param holder
  468. * @return all available skills for a given {@code player}, {@code classId}, {@code includeByFs} and {@code includeAutoGet}.
  469. */
  470. private List<L2SkillLearn> getAvailableSkills(L2PcInstance player, ClassId classId, boolean includeByFs, boolean includeAutoGet, ISkillsHolder holder)
  471. {
  472. final List<L2SkillLearn> result = new ArrayList<>();
  473. final Map<Integer, L2SkillLearn> skills = getCompleteClassSkillTree(classId);
  474. if (skills.isEmpty())
  475. {
  476. // The Skill Tree for this class is undefined.
  477. _log.warning(getClass().getSimpleName() + ": Skilltree for class " + classId + " is not defined!");
  478. return result;
  479. }
  480. for (L2SkillLearn skill : skills.values())
  481. {
  482. if (((includeAutoGet && skill.isAutoGet()) || skill.isLearnedByNpc() || (includeByFs && skill.isLearnedByFS())) && (player.getLevel() >= skill.getGetLevel()))
  483. {
  484. final L2Skill oldSkill = holder.getKnownSkill(skill.getSkillId());
  485. if (oldSkill != null)
  486. {
  487. if (oldSkill.getLevel() == (skill.getSkillLevel() - 1))
  488. {
  489. result.add(skill);
  490. }
  491. }
  492. else if (skill.getSkillLevel() == 1)
  493. {
  494. result.add(skill);
  495. }
  496. }
  497. }
  498. return result;
  499. }
  500. public Collection<L2Skill> getAllAvailableSkills(L2PcInstance player, ClassId classId, boolean includeByFs, boolean includeAutoGet)
  501. {
  502. // Get available skills
  503. int unLearnable = 0;
  504. PlayerSkillHolder holder = new PlayerSkillHolder();
  505. List<L2SkillLearn> learnable = getAvailableSkills(player, classId, includeByFs, includeAutoGet, holder);
  506. while (learnable.size() > unLearnable)
  507. {
  508. for (L2SkillLearn s : learnable)
  509. {
  510. L2Skill sk = SkillTable.getInstance().getInfo(s.getSkillId(), s.getSkillLevel());
  511. if ((sk == null) || ((sk.getId() == L2Skill.SKILL_DIVINE_INSPIRATION) && !Config.AUTO_LEARN_DIVINE_INSPIRATION && !player.isGM()))
  512. {
  513. unLearnable++;
  514. continue;
  515. }
  516. holder.addSkill(sk);
  517. }
  518. // Get new available skills, some skills depend of previous skills to be available.
  519. learnable = getAvailableSkills(player, classId, includeByFs, includeAutoGet, holder);
  520. }
  521. return holder.getSkills().values();
  522. }
  523. /**
  524. * Gets the available auto get skills.
  525. * @param player the player requesting the Auto-Get skills.
  526. * @return all the available Auto-Get skills for a given {@code player}.
  527. */
  528. public List<L2SkillLearn> getAvailableAutoGetSkills(L2PcInstance player)
  529. {
  530. final List<L2SkillLearn> result = new ArrayList<>();
  531. final Map<Integer, L2SkillLearn> skills = getCompleteClassSkillTree(player.getClassId());
  532. if (skills.isEmpty())
  533. {
  534. // The Skill Tree for this class is undefined, so we return an empty list.
  535. _log.warning(getClass().getSimpleName() + ": Skill Tree for this class Id(" + player.getClassId() + ") is not defined!");
  536. return result;
  537. }
  538. final Race race = player.getRace();
  539. for (L2SkillLearn skill : skills.values())
  540. {
  541. if (!skill.getRaces().isEmpty() && !skill.getRaces().contains(race))
  542. {
  543. continue;
  544. }
  545. if (skill.isAutoGet() && (player.getLevel() >= skill.getGetLevel()))
  546. {
  547. final L2Skill oldSkill = player.getSkills().get(skill.getSkillId());
  548. if (oldSkill != null)
  549. {
  550. if (oldSkill.getLevel() < skill.getSkillLevel())
  551. {
  552. result.add(skill);
  553. }
  554. }
  555. else
  556. {
  557. result.add(skill);
  558. }
  559. }
  560. }
  561. return result;
  562. }
  563. /**
  564. * Dwarvens will get additional dwarven only fishing skills.
  565. * @param player the player
  566. * @return all the available Fishing skills for a given {@code player}.
  567. */
  568. public List<L2SkillLearn> getAvailableFishingSkills(L2PcInstance player)
  569. {
  570. final List<L2SkillLearn> result = new ArrayList<>();
  571. final Race playerRace = player.getRace();
  572. for (L2SkillLearn skill : _fishingSkillTree.values())
  573. {
  574. // If skill is Race specific and the player's race isn't allowed, skip it.
  575. if (!skill.getRaces().isEmpty() && !skill.getRaces().contains(playerRace))
  576. {
  577. continue;
  578. }
  579. if (skill.isLearnedByNpc() && (player.getLevel() >= skill.getGetLevel()))
  580. {
  581. final L2Skill oldSkill = player.getSkills().get(skill.getSkillId());
  582. if (oldSkill != null)
  583. {
  584. if (oldSkill.getLevel() == (skill.getSkillLevel() - 1))
  585. {
  586. result.add(skill);
  587. }
  588. }
  589. else if (skill.getSkillLevel() == 1)
  590. {
  591. result.add(skill);
  592. }
  593. }
  594. }
  595. return result;
  596. }
  597. /**
  598. * Used in Gracia continent.
  599. * @param player the collecting skill learning player.
  600. * @return all the available Collecting skills for a given {@code player}.
  601. */
  602. public List<L2SkillLearn> getAvailableCollectSkills(L2PcInstance player)
  603. {
  604. final List<L2SkillLearn> result = new ArrayList<>();
  605. for (L2SkillLearn skill : _collectSkillTree.values())
  606. {
  607. final L2Skill oldSkill = player.getSkills().get(skill.getSkillId());
  608. if (oldSkill != null)
  609. {
  610. if (oldSkill.getLevel() == (skill.getSkillLevel() - 1))
  611. {
  612. result.add(skill);
  613. }
  614. }
  615. else if (skill.getSkillLevel() == 1)
  616. {
  617. result.add(skill);
  618. }
  619. }
  620. return result;
  621. }
  622. /**
  623. * Gets the available transfer skills.
  624. * @param player the transfer skill learning player.
  625. * @return all the available Transfer skills for a given {@code player}.
  626. */
  627. public List<L2SkillLearn> getAvailableTransferSkills(L2PcInstance player)
  628. {
  629. final List<L2SkillLearn> result = new ArrayList<>();
  630. ClassId classId = player.getClassId();
  631. // If new classes are implemented over 3rd class, a different way should be implemented.
  632. if (classId.level() == 3)
  633. {
  634. classId = classId.getParent();
  635. }
  636. if (!_transferSkillTrees.containsKey(classId))
  637. {
  638. return result;
  639. }
  640. for (L2SkillLearn skill : _transferSkillTrees.get(classId).values())
  641. {
  642. // If player doesn't know this transfer skill:
  643. if (player.getKnownSkill(skill.getSkillId()) == null)
  644. {
  645. result.add(skill);
  646. }
  647. }
  648. return result;
  649. }
  650. /**
  651. * Some transformations are not available for some races.
  652. * @param player the transformation skill learning player.
  653. * @return all the available Transformation skills for a given {@code player}.
  654. */
  655. public List<L2SkillLearn> getAvailableTransformSkills(L2PcInstance player)
  656. {
  657. final List<L2SkillLearn> result = new ArrayList<>();
  658. final Race race = player.getRace();
  659. for (L2SkillLearn skill : _transformSkillTree.values())
  660. {
  661. if ((player.getLevel() >= skill.getGetLevel()) && (skill.getRaces().isEmpty() || skill.getRaces().contains(race)))
  662. {
  663. final L2Skill oldSkill = player.getSkills().get(skill.getSkillId());
  664. if (oldSkill != null)
  665. {
  666. if (oldSkill.getLevel() == (skill.getSkillLevel() - 1))
  667. {
  668. result.add(skill);
  669. }
  670. }
  671. else if (skill.getSkillLevel() == 1)
  672. {
  673. result.add(skill);
  674. }
  675. }
  676. }
  677. return result;
  678. }
  679. /**
  680. * Gets the available pledge skills.
  681. * @param clan the pledge skill learning clan.
  682. * @return all the available Pledge skills for a given {@code clan}.
  683. */
  684. public List<L2SkillLearn> getAvailablePledgeSkills(L2Clan clan)
  685. {
  686. final List<L2SkillLearn> result = new ArrayList<>();
  687. for (L2SkillLearn skill : _pledgeSkillTree.values())
  688. {
  689. if (!skill.isResidencialSkill() && (clan.getLevel() >= skill.getGetLevel()))
  690. {
  691. final L2Skill oldSkill = clan.getSkills().get(skill.getSkillId());
  692. if (oldSkill != null)
  693. {
  694. if (oldSkill.getLevel() == (skill.getSkillLevel() - 1))
  695. {
  696. result.add(skill);
  697. }
  698. }
  699. else if (skill.getSkillLevel() == 1)
  700. {
  701. result.add(skill);
  702. }
  703. }
  704. }
  705. return result;
  706. }
  707. /**
  708. * Gets the available sub pledge skills.
  709. * @param clan the sub-pledge skill learning clan.
  710. * @return all the available Sub-Pledge skills for a given {@code clan}.
  711. */
  712. public List<L2SkillLearn> getAvailableSubPledgeSkills(L2Clan clan)
  713. {
  714. final List<L2SkillLearn> result = new ArrayList<>();
  715. for (L2SkillLearn skill : _subPledgeSkillTree.values())
  716. {
  717. if ((clan.getLevel() >= skill.getGetLevel()) && clan.isLearnableSubSkill(skill.getSkillId(), skill.getSkillLevel()))
  718. {
  719. result.add(skill);
  720. }
  721. }
  722. return result;
  723. }
  724. /**
  725. * Gets the available sub class skills.
  726. * @param player the sub-class skill learning player.
  727. * @return all the available Sub-Class skills for a given {@code player}.
  728. */
  729. public List<L2SkillLearn> getAvailableSubClassSkills(L2PcInstance player)
  730. {
  731. final List<L2SkillLearn> result = new ArrayList<>();
  732. for (L2SkillLearn skill : _subClassSkillTree.values())
  733. {
  734. if (player.getLevel() >= skill.getGetLevel())
  735. {
  736. List<SubClassData> subClassConds = null;
  737. for (SubClass subClass : player.getSubClasses().values())
  738. {
  739. subClassConds = skill.getSubClassConditions();
  740. if (!subClassConds.isEmpty() && (subClass.getClassIndex() <= subClassConds.size()) && (subClass.getClassIndex() == subClassConds.get(subClass.getClassIndex() - 1).getSlot()) && (subClassConds.get(subClass.getClassIndex() - 1).getLvl() <= subClass.getLevel()))
  741. {
  742. final L2Skill oldSkill = player.getSkills().get(skill.getSkillId());
  743. if (oldSkill != null)
  744. {
  745. if (oldSkill.getLevel() == (skill.getSkillLevel() - 1))
  746. {
  747. result.add(skill);
  748. }
  749. }
  750. else if (skill.getSkillLevel() == 1)
  751. {
  752. result.add(skill);
  753. }
  754. }
  755. }
  756. }
  757. }
  758. return result;
  759. }
  760. /**
  761. * Gets the available residential skills.
  762. * @param residenceId the id of the Castle, Fort, Territory.
  763. * @return all the available Residential skills for a given {@code residenceId}.
  764. */
  765. public List<L2SkillLearn> getAvailableResidentialSkills(int residenceId)
  766. {
  767. final List<L2SkillLearn> result = new ArrayList<>();
  768. for (L2SkillLearn skill : _pledgeSkillTree.values())
  769. {
  770. if (skill.isResidencialSkill() && skill.getResidenceIds().contains(residenceId))
  771. {
  772. result.add(skill);
  773. }
  774. }
  775. return result;
  776. }
  777. /**
  778. * Just a wrapper for all skill trees.
  779. * @param skillType the skill type.
  780. * @param id the skill Id.
  781. * @param lvl the skill level.
  782. * @param player the player learning the skill.
  783. * @return the skill learn for the specified parameters.
  784. */
  785. public L2SkillLearn getSkillLearn(AcquireSkillType skillType, int id, int lvl, L2PcInstance player)
  786. {
  787. L2SkillLearn sl = null;
  788. switch (skillType)
  789. {
  790. case Class:
  791. sl = getClassSkill(id, lvl, player.getLearningClass());
  792. break;
  793. case Transform:
  794. sl = getTransformSkill(id, lvl);
  795. break;
  796. case Fishing:
  797. sl = getFishingSkill(id, lvl);
  798. break;
  799. case Pledge:
  800. sl = getPledgeSkill(id, lvl);
  801. break;
  802. case SubPledge:
  803. sl = getSubPledgeSkill(id, lvl);
  804. break;
  805. case Transfer:
  806. sl = getTransferSkill(id, lvl, player.getClassId());
  807. break;
  808. case SubClass:
  809. sl = getSubClassSkill(id, lvl);
  810. break;
  811. case Collect:
  812. sl = getCollectSkill(id, lvl);
  813. break;
  814. }
  815. return sl;
  816. }
  817. /**
  818. * Gets the transform skill.
  819. * @param id the transformation skill ID.
  820. * @param lvl the transformation skill level.
  821. * @return the transform skill from the Transform Skill Tree for a given {@code id} and {@code lvl}.
  822. */
  823. public L2SkillLearn getTransformSkill(int id, int lvl)
  824. {
  825. return _transformSkillTree.get(SkillTable.getSkillHashCode(id, lvl));
  826. }
  827. /**
  828. * Gets the class skill.
  829. * @param id the class skill ID.
  830. * @param lvl the class skill level.
  831. * @param classId the class skill tree ID.
  832. * @return the class skill from the Class Skill Trees for a given {@code classId}, {@code id} and {@code lvl}.
  833. */
  834. public L2SkillLearn getClassSkill(int id, int lvl, ClassId classId)
  835. {
  836. return getCompleteClassSkillTree(classId).get(SkillTable.getSkillHashCode(id, lvl));
  837. }
  838. /**
  839. * Gets the fishing skill.
  840. * @param id the fishing skill ID.
  841. * @param lvl the fishing skill level.
  842. * @return Fishing skill from the Fishing Skill Tree for a given {@code id} and {@code lvl}.
  843. */
  844. public L2SkillLearn getFishingSkill(int id, int lvl)
  845. {
  846. return _fishingSkillTree.get(SkillTable.getSkillHashCode(id, lvl));
  847. }
  848. /**
  849. * Gets the pledge skill.
  850. * @param id the pledge skill ID.
  851. * @param lvl the pledge skill level.
  852. * @return the pledge skill from the Pledge Skill Tree for a given {@code id} and {@code lvl}.
  853. */
  854. public L2SkillLearn getPledgeSkill(int id, int lvl)
  855. {
  856. return _pledgeSkillTree.get(SkillTable.getSkillHashCode(id, lvl));
  857. }
  858. /**
  859. * Gets the sub pledge skill.
  860. * @param id the sub-pledge skill ID.
  861. * @param lvl the sub-pledge skill level.
  862. * @return the sub-pledge skill from the Sub-Pledge Skill Tree for a given {@code id} and {@code lvl}.
  863. */
  864. public L2SkillLearn getSubPledgeSkill(int id, int lvl)
  865. {
  866. return _subPledgeSkillTree.get(SkillTable.getSkillHashCode(id, lvl));
  867. }
  868. /**
  869. * Gets the transfer skill.
  870. * @param id the transfer skill ID.
  871. * @param lvl the transfer skill level.
  872. * @param classId the transfer skill tree ID.
  873. * @return the transfer skill from the Transfer Skill Trees for a given {@code classId}, {@code id} and {@code lvl}.
  874. */
  875. public L2SkillLearn getTransferSkill(int id, int lvl, ClassId classId)
  876. {
  877. if (classId.getParent() != null)
  878. {
  879. final ClassId parentId = classId.getParent();
  880. if (_transferSkillTrees.get(parentId) != null)
  881. {
  882. return _transferSkillTrees.get(parentId).get(SkillTable.getSkillHashCode(id, lvl));
  883. }
  884. }
  885. return null;
  886. }
  887. /**
  888. * Gets the sub class skill.
  889. * @param id the sub-class skill ID.
  890. * @param lvl the sub-class skill level.
  891. * @return the sub-class skill from the Sub-Class Skill Tree for a given {@code id} and {@code lvl}.
  892. */
  893. public L2SkillLearn getSubClassSkill(int id, int lvl)
  894. {
  895. return _subClassSkillTree.get(SkillTable.getSkillHashCode(id, lvl));
  896. }
  897. /**
  898. * Gets the common skill.
  899. * @param id the common skill Id.
  900. * @param lvl the common skill level.
  901. * @return the common skill from the Common Skill Tree for a given {@code id} and {@code lvl}.
  902. */
  903. public L2SkillLearn getCommonSkill(int id, int lvl)
  904. {
  905. return _commonSkillTree.get(SkillTable.getSkillHashCode(id, lvl));
  906. }
  907. /**
  908. * Gets the collect skill.
  909. * @param id the collect skill ID.
  910. * @param lvl the collect skill level.
  911. * @return the collect skill from the Collect Skill Tree for a given {@code id} and {@code lvl}.
  912. */
  913. public L2SkillLearn getCollectSkill(int id, int lvl)
  914. {
  915. return _collectSkillTree.get(SkillTable.getSkillHashCode(id, lvl));
  916. }
  917. /**
  918. * Gets the min level for new skill.
  919. * @param player the player that requires the minimum level.
  920. * @param skillTree the skill tree to search the minimum get level.
  921. * @return the minimum level for a new skill for a given {@code player} and {@code skillTree}.
  922. */
  923. public int getMinLevelForNewSkill(L2PcInstance player, Map<Integer, L2SkillLearn> skillTree)
  924. {
  925. int minLevel = 0;
  926. if (skillTree.isEmpty())
  927. {
  928. _log.warning(getClass().getSimpleName() + ": SkillTree is not defined for getMinLevelForNewSkill!");
  929. }
  930. else
  931. {
  932. for (L2SkillLearn s : skillTree.values())
  933. {
  934. if (s.isLearnedByNpc() && (player.getLevel() < s.getGetLevel()))
  935. {
  936. if ((minLevel == 0) || (minLevel > s.getGetLevel()))
  937. {
  938. minLevel = s.getGetLevel();
  939. }
  940. }
  941. }
  942. }
  943. return minLevel;
  944. }
  945. /**
  946. * Checks if is hero skill.
  947. * @param skillId the Id of the skill to check.
  948. * @param skillLevel the level of the skill to check, if it's -1 only Id will be checked.
  949. * @return {@code true} if the skill is present in the Hero Skill Tree, {@code false} otherwise.
  950. */
  951. public boolean isHeroSkill(int skillId, int skillLevel)
  952. {
  953. if (_heroSkillTree.containsKey(SkillTable.getSkillHashCode(skillId, skillLevel)))
  954. {
  955. return true;
  956. }
  957. for (L2SkillLearn skill : _heroSkillTree.values())
  958. {
  959. if ((skill.getSkillId() == skillId) && (skillLevel == -1))
  960. {
  961. return true;
  962. }
  963. }
  964. return false;
  965. }
  966. /**
  967. * Checks if is GM skill.
  968. * @param skillId skillId the Id of the skill to check.
  969. * @param skillLevel skillLevel the level of the skill to check, if it's -1 only Id will be checked.
  970. * @return {@code true} if the skill is present in the Game Master Skill Trees, {@code false} otherwise.
  971. */
  972. public boolean isGMSkill(int skillId, int skillLevel)
  973. {
  974. final Map<Integer, L2SkillLearn> gmSkills = new HashMap<>();
  975. gmSkills.putAll(_gameMasterSkillTree);
  976. gmSkills.putAll(_gameMasterAuraSkillTree);
  977. if (gmSkills.containsKey(SkillTable.getSkillHashCode(skillId, skillLevel)))
  978. {
  979. return true;
  980. }
  981. for (L2SkillLearn skill : gmSkills.values())
  982. {
  983. if ((skill.getSkillId() == skillId) && (skillLevel == -1))
  984. {
  985. return true;
  986. }
  987. }
  988. return false;
  989. }
  990. /**
  991. * Adds the skills.
  992. * @param gmchar the player to add the Game Master skills.
  993. * @param auraSkills if {@code true} it will add "GM Aura" skills, else will add the "GM regular" skills.
  994. */
  995. public void addSkills(L2PcInstance gmchar, boolean auraSkills)
  996. {
  997. final Collection<L2SkillLearn> skills = auraSkills ? _gameMasterAuraSkillTree.values() : _gameMasterSkillTree.values();
  998. final SkillTable st = SkillTable.getInstance();
  999. for (L2SkillLearn sl : skills)
  1000. {
  1001. gmchar.addSkill(st.getInfo(sl.getSkillId(), sl.getSkillLevel()), false); // Don't Save GM skills to database
  1002. }
  1003. }
  1004. /**
  1005. * Create and store hash values for skills for easy and fast checks.
  1006. */
  1007. private void generateCheckArrays()
  1008. {
  1009. int i;
  1010. int[] array;
  1011. // Class specific skills:
  1012. Map<Integer, L2SkillLearn> tempMap;
  1013. final Set<ClassId> keySet = _classSkillTrees.keySet();
  1014. _skillsByClassIdHashCodes = new TIntObjectHashMap<>(keySet.size());
  1015. for (ClassId cls : keySet)
  1016. {
  1017. i = 0;
  1018. tempMap = getCompleteClassSkillTree(cls);
  1019. array = new int[tempMap.size()];
  1020. for (int h : tempMap.keySet())
  1021. {
  1022. array[i++] = h;
  1023. }
  1024. tempMap.clear();
  1025. Arrays.sort(array);
  1026. _skillsByClassIdHashCodes.put(cls.ordinal(), array);
  1027. }
  1028. // Race specific skills from Fishing and Transformation skill trees.
  1029. final List<Integer> list = new ArrayList<>();
  1030. _skillsByRaceHashCodes = new TIntObjectHashMap<>(Race.values().length);
  1031. for (Race r : Race.values())
  1032. {
  1033. for (L2SkillLearn s : _fishingSkillTree.values())
  1034. {
  1035. if (s.getRaces().contains(r))
  1036. {
  1037. list.add(SkillTable.getSkillHashCode(s.getSkillId(), s.getSkillLevel()));
  1038. }
  1039. }
  1040. for (L2SkillLearn s : _transformSkillTree.values())
  1041. {
  1042. if (s.getRaces().contains(r))
  1043. {
  1044. list.add(SkillTable.getSkillHashCode(s.getSkillId(), s.getSkillLevel()));
  1045. }
  1046. }
  1047. i = 0;
  1048. array = new int[list.size()];
  1049. for (int s : list)
  1050. {
  1051. array[i++] = s;
  1052. }
  1053. Arrays.sort(array);
  1054. _skillsByRaceHashCodes.put(r.ordinal(), array);
  1055. list.clear();
  1056. }
  1057. // Skills available for all classes and races
  1058. for (L2SkillLearn s : _commonSkillTree.values())
  1059. {
  1060. if (s.getRaces().isEmpty())
  1061. {
  1062. list.add(SkillTable.getSkillHashCode(s.getSkillId(), s.getSkillLevel()));
  1063. }
  1064. }
  1065. for (L2SkillLearn s : _fishingSkillTree.values())
  1066. {
  1067. if (s.getRaces().isEmpty())
  1068. {
  1069. list.add(SkillTable.getSkillHashCode(s.getSkillId(), s.getSkillLevel()));
  1070. }
  1071. }
  1072. for (L2SkillLearn s : _transformSkillTree.values())
  1073. {
  1074. if (s.getRaces().isEmpty())
  1075. {
  1076. list.add(SkillTable.getSkillHashCode(s.getSkillId(), s.getSkillLevel()));
  1077. }
  1078. }
  1079. for (L2SkillLearn s : _collectSkillTree.values())
  1080. {
  1081. list.add(SkillTable.getSkillHashCode(s.getSkillId(), s.getSkillLevel()));
  1082. }
  1083. _allSkillsHashCodes = new int[list.size()];
  1084. int j = 0;
  1085. for (int hashcode : list)
  1086. {
  1087. _allSkillsHashCodes[j++] = hashcode;
  1088. }
  1089. Arrays.sort(_allSkillsHashCodes);
  1090. }
  1091. /**
  1092. * Verify if the give skill is valid for the given player.<br>
  1093. * GM's skills are excluded for GM players.
  1094. * @param player the player to verify the skill.
  1095. * @param skill the skill to be verified.
  1096. * @return {@code true} if the skill is allowed to the given player.
  1097. */
  1098. public boolean isSkillAllowed(L2PcInstance player, L2Skill skill)
  1099. {
  1100. if (skill.isExcludedFromCheck())
  1101. {
  1102. return true;
  1103. }
  1104. if (player.isGM() && skill.isGMSkill())
  1105. {
  1106. return true;
  1107. }
  1108. // Prevent accidental skill remove during reload
  1109. if (_loading)
  1110. {
  1111. return true;
  1112. }
  1113. final int maxLvl = SkillTable.getInstance().getMaxLevel(skill.getId());
  1114. final int hashCode = SkillTable.getSkillHashCode(skill.getId(), Math.min(skill.getLevel(), maxLvl));
  1115. if (Arrays.binarySearch(_skillsByClassIdHashCodes.get(player.getClassId().ordinal()), hashCode) >= 0)
  1116. {
  1117. return true;
  1118. }
  1119. if (Arrays.binarySearch(_skillsByRaceHashCodes.get(player.getRace().ordinal()), hashCode) >= 0)
  1120. {
  1121. return true;
  1122. }
  1123. if (Arrays.binarySearch(_allSkillsHashCodes, hashCode) >= 0)
  1124. {
  1125. return true;
  1126. }
  1127. // Exclude Transfer Skills from this check.
  1128. if (getTransferSkill(skill.getId(), Math.min(skill.getLevel(), maxLvl), player.getClassId()) != null)
  1129. {
  1130. return true;
  1131. }
  1132. return false;
  1133. }
  1134. /**
  1135. * Logs current Skill Trees skills count.
  1136. */
  1137. private void report()
  1138. {
  1139. int classSkillTreeCount = 0;
  1140. for (Map<Integer, L2SkillLearn> classSkillTree : _classSkillTrees.values())
  1141. {
  1142. classSkillTreeCount += classSkillTree.size();
  1143. }
  1144. int trasferSkillTreeCount = 0;
  1145. for (Map<Integer, L2SkillLearn> trasferSkillTree : _transferSkillTrees.values())
  1146. {
  1147. trasferSkillTreeCount += trasferSkillTree.size();
  1148. }
  1149. int dwarvenOnlyFishingSkillCount = 0;
  1150. for (L2SkillLearn fishSkill : _fishingSkillTree.values())
  1151. {
  1152. if (fishSkill.getRaces().contains(Race.Dwarf))
  1153. {
  1154. dwarvenOnlyFishingSkillCount++;
  1155. }
  1156. }
  1157. int resSkillCount = 0;
  1158. for (L2SkillLearn pledgeSkill : _pledgeSkillTree.values())
  1159. {
  1160. if (pledgeSkill.isResidencialSkill())
  1161. {
  1162. resSkillCount++;
  1163. }
  1164. }
  1165. final String className = getClass().getSimpleName();
  1166. _log.info(className + ": Loaded " + classSkillTreeCount + " Class Skills for " + _classSkillTrees.size() + " Class Skill Trees.");
  1167. _log.info(className + ": Loaded " + _subClassSkillTree.size() + " Sub-Class Skills.");
  1168. _log.info(className + ": Loaded " + trasferSkillTreeCount + " Transfer Skills for " + _transferSkillTrees.size() + " Transfer Skill Trees.");
  1169. _log.info(className + ": Loaded " + _fishingSkillTree.size() + " Fishing Skills, " + dwarvenOnlyFishingSkillCount + " Dwarven only Fishing Skills.");
  1170. _log.info(className + ": Loaded " + _collectSkillTree.size() + " Collect Skills.");
  1171. _log.info(className + ": Loaded " + _pledgeSkillTree.size() + " Pledge Skills, " + (_pledgeSkillTree.size() - resSkillCount) + " for Pledge and " + resSkillCount + " Residential.");
  1172. _log.info(className + ": Loaded " + _subPledgeSkillTree.size() + " Sub-Pledge Skills.");
  1173. _log.info(className + ": Loaded " + _transformSkillTree.size() + " Transform Skills.");
  1174. _log.info(className + ": Loaded " + _nobleSkillTree.size() + " Noble Skills.");
  1175. _log.info(className + ": Loaded " + _heroSkillTree.size() + " Hero Skills.");
  1176. _log.info(className + ": Loaded " + _gameMasterSkillTree.size() + " Game Master Skills.");
  1177. _log.info(className + ": Loaded " + _gameMasterAuraSkillTree.size() + " Game Master Aura Skills.");
  1178. final int commonSkills = _commonSkillTree.size();
  1179. if (commonSkills > 0)
  1180. {
  1181. _log.info(className + ": Loaded " + commonSkills + " Common Skills to all classes.");
  1182. }
  1183. }
  1184. /**
  1185. * Gets the single instance of SkillTreesData.
  1186. * @return the only instance of this class.
  1187. */
  1188. public static SkillTreesData getInstance()
  1189. {
  1190. return SingletonHolder._instance;
  1191. }
  1192. /**
  1193. * Singleton holder for the SkillTreesData class.
  1194. */
  1195. private static class SingletonHolder
  1196. {
  1197. protected static final SkillTreesData _instance = new SkillTreesData();
  1198. }
  1199. }