SkillTreesData.java 41 KB

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