RequestAcquireSkill.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  2. * Copyright (C) 2004-2015 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.network.clientpackets;
  20. import java.util.List;
  21. import com.l2jserver.Config;
  22. import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
  23. import com.l2jserver.gameserver.datatables.SkillData;
  24. import com.l2jserver.gameserver.enums.IllegalActionPunishmentType;
  25. import com.l2jserver.gameserver.instancemanager.QuestManager;
  26. import com.l2jserver.gameserver.model.ClanPrivilege;
  27. import com.l2jserver.gameserver.model.L2Clan;
  28. import com.l2jserver.gameserver.model.L2SkillLearn;
  29. import com.l2jserver.gameserver.model.actor.L2Npc;
  30. import com.l2jserver.gameserver.model.actor.instance.L2FishermanInstance;
  31. import com.l2jserver.gameserver.model.actor.instance.L2NpcInstance;
  32. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  33. import com.l2jserver.gameserver.model.actor.instance.L2VillageMasterInstance;
  34. import com.l2jserver.gameserver.model.base.AcquireSkillType;
  35. import com.l2jserver.gameserver.model.events.EventDispatcher;
  36. import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerSkillLearn;
  37. import com.l2jserver.gameserver.model.holders.ItemHolder;
  38. import com.l2jserver.gameserver.model.holders.SkillHolder;
  39. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  40. import com.l2jserver.gameserver.model.quest.Quest;
  41. import com.l2jserver.gameserver.model.quest.QuestState;
  42. import com.l2jserver.gameserver.model.skills.CommonSkill;
  43. import com.l2jserver.gameserver.model.skills.Skill;
  44. import com.l2jserver.gameserver.network.SystemMessageId;
  45. import com.l2jserver.gameserver.network.serverpackets.AcquireSkillDone;
  46. import com.l2jserver.gameserver.network.serverpackets.AcquireSkillList;
  47. import com.l2jserver.gameserver.network.serverpackets.ExStorageMaxCount;
  48. import com.l2jserver.gameserver.network.serverpackets.PledgeSkillList;
  49. import com.l2jserver.gameserver.network.serverpackets.StatusUpdate;
  50. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  51. import com.l2jserver.gameserver.util.Util;
  52. /**
  53. * Request Acquire Skill client packet implementation.
  54. * @author Zoey76
  55. */
  56. public final class RequestAcquireSkill extends L2GameClientPacket
  57. {
  58. private static final String _C__7C_REQUESTACQUIRESKILL = "[C] 7C RequestAcquireSkill";
  59. private static final String[] QUEST_VAR_NAMES =
  60. {
  61. "EmergentAbility65-",
  62. "EmergentAbility70-",
  63. "ClassAbility75-",
  64. "ClassAbility80-"
  65. };
  66. private int _id;
  67. private int _level;
  68. private AcquireSkillType _skillType;
  69. private int _subType;
  70. @Override
  71. protected void readImpl()
  72. {
  73. _id = readD();
  74. _level = readD();
  75. _skillType = AcquireSkillType.getAcquireSkillType(readD());
  76. if (_skillType == AcquireSkillType.SUBPLEDGE)
  77. {
  78. _subType = readD();
  79. }
  80. }
  81. @Override
  82. protected void runImpl()
  83. {
  84. final L2PcInstance activeChar = getClient().getActiveChar();
  85. if (activeChar == null)
  86. {
  87. return;
  88. }
  89. if ((_level < 1) || (_level > 1000) || (_id < 1) || (_id > 32000))
  90. {
  91. Util.handleIllegalPlayerAction(activeChar, "Wrong Packet Data in Aquired Skill", Config.DEFAULT_PUNISH);
  92. _log.warning("Recived Wrong Packet Data in Aquired Skill - id: " + _id + " level: " + _level + " for " + activeChar);
  93. return;
  94. }
  95. final L2Npc trainer = activeChar.getLastFolkNPC();
  96. if (!(trainer instanceof L2NpcInstance))
  97. {
  98. return;
  99. }
  100. if (!trainer.canInteract(activeChar) && !activeChar.isGM())
  101. {
  102. return;
  103. }
  104. final Skill skill = SkillData.getInstance().getSkill(_id, _level);
  105. if (skill == null)
  106. {
  107. _log.warning(RequestAcquireSkill.class.getSimpleName() + ": Player " + activeChar.getName() + " is trying to learn a null skill Id: " + _id + " level: " + _level + "!");
  108. return;
  109. }
  110. // Hack check. Doesn't apply to all Skill Types
  111. final int prevSkillLevel = activeChar.getSkillLevel(_id);
  112. if ((prevSkillLevel > 0) && !((_skillType == AcquireSkillType.TRANSFER) || (_skillType == AcquireSkillType.SUBPLEDGE)))
  113. {
  114. if (prevSkillLevel == _level)
  115. {
  116. _log.warning("Player " + activeChar.getName() + " is trying to learn a skill that already knows, Id: " + _id + " level: " + _level + "!");
  117. return;
  118. }
  119. else if (prevSkillLevel != (_level - 1))
  120. {
  121. // The previous level skill has not been learned.
  122. activeChar.sendPacket(SystemMessageId.PREVIOUS_LEVEL_SKILL_NOT_LEARNED);
  123. Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " is requesting skill Id: " + _id + " level " + _level + " without knowing it's previous level!", IllegalActionPunishmentType.NONE);
  124. return;
  125. }
  126. }
  127. final L2SkillLearn s = SkillTreesData.getInstance().getSkillLearn(_skillType, _id, _level, activeChar);
  128. if (s == null)
  129. {
  130. return;
  131. }
  132. switch (_skillType)
  133. {
  134. case CLASS:
  135. {
  136. if (checkPlayerSkill(activeChar, trainer, s))
  137. {
  138. giveSkill(activeChar, trainer, skill);
  139. }
  140. break;
  141. }
  142. case TRANSFORM:
  143. {
  144. // Hack check.
  145. if (!canTransform(activeChar))
  146. {
  147. activeChar.sendPacket(SystemMessageId.NOT_COMPLETED_QUEST_FOR_SKILL_ACQUISITION);
  148. Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " is requesting skill Id: " + _id + " level " + _level + " without required quests!", IllegalActionPunishmentType.NONE);
  149. return;
  150. }
  151. if (checkPlayerSkill(activeChar, trainer, s))
  152. {
  153. giveSkill(activeChar, trainer, skill);
  154. }
  155. break;
  156. }
  157. case FISHING:
  158. {
  159. if (checkPlayerSkill(activeChar, trainer, s))
  160. {
  161. giveSkill(activeChar, trainer, skill);
  162. }
  163. break;
  164. }
  165. case PLEDGE:
  166. {
  167. if (!activeChar.isClanLeader())
  168. {
  169. return;
  170. }
  171. final L2Clan clan = activeChar.getClan();
  172. int repCost = s.getLevelUpSp();
  173. if (clan.getReputationScore() >= repCost)
  174. {
  175. if (Config.LIFE_CRYSTAL_NEEDED)
  176. {
  177. for (ItemHolder item : s.getRequiredItems())
  178. {
  179. if (!activeChar.destroyItemByItemId("Consume", item.getId(), item.getCount(), trainer, false))
  180. {
  181. // Doesn't have required item.
  182. activeChar.sendPacket(SystemMessageId.ITEM_OR_PREREQUISITES_MISSING_TO_LEARN_SKILL);
  183. L2VillageMasterInstance.showPledgeSkillList(activeChar);
  184. return;
  185. }
  186. final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
  187. sm.addItemName(item.getId());
  188. sm.addLong(item.getCount());
  189. activeChar.sendPacket(sm);
  190. }
  191. }
  192. clan.takeReputationScore(repCost, true);
  193. final SystemMessage cr = SystemMessage.getSystemMessage(SystemMessageId.S1_DEDUCTED_FROM_CLAN_REP);
  194. cr.addInt(repCost);
  195. activeChar.sendPacket(cr);
  196. clan.addNewSkill(skill);
  197. clan.broadcastToOnlineMembers(new PledgeSkillList(clan));
  198. activeChar.sendPacket(new AcquireSkillDone());
  199. L2VillageMasterInstance.showPledgeSkillList(activeChar);
  200. }
  201. else
  202. {
  203. activeChar.sendPacket(SystemMessageId.ACQUIRE_SKILL_FAILED_BAD_CLAN_REP_SCORE);
  204. L2VillageMasterInstance.showPledgeSkillList(activeChar);
  205. }
  206. break;
  207. }
  208. case SUBPLEDGE:
  209. {
  210. if (!activeChar.isClanLeader() || !activeChar.hasClanPrivilege(ClanPrivilege.CL_TROOPS_FAME))
  211. {
  212. return;
  213. }
  214. final L2Clan clan = activeChar.getClan();
  215. if ((clan.getFortId() == 0) && (clan.getCastleId() == 0))
  216. {
  217. return;
  218. }
  219. // Hack check. Check if SubPledge can accept the new skill:
  220. if (!clan.isLearnableSubPledgeSkill(skill, _subType))
  221. {
  222. activeChar.sendPacket(SystemMessageId.SQUAD_SKILL_ALREADY_ACQUIRED);
  223. Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " is requesting skill Id: " + _id + " level " + _level + " without knowing it's previous level!", IllegalActionPunishmentType.NONE);
  224. return;
  225. }
  226. final int repCost = s.getLevelUpSp();
  227. if (clan.getReputationScore() < repCost)
  228. {
  229. activeChar.sendPacket(SystemMessageId.ACQUIRE_SKILL_FAILED_BAD_CLAN_REP_SCORE);
  230. return;
  231. }
  232. for (ItemHolder item : s.getRequiredItems())
  233. {
  234. if (!activeChar.destroyItemByItemId("SubSkills", item.getId(), item.getCount(), trainer, false))
  235. {
  236. activeChar.sendPacket(SystemMessageId.ITEM_OR_PREREQUISITES_MISSING_TO_LEARN_SKILL);
  237. return;
  238. }
  239. final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
  240. sm.addItemName(item.getId());
  241. sm.addLong(item.getCount());
  242. activeChar.sendPacket(sm);
  243. }
  244. if (repCost > 0)
  245. {
  246. clan.takeReputationScore(repCost, true);
  247. final SystemMessage cr = SystemMessage.getSystemMessage(SystemMessageId.S1_DEDUCTED_FROM_CLAN_REP);
  248. cr.addInt(repCost);
  249. activeChar.sendPacket(cr);
  250. }
  251. clan.addNewSkill(skill, _subType);
  252. clan.broadcastToOnlineMembers(new PledgeSkillList(clan));
  253. activeChar.sendPacket(new AcquireSkillDone());
  254. showSubUnitSkillList(activeChar);
  255. break;
  256. }
  257. case TRANSFER:
  258. {
  259. if (checkPlayerSkill(activeChar, trainer, s))
  260. {
  261. giveSkill(activeChar, trainer, skill);
  262. }
  263. break;
  264. }
  265. case SUBCLASS:
  266. {
  267. // Hack check.
  268. if (activeChar.isSubClassActive())
  269. {
  270. activeChar.sendPacket(SystemMessageId.SKILL_NOT_FOR_SUBCLASS);
  271. Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " is requesting skill Id: " + _id + " level " + _level + " while Sub-Class is active!", IllegalActionPunishmentType.NONE);
  272. return;
  273. }
  274. // Certification Skills - Exploit fix
  275. if ((prevSkillLevel == -1) && (_level > 1))
  276. {
  277. // The previous level skill has not been learned.
  278. activeChar.sendPacket(SystemMessageId.PREVIOUS_LEVEL_SKILL_NOT_LEARNED);
  279. Util.handleIllegalPlayerAction(activeChar, "Player " + activeChar.getName() + " is requesting skill Id: " + _id + " level " + _level + " without knowing it's previous level!", IllegalActionPunishmentType.NONE);
  280. return;
  281. }
  282. QuestState st = activeChar.getQuestState("SubClassSkills");
  283. if (st == null)
  284. {
  285. final Quest subClassSkilllsQuest = QuestManager.getInstance().getQuest("SubClassSkills");
  286. if (subClassSkilllsQuest != null)
  287. {
  288. st = subClassSkilllsQuest.newQuestState(activeChar);
  289. }
  290. else
  291. {
  292. _log.warning("Null SubClassSkills quest, for Sub-Class skill Id: " + _id + " level: " + _level + " for player " + activeChar.getName() + "!");
  293. return;
  294. }
  295. }
  296. for (String varName : QUEST_VAR_NAMES)
  297. {
  298. for (int i = 1; i <= Config.MAX_SUBCLASS; i++)
  299. {
  300. final String itemOID = st.getGlobalQuestVar(varName + i);
  301. if (!itemOID.isEmpty() && !itemOID.endsWith(";") && !itemOID.equals("0"))
  302. {
  303. if (Util.isDigit(itemOID))
  304. {
  305. final int itemObjId = Integer.parseInt(itemOID);
  306. final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(itemObjId);
  307. if (item != null)
  308. {
  309. for (ItemHolder itemIdCount : s.getRequiredItems())
  310. {
  311. if (item.getId() == itemIdCount.getId())
  312. {
  313. if (checkPlayerSkill(activeChar, trainer, s))
  314. {
  315. giveSkill(activeChar, trainer, skill);
  316. // Logging the given skill.
  317. st.saveGlobalQuestVar(varName + i, skill.getId() + ";");
  318. }
  319. return;
  320. }
  321. }
  322. }
  323. else
  324. {
  325. _log.warning("Inexistent item for object Id " + itemObjId + ", for Sub-Class skill Id: " + _id + " level: " + _level + " for player " + activeChar.getName() + "!");
  326. }
  327. }
  328. else
  329. {
  330. _log.warning("Invalid item object Id " + itemOID + ", for Sub-Class skill Id: " + _id + " level: " + _level + " for player " + activeChar.getName() + "!");
  331. }
  332. }
  333. }
  334. }
  335. // Player doesn't have required item.
  336. activeChar.sendPacket(SystemMessageId.ITEM_OR_PREREQUISITES_MISSING_TO_LEARN_SKILL);
  337. showSkillList(trainer, activeChar);
  338. break;
  339. }
  340. case COLLECT:
  341. {
  342. if (checkPlayerSkill(activeChar, trainer, s))
  343. {
  344. giveSkill(activeChar, trainer, skill);
  345. }
  346. break;
  347. }
  348. default:
  349. {
  350. _log.warning("Recived Wrong Packet Data in Aquired Skill, unknown skill type:" + _skillType);
  351. break;
  352. }
  353. }
  354. }
  355. public static void showSubUnitSkillList(L2PcInstance activeChar)
  356. {
  357. final List<L2SkillLearn> skills = SkillTreesData.getInstance().getAvailableSubPledgeSkills(activeChar.getClan());
  358. final AcquireSkillList asl = new AcquireSkillList(AcquireSkillType.SUBPLEDGE);
  359. int count = 0;
  360. for (L2SkillLearn s : skills)
  361. {
  362. if (SkillData.getInstance().getSkill(s.getSkillId(), s.getSkillLevel()) != null)
  363. {
  364. asl.addSkill(s.getSkillId(), s.getSkillLevel(), s.getSkillLevel(), s.getLevelUpSp(), 0);
  365. ++count;
  366. }
  367. }
  368. if (count == 0)
  369. {
  370. activeChar.sendPacket(SystemMessageId.NO_MORE_SKILLS_TO_LEARN);
  371. }
  372. else
  373. {
  374. activeChar.sendPacket(asl);
  375. }
  376. }
  377. /**
  378. * Perform a simple check for current player and skill.<br>
  379. * Takes the needed SP if the skill require it and all requirements are meet.<br>
  380. * Consume required items if the skill require it and all requirements are meet.<br>
  381. * @param player the skill learning player.
  382. * @param trainer the skills teaching Npc.
  383. * @param s the skill to be learn.
  384. * @return {@code true} if all requirements are meet, {@code false} otherwise.
  385. */
  386. private boolean checkPlayerSkill(L2PcInstance player, L2Npc trainer, L2SkillLearn s)
  387. {
  388. if (s != null)
  389. {
  390. if ((s.getSkillId() == _id) && (s.getSkillLevel() == _level))
  391. {
  392. // Hack check.
  393. if (s.getGetLevel() > player.getLevel())
  394. {
  395. player.sendPacket(SystemMessageId.YOU_DONT_MEET_SKILL_LEVEL_REQUIREMENTS);
  396. Util.handleIllegalPlayerAction(player, "Player " + player.getName() + ", level " + player.getLevel() + " is requesting skill Id: " + _id + " level " + _level + " without having minimum required level, " + s.getGetLevel() + "!", IllegalActionPunishmentType.NONE);
  397. return false;
  398. }
  399. // First it checks that the skill require SP and the player has enough SP to learn it.
  400. final int levelUpSp = s.getCalculatedLevelUpSp(player.getClassId(), player.getLearningClass());
  401. if ((levelUpSp > 0) && (levelUpSp > player.getSp()))
  402. {
  403. player.sendPacket(SystemMessageId.NOT_ENOUGH_SP_TO_LEARN_SKILL);
  404. showSkillList(trainer, player);
  405. return false;
  406. }
  407. if (!Config.DIVINE_SP_BOOK_NEEDED && (_id == CommonSkill.DIVINE_INSPIRATION.getId()))
  408. {
  409. return true;
  410. }
  411. // Check for required skills.
  412. if (!s.getPreReqSkills().isEmpty())
  413. {
  414. for (SkillHolder skill : s.getPreReqSkills())
  415. {
  416. if (player.getSkillLevel(skill.getSkillId()) != skill.getSkillLvl())
  417. {
  418. if (skill.getSkillId() == CommonSkill.ONYX_BEAST_TRANSFORMATION.getId())
  419. {
  420. player.sendPacket(SystemMessageId.YOU_MUST_LEARN_ONYX_BEAST_SKILL);
  421. }
  422. else
  423. {
  424. player.sendPacket(SystemMessageId.ITEM_OR_PREREQUISITES_MISSING_TO_LEARN_SKILL);
  425. }
  426. return false;
  427. }
  428. }
  429. }
  430. // Check for required items.
  431. if (!s.getRequiredItems().isEmpty())
  432. {
  433. // Then checks that the player has all the items
  434. long reqItemCount = 0;
  435. for (ItemHolder item : s.getRequiredItems())
  436. {
  437. reqItemCount = player.getInventory().getInventoryItemCount(item.getId(), -1);
  438. if (reqItemCount < item.getCount())
  439. {
  440. // Player doesn't have required item.
  441. player.sendPacket(SystemMessageId.ITEM_OR_PREREQUISITES_MISSING_TO_LEARN_SKILL);
  442. showSkillList(trainer, player);
  443. return false;
  444. }
  445. }
  446. // If the player has all required items, they are consumed.
  447. for (ItemHolder itemIdCount : s.getRequiredItems())
  448. {
  449. if (!player.destroyItemByItemId("SkillLearn", itemIdCount.getId(), itemIdCount.getCount(), trainer, true))
  450. {
  451. Util.handleIllegalPlayerAction(player, "Somehow player " + player.getName() + ", level " + player.getLevel() + " lose required item Id: " + itemIdCount.getId() + " to learn skill while learning skill Id: " + _id + " level " + _level + "!", IllegalActionPunishmentType.NONE);
  452. }
  453. }
  454. }
  455. // If the player has SP and all required items then consume SP.
  456. if (levelUpSp > 0)
  457. {
  458. player.setSp(player.getSp() - levelUpSp);
  459. final StatusUpdate su = new StatusUpdate(player);
  460. su.addAttribute(StatusUpdate.SP, player.getSp());
  461. player.sendPacket(su);
  462. }
  463. return true;
  464. }
  465. }
  466. return false;
  467. }
  468. /**
  469. * Add the skill to the player and makes proper updates.
  470. * @param player the player acquiring a skill.
  471. * @param trainer the Npc teaching a skill.
  472. * @param skill the skill to be learn.
  473. */
  474. private void giveSkill(L2PcInstance player, L2Npc trainer, Skill skill)
  475. {
  476. // Send message.
  477. final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.LEARNED_SKILL_S1);
  478. sm.addSkillName(skill);
  479. player.sendPacket(sm);
  480. player.sendPacket(new AcquireSkillDone());
  481. player.addSkill(skill, true);
  482. player.sendSkillList();
  483. player.updateShortCuts(_id, _level);
  484. showSkillList(trainer, player);
  485. // If skill is expand type then sends packet:
  486. if ((_id >= 1368) && (_id <= 1372))
  487. {
  488. player.sendPacket(new ExStorageMaxCount(player));
  489. }
  490. // Notify scripts of the skill learn.
  491. EventDispatcher.getInstance().notifyEventAsync(new OnPlayerSkillLearn(trainer, player, skill, _skillType), trainer);
  492. }
  493. /**
  494. * Wrapper for returning the skill list to the player after it's done with current skill.
  495. * @param trainer the Npc which the {@code player} is interacting
  496. * @param player the active character
  497. */
  498. private void showSkillList(L2Npc trainer, L2PcInstance player)
  499. {
  500. if ((_skillType == AcquireSkillType.TRANSFORM) || (_skillType == AcquireSkillType.SUBCLASS) || (_skillType == AcquireSkillType.TRANSFER))
  501. {
  502. // Managed in Datapack.
  503. return;
  504. }
  505. if (trainer instanceof L2FishermanInstance)
  506. {
  507. L2FishermanInstance.showFishSkillList(player);
  508. }
  509. else
  510. {
  511. L2NpcInstance.showSkillList(player, trainer, player.getLearningClass());
  512. }
  513. }
  514. /**
  515. * Verify if the player can transform.
  516. * @param player the player to verify
  517. * @return {@code true} if the player meets the required conditions to learn a transformation, {@code false} otherwise
  518. */
  519. public static boolean canTransform(L2PcInstance player)
  520. {
  521. if (Config.ALLOW_TRANSFORM_WITHOUT_QUEST)
  522. {
  523. return true;
  524. }
  525. final QuestState st = player.getQuestState("Q00136_MoreThanMeetsTheEye");
  526. return (st != null) && st.isCompleted();
  527. }
  528. @Override
  529. public String getType()
  530. {
  531. return _C__7C_REQUESTACQUIRESKILL;
  532. }
  533. }