QuestState.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package net.sf.l2j.gameserver.model.quest;
  16. import java.util.Map;
  17. import java.util.logging.Logger;
  18. import javolution.util.FastMap;
  19. import net.sf.l2j.Config;
  20. import net.sf.l2j.gameserver.GameTimeController;
  21. import net.sf.l2j.gameserver.cache.HtmCache;
  22. import net.sf.l2j.gameserver.instancemanager.QuestManager;
  23. import net.sf.l2j.gameserver.model.L2Character;
  24. import net.sf.l2j.gameserver.model.L2DropData;
  25. import net.sf.l2j.gameserver.model.L2ItemInstance;
  26. import net.sf.l2j.gameserver.model.actor.instance.L2MonsterInstance;
  27. import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
  28. import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  29. import net.sf.l2j.gameserver.network.SystemMessageId;
  30. import net.sf.l2j.gameserver.network.serverpackets.ExShowQuestMark;
  31. import net.sf.l2j.gameserver.network.serverpackets.ItemList;
  32. import net.sf.l2j.gameserver.network.serverpackets.PlaySound;
  33. import net.sf.l2j.gameserver.network.serverpackets.QuestList;
  34. import net.sf.l2j.gameserver.network.serverpackets.StatusUpdate;
  35. import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
  36. import net.sf.l2j.gameserver.network.serverpackets.TutorialCloseHtml;
  37. import net.sf.l2j.gameserver.network.serverpackets.TutorialEnableClientEvent;
  38. import net.sf.l2j.gameserver.network.serverpackets.TutorialShowHtml;
  39. import net.sf.l2j.gameserver.network.serverpackets.TutorialShowQuestionMark;
  40. import net.sf.l2j.gameserver.skills.Stats;
  41. import net.sf.l2j.util.Rnd;
  42. /**
  43. * @author Luis Arias
  44. */
  45. public final class QuestState
  46. {
  47. protected static final Logger _log = Logger.getLogger(Quest.class.getName());
  48. /** Quest associated to the QuestState */
  49. private final String _questName;
  50. /** Player who engaged the quest */
  51. private final L2PcInstance _player;
  52. /** State of the quest */
  53. private byte _state;
  54. /** List of couples (variable for quest,value of the variable for quest) */
  55. private Map<String, String> _vars;
  56. /** Boolean flag letting QuestStateManager know to exit quest when cleaning up */
  57. private boolean _isExitQuestOnCleanUp = false;
  58. /**
  59. * Constructor of the QuestState : save the quest in the list of quests of the player.<BR/><BR/>
  60. *
  61. * <U><I>Actions :</U></I><BR/>
  62. * <LI>Save informations in the object QuestState created (Quest, Player, Completion, State)</LI>
  63. * <LI>Add the QuestState in the player's list of quests by using setQuestState()</LI>
  64. * <LI>Add drops gotten by the quest</LI>
  65. * <BR/>
  66. * @param quest : quest associated with the QuestState
  67. * @param player : L2PcInstance pointing out the player
  68. * @param state : state of the quest
  69. * @param completed : boolean for completion of the quest
  70. */
  71. QuestState(Quest quest, L2PcInstance player, byte state)
  72. {
  73. _questName = quest.getName();
  74. _player = player;
  75. // Save the state of the quest for the player in the player's list of quest onwed
  76. getPlayer().setQuestState(this);
  77. // set the state of the quest
  78. _state = state;
  79. }
  80. public String getQuestName()
  81. {
  82. return _questName;
  83. }
  84. /**
  85. * Return the quest
  86. * @return Quest
  87. */
  88. public Quest getQuest()
  89. {
  90. return QuestManager.getInstance().getQuest(_questName);
  91. }
  92. /**
  93. * Return the L2PcInstance
  94. * @return L2PcInstance
  95. */
  96. public L2PcInstance getPlayer()
  97. {
  98. return _player;
  99. }
  100. /**
  101. * Return the state of the quest
  102. * @return State
  103. */
  104. public byte getState()
  105. {
  106. return _state;
  107. }
  108. /**
  109. * Return true if quest completed, false otherwise
  110. * @return boolean
  111. */
  112. public boolean isCompleted()
  113. {
  114. return (getState() == State.COMPLETED);
  115. }
  116. /**
  117. * Return true if quest started, false otherwise
  118. * @return boolean
  119. */
  120. public boolean isStarted()
  121. {
  122. return (getState() == State.STARTED);
  123. }
  124. /**
  125. * Return state of the quest after its initialization.<BR><BR>
  126. * <U><I>Actions :</I></U>
  127. * <LI>Remove drops from previous state</LI>
  128. * <LI>Set new state of the quest</LI>
  129. * <LI>Add drop for new state</LI>
  130. * <LI>Update information in database</LI>
  131. * <LI>Send packet QuestList to client</LI>
  132. * @param state
  133. * @return object
  134. */
  135. public Object setState(byte state)
  136. {
  137. // set new state if it is not already in that state
  138. if (_state != state)
  139. {
  140. _state = state;
  141. Quest.updateQuestInDb(this);
  142. QuestList ql = new QuestList();
  143. getPlayer().sendPacket(ql);
  144. }
  145. return state;
  146. }
  147. /**
  148. * Add parameter used in quests.
  149. * @param var : String pointing out the name of the variable for quest
  150. * @param val : String pointing out the value of the variable for quest
  151. * @return String (equal to parameter "val")
  152. */
  153. String setInternal(String var, String val)
  154. {
  155. if (_vars == null)
  156. _vars = new FastMap<String, String>();
  157. if (val == null)
  158. val = "";
  159. _vars.put(var, val);
  160. return val;
  161. }
  162. /**
  163. * Return value of parameter "val" after adding the couple (var,val) in class variable "vars".<BR><BR>
  164. * <U><I>Actions :</I></U><BR>
  165. * <LI>Initialize class variable "vars" if is null</LI>
  166. * <LI>Initialize parameter "val" if is null</LI>
  167. * <LI>Add/Update couple (var,val) in class variable FastMap "vars"</LI>
  168. * <LI>If the key represented by "var" exists in FastMap "vars", the couple (var,val) is updated in the database. The key is known as
  169. * existing if the preceding value of the key (given as result of function put()) is not null.<BR>
  170. * If the key doesn't exist, the couple is added/created in the database</LI>
  171. * @param var : String indicating the name of the variable for quest
  172. * @param val : String indicating the value of the variable for quest
  173. * @return String (equal to parameter "val")
  174. */
  175. public String set(String var, String val)
  176. {
  177. if (_vars == null)
  178. _vars = new FastMap<String, String>();
  179. if (val == null)
  180. val = "";
  181. // FastMap.put() returns previous value associated with specified key, or null if there was no mapping for key.
  182. String old = _vars.put(var, val);
  183. if (old != null)
  184. Quest.updateQuestVarInDb(this, var, val);
  185. else
  186. Quest.createQuestVarInDb(this, var, val);
  187. if (var == "cond")
  188. {
  189. try
  190. {
  191. int previousVal = 0;
  192. try
  193. {
  194. previousVal = Integer.parseInt(old);
  195. }
  196. catch (Exception ex)
  197. {
  198. previousVal = 0;
  199. }
  200. setCond(Integer.parseInt(val), previousVal);
  201. }
  202. catch (Exception e)
  203. {
  204. _log.finer(getPlayer().getName() + ", " + getQuestName() + " cond [" + val + "] is not an integer. Value stored, but no packet was sent: " + e);
  205. }
  206. }
  207. return val;
  208. }
  209. /**
  210. * Internally handles the progression of the quest so that it is ready for sending
  211. * appropriate packets to the client<BR><BR>
  212. * <U><I>Actions :</I></U><BR>
  213. * <LI>Check if the new progress number resets the quest to a previous (smaller) step</LI>
  214. * <LI>If not, check if quest progress steps have been skipped</LI>
  215. * <LI>If skipped, prepare the variable completedStateFlags appropriately to be ready for sending to clients</LI>
  216. * <LI>If no steps were skipped, flags do not need to be prepared...</LI>
  217. * <LI>If the passed step resets the quest to a previous step, reset such that steps after the parameter are not
  218. * considered, while skipped steps before the parameter, if any, maintain their info</LI>
  219. * @param cond : int indicating the step number for the current quest progress (as will be shown to the client)
  220. * @param old : int indicating the previously noted step
  221. *
  222. * For more info on the variable communicating the progress steps to the client, please see
  223. * @link net.sf.l2j.loginserver.serverpacket.QuestList
  224. */
  225. private void setCond(int cond, int old)
  226. {
  227. int completedStateFlags = 0; // initializing...
  228. // if there is no change since last setting, there is nothing to do here
  229. if (cond == old)
  230. return;
  231. // cond 0 and 1 do not need completedStateFlags. Also, if cond > 1, the 1st step must
  232. // always exist (i.e. it can never be skipped). So if cond is 2, we can still safely
  233. // assume no steps have been skipped.
  234. // Finally, more than 31 steps CANNOT be supported in any way with skipping.
  235. if (cond < 3 || cond > 31)
  236. {
  237. unset("__compltdStateFlags");
  238. }
  239. else
  240. completedStateFlags = getInt("__compltdStateFlags");
  241. // case 1: No steps have been skipped so far...
  242. if (completedStateFlags == 0)
  243. {
  244. // check if this step also doesn't skip anything. If so, no further work is needed
  245. // also, in this case, no work is needed if the state is being reset to a smaller value
  246. // in those cases, skip forward to informing the client about the change...
  247. // ELSE, if we just now skipped for the first time...prepare the flags!!!
  248. if (cond > (old + 1))
  249. {
  250. // set the most significant bit to 1 (indicates that there exist skipped states)
  251. // also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
  252. // what the cond says)
  253. completedStateFlags = 0x80000001;
  254. // since no flag had been skipped until now, the least significant bits must all
  255. // be set to 1, up until "old" number of bits.
  256. completedStateFlags |= ((1 << old) - 1);
  257. // now, just set the bit corresponding to the passed cond to 1 (current step)
  258. completedStateFlags |= (1 << (cond - 1));
  259. set("__compltdStateFlags", String.valueOf(completedStateFlags));
  260. }
  261. }
  262. // case 2: There were exist previously skipped steps
  263. else
  264. {
  265. // if this is a push back to a previous step, clear all completion flags ahead
  266. if (cond < old)
  267. {
  268. completedStateFlags &= ((1 << cond) - 1); // note, this also unsets the flag indicating that there exist skips
  269. //now, check if this resulted in no steps being skipped any more
  270. if (completedStateFlags == ((1 << cond) - 1))
  271. unset("__compltdStateFlags");
  272. else
  273. {
  274. // set the most significant bit back to 1 again, to correctly indicate that this skips states.
  275. // also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
  276. // what the cond says)
  277. completedStateFlags |= 0x80000001;
  278. set("__compltdStateFlags", String.valueOf(completedStateFlags));
  279. }
  280. }
  281. // if this moves forward, it changes nothing on previously skipped steps...so just mark this
  282. // state and we are done
  283. else
  284. {
  285. completedStateFlags |= (1 << (cond - 1));
  286. set("__compltdStateFlags", String.valueOf(completedStateFlags));
  287. }
  288. }
  289. // send a packet to the client to inform it of the quest progress (step change)
  290. QuestList ql = new QuestList();
  291. getPlayer().sendPacket(ql);
  292. int questId = getQuest().getQuestIntId();
  293. if (questId > 0 && questId < 999 && cond > 0)
  294. getPlayer().sendPacket(new ExShowQuestMark(questId));
  295. }
  296. /**
  297. * Remove the variable of quest from the list of variables for the quest.<BR><BR>
  298. * <U><I>Concept : </I></U>
  299. * Remove the variable of quest represented by "var" from the class variable FastMap "vars" and from the database.
  300. * @param var : String designating the variable for the quest to be deleted
  301. * @return String pointing out the previous value associated with the variable "var"
  302. */
  303. public String unset(String var)
  304. {
  305. if (_vars == null)
  306. return null;
  307. String old = _vars.remove(var);
  308. if (old != null)
  309. Quest.deleteQuestVarInDb(this, var);
  310. return old;
  311. }
  312. /**
  313. * Return the value of the variable of quest represented by "var"
  314. * @param var : name of the variable of quest
  315. * @return Object
  316. */
  317. public Object get(String var)
  318. {
  319. if (_vars == null)
  320. return null;
  321. return _vars.get(var);
  322. }
  323. /**
  324. * Return the value of the variable of quest represented by "var"
  325. * @param var : String designating the variable for the quest
  326. * @return int
  327. */
  328. public int getInt(String var)
  329. {
  330. int varint = 0;
  331. try
  332. {
  333. varint = Integer.parseInt(_vars.get(var));
  334. }
  335. catch (Exception e)
  336. {
  337. _log.finer(getPlayer().getName() + ": variable " + var + " isn't an integer: " + varint + e);
  338. // if (Config.AUTODELETE_INVALID_QUEST_DATA)
  339. // exitQuest(true);
  340. }
  341. return varint;
  342. }
  343. /**
  344. * Add player to get notification of characters death
  345. * @param character : L2Character of the character to get notification of death
  346. */
  347. public void addNotifyOfDeath(L2Character character)
  348. {
  349. if (character == null)
  350. return;
  351. character.addNotifyQuestOfDeath(this);
  352. }
  353. /**
  354. * Return the quantity of one sort of item hold by the player
  355. * @param itemId : ID of the item wanted to be count
  356. * @return int
  357. */
  358. public int getQuestItemsCount(int itemId)
  359. {
  360. int count = 0;
  361. for (L2ItemInstance item : getPlayer().getInventory().getItems())
  362. if (item.getItemId() == itemId)
  363. count += item.getCount();
  364. return count;
  365. }
  366. /**
  367. * Return the level of enchantment on the weapon of the player(Done specifically for weapon SA's)
  368. * @param itemId : ID of the item to check enchantment
  369. * @return int
  370. */
  371. public int getEnchantLevel(int itemId)
  372. {
  373. L2ItemInstance enchanteditem = getPlayer().getInventory().getItemByItemId(itemId);
  374. if (enchanteditem == null)
  375. return 0;
  376. return enchanteditem.getEnchantLevel();
  377. }
  378. /**
  379. * Give item/reward to the player
  380. * @param itemId
  381. * @param count
  382. */
  383. public void giveItems(int itemId, int count)
  384. {
  385. giveItems(itemId, count, 0);
  386. }
  387. public void giveItems(int itemId, int count, int enchantlevel)
  388. {
  389. if (count <= 0)
  390. return;
  391. int questId = getQuest().getQuestIntId();
  392. // If item for reward is gold (ID=57), modify count with rate for quest reward
  393. if (itemId == 57 && !(questId >= 217 && questId <= 233) && !(questId >= 401 && questId <= 418))
  394. count = (int) (count * Config.RATE_QUESTS_REWARD);
  395. // Set quantity of item
  396. // Add items to player's inventory
  397. L2ItemInstance item = getPlayer().getInventory().addItem("Quest", itemId, count, getPlayer(), getPlayer().getTarget());
  398. if (item == null)
  399. return;
  400. if (enchantlevel > 0)
  401. item.setEnchantLevel(enchantlevel);
  402. // If item for reward is gold, send message of gold reward to client
  403. if (itemId == 57)
  404. {
  405. SystemMessage smsg = new SystemMessage(SystemMessageId.EARNED_ADENA);
  406. smsg.addNumber(count);
  407. getPlayer().sendPacket(smsg);
  408. }
  409. // Otherwise, send message of object reward to client
  410. else
  411. {
  412. if (count > 1)
  413. {
  414. SystemMessage smsg = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
  415. smsg.addItemName(item);
  416. smsg.addNumber(count);
  417. getPlayer().sendPacket(smsg);
  418. }
  419. else
  420. {
  421. SystemMessage smsg = new SystemMessage(SystemMessageId.EARNED_ITEM);
  422. smsg.addItemName(item);
  423. getPlayer().sendPacket(smsg);
  424. }
  425. }
  426. getPlayer().sendPacket(new ItemList(getPlayer(), false));
  427. StatusUpdate su = new StatusUpdate(getPlayer().getObjectId());
  428. su.addAttribute(StatusUpdate.CUR_LOAD, getPlayer().getCurrentLoad());
  429. getPlayer().sendPacket(su);
  430. }
  431. /**
  432. * Drop Quest item using Config.RATE_DROP_QUEST
  433. * @param itemId : int Item Identifier of the item to be dropped
  434. * @param count(minCount, maxCount) : int Quantity of items to be dropped
  435. * @param neededCount : Quantity of items needed for quest
  436. * @param dropChance : int Base chance of drop, same as in droplist
  437. * @param sound : boolean indicating whether to play sound
  438. * @return boolean indicating whether player has requested number of items
  439. */
  440. public boolean dropQuestItems(int itemId, int count, int neededCount, int dropChance, boolean sound)
  441. {
  442. return dropQuestItems(itemId, count, count, neededCount, dropChance, sound);
  443. }
  444. public boolean dropQuestItems(int itemId, int minCount, int maxCount, int neededCount, int dropChance, boolean sound)
  445. {
  446. dropChance *= Config.RATE_DROP_QUEST / ((getPlayer().getParty() != null) ? getPlayer().getParty().getMemberCount() : 1);
  447. int currentCount = getQuestItemsCount(itemId);
  448. if (neededCount > 0 && currentCount >= neededCount)
  449. return true;
  450. if (currentCount >= neededCount)
  451. return true;
  452. int itemCount = 0;
  453. int random = Rnd.get(L2DropData.MAX_CHANCE);
  454. while (random < dropChance)
  455. {
  456. // Get the item quantity dropped
  457. if (minCount < maxCount)
  458. itemCount += Rnd.get(minCount, maxCount);
  459. else if (minCount == maxCount)
  460. itemCount += minCount;
  461. else
  462. itemCount++;
  463. // Prepare for next iteration if dropChance > L2DropData.MAX_CHANCE
  464. dropChance -= L2DropData.MAX_CHANCE;
  465. }
  466. if (itemCount > 0)
  467. {
  468. // if over neededCount, just fill the gap
  469. if (neededCount > 0 && currentCount + itemCount > neededCount)
  470. itemCount = neededCount - currentCount;
  471. // Inventory slot check
  472. if (!getPlayer().getInventory().validateCapacityByItemId(itemId))
  473. return false;
  474. // Give the item to Player
  475. getPlayer().addItem("Quest", itemId, itemCount, getPlayer().getTarget(), true);
  476. if (sound)
  477. playSound((currentCount + itemCount < neededCount) ? "Itemsound.quest_itemget" : "Itemsound.quest_middle");
  478. }
  479. return (neededCount > 0 && currentCount + itemCount >= neededCount);
  480. }
  481. //TODO: More radar functions need to be added when the radar class is complete.
  482. // BEGIN STUFF THAT WILL PROBABLY BE CHANGED
  483. public void addRadar(int x, int y, int z)
  484. {
  485. getPlayer().getRadar().addMarker(x, y, z);
  486. }
  487. public void removeRadar(int x, int y, int z)
  488. {
  489. getPlayer().getRadar().removeMarker(x, y, z);
  490. }
  491. public void clearRadar()
  492. {
  493. getPlayer().getRadar().removeAllMarkers();
  494. }
  495. // END STUFF THAT WILL PROBABLY BE CHANGED
  496. /**
  497. * Remove items from player's inventory when talking to NPC in order to have rewards.<BR><BR>
  498. * <U><I>Actions :</I></U>
  499. * <LI>Destroy quantity of items wanted</LI>
  500. * <LI>Send new inventory list to player</LI>
  501. * @param itemId : Identifier of the item
  502. * @param count : Quantity of items to destroy
  503. */
  504. public void takeItems(int itemId, int count)
  505. {
  506. // Get object item from player's inventory list
  507. L2ItemInstance item = getPlayer().getInventory().getItemByItemId(itemId);
  508. if (item == null)
  509. return;
  510. // Tests on count value in order not to have negative value
  511. if (count < 0 || count > item.getCount())
  512. count = item.getCount();
  513. // Destroy the quantity of items wanted
  514. if (itemId == 57)
  515. getPlayer().reduceAdena("Quest", count, getPlayer(), true);
  516. else
  517. getPlayer().destroyItemByItemId("Quest", itemId, count, getPlayer(), true);
  518. }
  519. /**
  520. * Send a packet in order to play sound at client terminal
  521. * @param sound
  522. */
  523. public void playSound(String sound)
  524. {
  525. getPlayer().sendPacket(new PlaySound(sound));
  526. }
  527. /**
  528. * Add XP and SP as quest reward
  529. * @param exp
  530. * @param sp
  531. */
  532. public void addExpAndSp(int exp, int sp)
  533. {
  534. getPlayer().addExpAndSp((int) getPlayer().calcStat(Stats.EXPSP_RATE, exp * Config.RATE_QUESTS_REWARD, null, null), (int) getPlayer().calcStat(Stats.EXPSP_RATE, sp * Config.RATE_QUESTS_REWARD, null, null));
  535. }
  536. /**
  537. * Return random value
  538. * @param max : max value for randomisation
  539. * @return int
  540. */
  541. public int getRandom(int max)
  542. {
  543. return Rnd.get(max);
  544. }
  545. /**
  546. * Return number of ticks from GameTimeController
  547. * @return int
  548. */
  549. public int getItemEquipped(int loc)
  550. {
  551. return getPlayer().getInventory().getPaperdollItemId(loc);
  552. }
  553. /**
  554. * Return the number of ticks from the GameTimeController
  555. * @return int
  556. */
  557. public int getGameTicks()
  558. {
  559. return GameTimeController.getGameTicks();
  560. }
  561. /**
  562. * Return true if quest is to exited on clean up by QuestStateManager
  563. * @return boolean
  564. */
  565. public final boolean isExitQuestOnCleanUp()
  566. {
  567. return _isExitQuestOnCleanUp;
  568. }
  569. /**
  570. * Return the QuestTimer object with the specified name
  571. * @return QuestTimer<BR> Return null if name does not exist
  572. */
  573. public void setIsExitQuestOnCleanUp(boolean isExitQuestOnCleanUp)
  574. {
  575. _isExitQuestOnCleanUp = isExitQuestOnCleanUp;
  576. }
  577. /**
  578. * Start a timer for quest.<BR><BR>
  579. * @param name<BR> The name of the timer. Will also be the value for event of onEvent
  580. * @param time<BR> The milisecond value the timer will elapse
  581. */
  582. public void startQuestTimer(String name, long time)
  583. {
  584. getQuest().startQuestTimer(name, time, null, getPlayer(), false);
  585. }
  586. public void startQuestTimer(String name, long time, L2NpcInstance npc)
  587. {
  588. getQuest().startQuestTimer(name, time, npc, getPlayer(), false);
  589. }
  590. public void startRepeatingQuestTimer(String name, long time)
  591. {
  592. getQuest().startQuestTimer(name, time, null, getPlayer(), true);
  593. }
  594. public void startRepeatingQuestTimer(String name, long time, L2NpcInstance npc)
  595. {
  596. getQuest().startQuestTimer(name, time, npc, getPlayer(), true);
  597. }
  598. /**
  599. * Return the QuestTimer object with the specified name
  600. * @return QuestTimer<BR> Return null if name does not exist
  601. */
  602. public final QuestTimer getQuestTimer(String name)
  603. {
  604. return getQuest().getQuestTimer(name, null, getPlayer());
  605. }
  606. /**
  607. * Add spawn for player instance
  608. * Return object id of newly spawned npc
  609. */
  610. public L2NpcInstance addSpawn(int npcId)
  611. {
  612. return addSpawn(npcId, getPlayer().getX(), getPlayer().getY(), getPlayer().getZ(), 0, false, 0);
  613. }
  614. public L2NpcInstance addSpawn(int npcId, int despawnDelay)
  615. {
  616. return addSpawn(npcId, getPlayer().getX(), getPlayer().getY(), getPlayer().getZ(), 0, false, despawnDelay);
  617. }
  618. public L2NpcInstance addSpawn(int npcId, int x, int y, int z)
  619. {
  620. return addSpawn(npcId, x, y, z, 0, false, 0);
  621. }
  622. /**
  623. * Add spawn for player instance
  624. * Will despawn after the spawn length expires
  625. * Uses player's coords and heading.
  626. * Adds a little randomization in the x y coords
  627. * Return object id of newly spawned npc
  628. */
  629. public L2NpcInstance addSpawn(int npcId, L2Character cha)
  630. {
  631. return addSpawn(npcId, cha, true, 0);
  632. }
  633. public L2NpcInstance addSpawn(int npcId, L2Character cha, int despawnDelay)
  634. {
  635. return addSpawn(npcId, cha.getX(), cha.getY(), cha.getZ(), cha.getHeading(), true, despawnDelay);
  636. }
  637. /**
  638. * Add spawn for player instance
  639. * Will despawn after the spawn length expires
  640. * Return object id of newly spawned npc
  641. */
  642. public L2NpcInstance addSpawn(int npcId, int x, int y, int z, int despawnDelay)
  643. {
  644. return addSpawn(npcId, x, y, z, 0, false, despawnDelay);
  645. }
  646. /**
  647. * Add spawn for player instance
  648. * Inherits coords and heading from specified L2Character instance.
  649. * It could be either the player, or any killed/attacked mob
  650. * Return object id of newly spawned npc
  651. */
  652. public L2NpcInstance addSpawn(int npcId, L2Character cha, boolean randomOffset, int despawnDelay)
  653. {
  654. return addSpawn(npcId, cha.getX(), cha.getY(), cha.getZ(), cha.getHeading(), randomOffset, despawnDelay);
  655. }
  656. /**
  657. * Add spawn for player instance
  658. * Return object id of newly spawned npc
  659. */
  660. public L2NpcInstance addSpawn(int npcId, int x, int y, int z, int heading, boolean randomOffset, int despawnDelay)
  661. {
  662. return getQuest().addSpawn(npcId, x, y, z, heading, randomOffset, despawnDelay, false);
  663. }
  664. /**
  665. * Add spawn for player instance
  666. * Return object id of newly spawned npc
  667. */
  668. public L2NpcInstance addSpawn(int npcId, int x, int y, int z, int heading, boolean randomOffset, int despawnDelay, boolean isSummonSpawn)
  669. {
  670. return getQuest().addSpawn(npcId, x, y, z, heading, randomOffset, despawnDelay, isSummonSpawn);
  671. }
  672. public String showHtmlFile(String fileName)
  673. {
  674. return getQuest().showHtmlFile(getPlayer(), fileName);
  675. }
  676. /**
  677. * Destroy element used by quest when quest is exited
  678. * @param repeatable
  679. * @return QuestState
  680. */
  681. public QuestState exitQuest(boolean repeatable)
  682. {
  683. if (isCompleted())
  684. return this;
  685. // Say quest is completed
  686. setState(State.COMPLETED);
  687. // Clean registered quest items
  688. int[] itemIdList = getQuest().getRegisteredItemIds();
  689. if (itemIdList != null)
  690. {
  691. for (int i = 0; i < itemIdList.length; i++)
  692. {
  693. takeItems(itemIdList[i], -1);
  694. }
  695. }
  696. // If quest is repeatable, delete quest from list of quest of the player and from database (quest CAN be created again => repeatable)
  697. if (repeatable)
  698. {
  699. getPlayer().delQuestState(getQuestName());
  700. Quest.deleteQuestInDb(this);
  701. _vars = null;
  702. }
  703. else
  704. {
  705. // Otherwise, delete variables for quest and update database (quest CANNOT be created again => not repeatable)
  706. if (_vars != null)
  707. for (String var : _vars.keySet())
  708. unset(var);
  709. Quest.updateQuestInDb(this);
  710. }
  711. return this;
  712. }
  713. public void showQuestionMark(int number)
  714. {
  715. getPlayer().sendPacket(new TutorialShowQuestionMark(number));
  716. }
  717. public void playTutorialVoice(String voice)
  718. {
  719. getPlayer().sendPacket(new PlaySound(2, voice, 0, 0, getPlayer().getX(), getPlayer().getY(), getPlayer().getZ()));
  720. }
  721. public void showTutorialHTML(String html)
  722. {
  723. String text = HtmCache.getInstance().getHtm("data/scripts/quests/255_Tutorial/" + html);
  724. if (text == null)
  725. {
  726. _log.warning("missing html page data/scripts/quests/255_Tutorial/" + html);
  727. text = "<html><body>File data/scripts/quests/255_Tutorial/" + html + " not found or file is empty.</body></html>";
  728. }
  729. getPlayer().sendPacket(new TutorialShowHtml(text));
  730. }
  731. public void closeTutorialHtml()
  732. {
  733. getPlayer().sendPacket(new TutorialCloseHtml());
  734. }
  735. public void onTutorialClientEvent(int number)
  736. {
  737. getPlayer().sendPacket(new TutorialEnableClientEvent(number));
  738. }
  739. public void dropItem(L2MonsterInstance npc, L2PcInstance player, int itemId, int count)
  740. {
  741. npc.dropItem(player, itemId, count);
  742. }
  743. }