Advertisement
Guest User

QuestState.java

a guest
Aug 3rd, 2019
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 30.78 KB | None | 0 0
  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.  
  17. import java.sql.Connection;
  18. import java.sql.PreparedStatement;
  19. import java.util.HashMap;
  20. import java.util.Map;
  21.  
  22. import net.sf.l2j.commons.config.Config;
  23. import net.sf.l2j.commons.db.DatabaseFactory;
  24. import net.sf.l2j.commons.util.Rnd;
  25. import net.sf.l2j.gameserver.cache.HtmCache;
  26. import net.sf.l2j.gameserver.model.actor.instance.L2MonsterInstance;
  27. import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  28. import net.sf.l2j.gameserver.model.item.DropData;
  29. import net.sf.l2j.gameserver.model.item.instance.ItemInstance;
  30. import net.sf.l2j.gameserver.model.item.kind.Premium;
  31. import net.sf.l2j.gameserver.model.itemcontainer.PcInventory;
  32. import net.sf.l2j.gameserver.network.SystemMessageId;
  33. import net.sf.l2j.gameserver.network.serverpackets.ExShowQuestMark;
  34. import net.sf.l2j.gameserver.network.serverpackets.InventoryUpdate;
  35. import net.sf.l2j.gameserver.network.serverpackets.PlaySound;
  36. import net.sf.l2j.gameserver.network.serverpackets.QuestList;
  37. import net.sf.l2j.gameserver.network.serverpackets.StatusUpdate;
  38. import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
  39. import net.sf.l2j.gameserver.network.serverpackets.TutorialCloseHtml;
  40. import net.sf.l2j.gameserver.network.serverpackets.TutorialEnableClientEvent;
  41. import net.sf.l2j.gameserver.network.serverpackets.TutorialShowHtml;
  42. import net.sf.l2j.gameserver.network.serverpackets.TutorialShowQuestionMark;
  43.  
  44. import org.slf4j.Logger;
  45. import org.slf4j.LoggerFactory;
  46.  
  47. /**
  48.  * @author Luis Arias
  49.  */
  50. public final class QuestState
  51. {
  52.     protected static final Logger _log = LoggerFactory.getLogger(Quest.class.getName());
  53.    
  54.     public static final String SOUND_ACCEPT = "ItemSound.quest_accept";
  55.     public static final String SOUND_ITEMGET = "ItemSound.quest_itemget";
  56.     public static final String SOUND_MIDDLE = "ItemSound.quest_middle";
  57.     public static final String SOUND_FINISH = "ItemSound.quest_finish";
  58.     public static final String SOUND_GIVEUP = "ItemSound.quest_giveup";
  59.     public static final String SOUND_JACKPOT = "ItemSound.quest_jackpot";
  60.     public static final String SOUND_FANFARE = "ItemSound.quest_fanfare_2";
  61.     public static final String SOUND_TUTORIAL = "ItemSound.quest_tutorial";
  62.     public static final String SOUND_BEFORE_BATTLE = "Itemsound.quest_before_battle";
  63.     public static final String SOUND_HORROR2 = "SkillSound5.horror_02";
  64.     public static final String SOUND_FANFARE_MIDDLE = "ItemSound.quest_fanfare_middle";
  65.     public static final String SOUND_FANFARE2 = "ItemSound.quest_fanfare_2";
  66.     public static final String SOUND_BROKEN_KEY = "ItemSound2.broken_key";
  67.     public static final String SOUND_ENCHANT_SUCESS = "ItemSound3.sys_enchant_sucess";
  68.     public static final String SOUND_ENCHANT_FAILED = "ItemSound3.sys_enchant_failed";
  69.     public static final String SOUND_ED_CHIMES05 = "AmdSound.ed_chimes_05";
  70.     public static final String SOUND_ARMOR_WOOD_3 = "ItemSound.armor_wood_3";
  71.     public static final String SOUND_ITEM_DROP_EQUIP_ARMOR_CLOTH = "ItemSound.item_drop_equip_armor_cloth";
  72.    
  73.     private static final String QUEST_SET_VAR = "REPLACE INTO character_quests (charId,name,var,value) VALUES (?,?,?,?)";
  74.     private static final String QUEST_DEL_VAR = "DELETE FROM character_quests WHERE charId=? AND name=? AND var=?";
  75.     private static final String QUEST_DELETE = "DELETE FROM character_quests WHERE charId=? AND name=?";
  76.     private static final String QUEST_COMPLETE = "DELETE FROM character_quests WHERE charId=? AND name=? AND var<>'<state>'";
  77.    
  78.     public static final byte DROP_DIVMOD = 0;
  79.     public static final byte DROP_FIXED_RATE = 1;
  80.     public static final byte DROP_FIXED_COUNT = 2;
  81.     public static final byte DROP_FIXED_BOTH = 3;
  82.    
  83.     private final L2PcInstance _player;
  84.     private final Quest _quest;
  85.     private byte _state;
  86.     private final Map<String, String> _vars = new HashMap<>();
  87.    
  88.     /**
  89.      * Constructor of the QuestState : save the quest in the list of quests of the player.<BR/>
  90.      * <BR/>
  91.      * <U><I>Actions :</U></I><BR/>
  92.      * <LI>Save informations in the object QuestState created (Quest, Player, Completion, State)</LI> <LI>Add the QuestState in the player's list of quests by using setQuestState()</LI> <LI>Add drops gotten by the quest</LI> <BR/>
  93.      * @param quest : quest associated with the QuestState
  94.      * @param player : L2PcInstance pointing out the player
  95.      * @param state : state of the quest
  96.      */
  97.     QuestState(L2PcInstance player, Quest quest, byte state)
  98.     {
  99.         _player = player;
  100.         _quest = quest;
  101.         _state = state;
  102.        
  103.         _player.setQuestState(this);
  104.     }
  105.    
  106.     /**
  107.      * Return the L2PcInstance
  108.      * @return L2PcInstance
  109.      */
  110.     public L2PcInstance getPlayer()
  111.     {
  112.         return _player;
  113.     }
  114.    
  115.     /**
  116.      * Return the quest
  117.      * @return Quest
  118.      */
  119.     public Quest getQuest()
  120.     {
  121.         return _quest;
  122.     }
  123.    
  124.     /**
  125.      * Return the state of the quest
  126.      * @return State
  127.      */
  128.     public byte getState()
  129.     {
  130.         return _state;
  131.     }
  132.    
  133.     /**
  134.      * Return true if quest just created, false otherwise
  135.      * @return
  136.      */
  137.     public boolean isCreated()
  138.     {
  139.         return (_state == Quest.STATE_CREATED);
  140.     }
  141.    
  142.     /**
  143.      * Return true if quest completed, false otherwise
  144.      * @return boolean
  145.      */
  146.     public boolean isCompleted()
  147.     {
  148.         return (_state == Quest.STATE_COMPLETED);
  149.     }
  150.    
  151.     /**
  152.      * Return true if quest started, false otherwise
  153.      * @return boolean
  154.      */
  155.     public boolean isStarted()
  156.     {
  157.         return (_state == Quest.STATE_STARTED);
  158.     }
  159.    
  160.     /**
  161.      * Set state of the quest.
  162.      * <ul>
  163.      * <li>Remove drops from previous state</li>
  164.      * <li>Set new state of the quest</li>
  165.      * <li>Add drop for new state</li>
  166.      * <li>Update information in database</li>
  167.      * <li>Send packet QuestList to client</li>
  168.      * </ul>
  169.      * @param state
  170.      */
  171.     public void setState(byte state)
  172.     {
  173.         if (_state != state)
  174.         {
  175.             _state = state;
  176.            
  177.             setQuestVarInDb("<state>", String.valueOf(_state));
  178.            
  179.             _player.sendPacket(new QuestList(_player));
  180.         }
  181.     }
  182.    
  183.     /**
  184.      * Destroy element used by quest when quest is exited
  185.      * @param repeatable
  186.      */
  187.     public void exitQuest(boolean repeatable)
  188.     {
  189.         if (!isStarted())
  190.         {
  191.             return;
  192.         }
  193.        
  194.         // Remove quest from player's notifyDeath list.
  195.         _player.removeNotifyQuestOfDeath(this);
  196.        
  197.         // Remove/Complete quest.
  198.         if (repeatable)
  199.         {
  200.             _player.delQuestState(this);
  201.             _player.sendPacket(new QuestList(_player));
  202.         }
  203.         else
  204.         {
  205.             setState(Quest.STATE_COMPLETED);
  206.         }
  207.        
  208.         // Remove quest variables.
  209.         _vars.clear();
  210.        
  211.         // Remove registered quest items.
  212.         int[] itemIdList = _quest.getItemsIds();
  213.         if (itemIdList != null)
  214.         {
  215.             for (int itemId : itemIdList)
  216.             {
  217.                 takeItems(itemId, -1);
  218.             }
  219.         }
  220.        
  221.         try (Connection con = DatabaseFactory.getInstance().getConnection())
  222.         {
  223.             PreparedStatement statement;
  224.             if (repeatable)
  225.             {
  226.                 statement = con.prepareStatement(QUEST_DELETE);
  227.             }
  228.             else
  229.             {
  230.                 statement = con.prepareStatement(QUEST_COMPLETE);
  231.             }
  232.            
  233.             statement.setInt(1, _player.getObjectId());
  234.             statement.setString(2, _quest.getName());
  235.             statement.executeUpdate();
  236.             statement.close();
  237.         }
  238.         catch (Exception e)
  239.         {
  240.             _log.warn("could not delete char quest:", e);
  241.         }
  242.     }
  243.    
  244.     /**
  245.      * Add player to get notification of characters death
  246.      */
  247.     public void addNotifyOfDeath()
  248.     {
  249.         if (_player != null)
  250.         {
  251.             _player.addNotifyQuestOfDeath(this);
  252.         }
  253.     }
  254.    
  255.     /**
  256.      * Return value of parameter "val" after adding the couple (var,val) in class variable "vars".<BR>
  257.      * <BR>
  258.      * <U><I>Actions :</I></U><BR>
  259.      * <LI>Initialize class variable "vars" if is null</LI> <LI>Initialize parameter "val" if is null</LI> <LI>Add/Update couple (var,val) in class variable FastMap "vars"</LI> <LI>If the key represented by "var" exists in FastMap "vars", the couple (var,val) is updated in the database. The key is
  260.      * known as existing if the preceding value of the key (given as result of function put()) is not null.<BR>
  261.      * If the key doesn't exist, the couple is added/created in the database</LI>
  262.      * @param var : String indicating the name of the variable for quest
  263.      * @param value : String indicating the value of the variable for quest
  264.      */
  265.     public void set(String var, String value)
  266.     {
  267.         if (var == null || var.isEmpty() || value == null || value.isEmpty())
  268.         {
  269.             return;
  270.         }
  271.        
  272.         // FastMap.put() returns previous value associated with specified key, or null if there was no mapping for key.
  273.         String old = _vars.put(var, value);
  274.        
  275.         setQuestVarInDb(var, value);
  276.        
  277.         if ("cond".equals(var))
  278.         {
  279.             try
  280.             {
  281.                 int previousVal = 0;
  282.                 try
  283.                 {
  284.                     previousVal = Integer.parseInt(old);
  285.                 }
  286.                 catch (Exception ex)
  287.                 {
  288.                     previousVal = 0;
  289.                 }
  290.                 setCond(Integer.parseInt(value), previousVal);
  291.             }
  292.             catch (Exception e)
  293.             {
  294.                 _log.warn(_player.getName() + ", " + _quest.getName() + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
  295.             }
  296.         }
  297.     }
  298.    
  299.     /**
  300.      * Add parameter used in quests.
  301.      * @param var : String pointing out the name of the variable for quest
  302.      * @param value : String pointing out the value of the variable for quest
  303.      */
  304.     public void setInternal(String var, String value)
  305.     {
  306.         if (var == null || var.isEmpty() || value == null || value.isEmpty())
  307.         {
  308.             return;
  309.         }
  310.        
  311.         _vars.put(var, value);
  312.     }
  313.    
  314.     /**
  315.      * Internally handles the progression of the quest so that it is ready for sending appropriate packets to the client<BR>
  316.      * <BR>
  317.      * <U><I>Actions :</I></U><BR>
  318.      * <LI>Check if the new progress number resets the quest to a previous (smaller) step</LI> <LI>If not, check if quest progress steps have been skipped</LI> <LI>If skipped, prepare the variable completedStateFlags appropriately to be ready for sending to clients</LI> <LI>If no steps were skipped,
  319.      * flags do not need to be prepared...</LI> <LI>If the passed step resets the quest to a previous step, reset such that steps after the parameter are not considered, while skipped steps before the parameter, if any, maintain their info</LI>
  320.      * @param cond : int indicating the step number for the current quest progress (as will be shown to the client)
  321.      * @param old : int indicating the previously noted step For more info on the variable communicating the progress steps to the client, please see
  322.      */
  323.     private void setCond(int cond, int old)
  324.     {
  325.         // if there is no change since last setting, there is nothing to do here
  326.         if (cond == old)
  327.         {
  328.             return;
  329.         }
  330.        
  331.         int completedStateFlags = 0;
  332.        
  333.         // cond 0 and 1 do not need completedStateFlags. Also, if cond > 1, the 1st step must
  334.         // always exist (i.e. it can never be skipped). So if cond is 2, we can still safely
  335.         // assume no steps have been skipped.
  336.         // Finally, more than 31 steps CANNOT be supported in any way with skipping.
  337.         if (cond < 3 || cond > 31)
  338.         {
  339.             unset("__compltdStateFlags");
  340.         }
  341.         else
  342.         {
  343.             completedStateFlags = getInt("__compltdStateFlags");
  344.         }
  345.        
  346.         // case 1: No steps have been skipped so far...
  347.         if (completedStateFlags == 0)
  348.         {
  349.             // check if this step also doesn't skip anything. If so, no further work is needed
  350.             // also, in this case, no work is needed if the state is being reset to a smaller value
  351.             // in those cases, skip forward to informing the client about the change...
  352.            
  353.             // ELSE, if we just now skipped for the first time...prepare the flags!!!
  354.             if (cond > (old + 1))
  355.             {
  356.                 // set the most significant bit to 1 (indicates that there exist skipped states)
  357.                 // also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
  358.                 // what the cond says)
  359.                 completedStateFlags = 0x80000001;
  360.                
  361.                 // since no flag had been skipped until now, the least significant bits must all
  362.                 // be set to 1, up until "old" number of bits.
  363.                 completedStateFlags |= ((1 << old) - 1);
  364.                
  365.                 // now, just set the bit corresponding to the passed cond to 1 (current step)
  366.                 completedStateFlags |= (1 << (cond - 1));
  367.                 set("__compltdStateFlags", String.valueOf(completedStateFlags));
  368.             }
  369.         }
  370.         // case 2: There were exist previously skipped steps
  371.         else
  372.         {
  373.             // if this is a push back to a previous step, clear all completion flags ahead
  374.             if (cond < old)
  375.             {
  376.                 completedStateFlags &= ((1 << cond) - 1); // note, this also unsets the flag indicating that there exist skips
  377.                
  378.                 // now, check if this resulted in no steps being skipped any more
  379.                 if (completedStateFlags == ((1 << cond) - 1))
  380.                 {
  381.                     unset("__compltdStateFlags");
  382.                 }
  383.                 else
  384.                 {
  385.                     // set the most significant bit back to 1 again, to correctly indicate that this skips states.
  386.                     // also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
  387.                     // what the cond says)
  388.                     completedStateFlags |= 0x80000001;
  389.                     set("__compltdStateFlags", String.valueOf(completedStateFlags));
  390.                 }
  391.             }
  392.             // if this moves forward, it changes nothing on previously skipped steps...so just mark this
  393.             // state and we are done
  394.             else
  395.             {
  396.                 completedStateFlags |= (1 << (cond - 1));
  397.                 set("__compltdStateFlags", String.valueOf(completedStateFlags));
  398.             }
  399.         }
  400.        
  401.         // send a packet to the client to inform it of the quest progress (step change)
  402.         _player.sendPacket(new QuestList(_player));
  403.        
  404.         if (_quest.isRealQuest() && cond > 0)
  405.         {
  406.             _player.sendPacket(new ExShowQuestMark(_quest.getQuestId()));
  407.         }
  408.     }
  409.    
  410.     /**
  411.      * Remove the variable of quest from the list of variables for the quest.<BR>
  412.      * <BR>
  413.      * <U><I>Concept : </I></U> Remove the variable of quest represented by "var" from the class variable FastMap "vars" and from the database.
  414.      * @param var : String designating the variable for the quest to be deleted
  415.      */
  416.     public void unset(String var)
  417.     {
  418.         if (_vars.remove(var) != null)
  419.         {
  420.             removeQuestVarInDb(var);
  421.         }
  422.     }
  423.    
  424.     /**
  425.      * Return the value of the variable of quest represented by "var"
  426.      * @param var : name of the variable of quest
  427.      * @return String
  428.      */
  429.     public String get(String var)
  430.     {
  431.         return _vars.get(var);
  432.     }
  433.    
  434.     /**
  435.      * Return the value of the variable of quest represented by "var"
  436.      * @param var : String designating the variable for the quest
  437.      * @return int
  438.      */
  439.     public int getInt(String var)
  440.     {
  441.         final String variable = _vars.get(var);
  442.         if (variable == null || variable.isEmpty())
  443.         {
  444.             return 0;
  445.         }
  446.        
  447.         int value = 0;
  448.         try
  449.         {
  450.             value = Integer.parseInt(variable);
  451.         }
  452.         catch (Exception e)
  453.         {
  454.             _log.warn(_player.getName() + ": variable " + var + " isn't an integer: " + value + " ! " + e.getMessage(), e);
  455.         }
  456.        
  457.         return value;
  458.     }
  459.    
  460.     /**
  461.      * Set in the database the quest for the player.
  462.      * @param var : String designating the name of the variable for the quest
  463.      * @param value : String designating the value of the variable for the quest
  464.      */
  465.     private void setQuestVarInDb(String var, String value)
  466.     {
  467.         try (Connection con = DatabaseFactory.getInstance().getConnection())
  468.         {
  469.             PreparedStatement statement = con.prepareStatement(QUEST_SET_VAR);
  470.             statement.setInt(1, _player.getObjectId());
  471.             statement.setString(2, _quest.getName());
  472.             statement.setString(3, var);
  473.             statement.setString(4, value);
  474.             statement.executeUpdate();
  475.             statement.close();
  476.         }
  477.         catch (Exception e)
  478.         {
  479.             _log.warn("could not insert char quest:", e);
  480.         }
  481.     }
  482.    
  483.     /**
  484.      * Delete a variable of player's quest from the database.
  485.      * @param var : String designating the variable characterizing the quest
  486.      */
  487.     private void removeQuestVarInDb(String var)
  488.     {
  489.         try (Connection con = DatabaseFactory.getInstance().getConnection())
  490.         {
  491.             PreparedStatement statement = con.prepareStatement(QUEST_DEL_VAR);
  492.             statement.setInt(1, _player.getObjectId());
  493.             statement.setString(2, _quest.getName());
  494.             statement.setString(3, var);
  495.             statement.executeUpdate();
  496.             statement.close();
  497.         }
  498.         catch (Exception e)
  499.         {
  500.             _log.warn("could not delete char quest:", e);
  501.         }
  502.     }
  503.    
  504.     /**
  505.      * Check for an item in player's inventory.
  506.      * @param itemId the ID of the item to check for
  507.      * @return {@code true} if the item exists in player's inventory, {@code false} otherwise
  508.      */
  509.     public boolean hasQuestItems(int itemId)
  510.     {
  511.         return _player.getInventory().getItemByItemId(itemId) != null;
  512.     }
  513.    
  514.     /**
  515.      * Check for multiple items in player's inventory.
  516.      * @param itemIds a list of item IDs to check for
  517.      * @return {@code true} if all items exist in player's inventory, {@code false} otherwise
  518.      */
  519.     public boolean hasQuestItems(int... itemIds)
  520.     {
  521.         final PcInventory inv = _player.getInventory();
  522.         for (int itemId : itemIds)
  523.         {
  524.             if (inv.getItemByItemId(itemId) == null)
  525.             {
  526.                 return false;
  527.             }
  528.         }
  529.         return true;
  530.     }
  531.    
  532.     /**
  533.      * Check if player possesses at least one given item.
  534.      * @param itemIds a list of item IDs to check for
  535.      * @return {@code true} if at least one item exists in player's inventory, {@code false} otherwise
  536.      */
  537.     public boolean hasAtLeastOneQuestItem(int... itemIds)
  538.     {
  539.         return _player.getInventory().hasAtLeastOneItem(itemIds);
  540.     }
  541.    
  542.     /**
  543.      * @param itemId : ID of the item wanted to be count
  544.      * @return the quantity of one sort of item hold by the player
  545.      */
  546.     public int getQuestItemsCount(int itemId)
  547.     {
  548.         int count = 0;
  549.        
  550.         for (ItemInstance item : _player.getInventory().getItems())
  551.         {
  552.             if (item != null && item.getItemId() == itemId)
  553.             {
  554.                 count += item.getCount();
  555.             }
  556.         }
  557.        
  558.         return count;
  559.     }
  560.    
  561.     /**
  562.      * @param loc A paperdoll slot to check.
  563.      * @return the id of the item in the loc paperdoll slot.
  564.      */
  565.     public int getItemEquipped(int loc)
  566.     {
  567.         return _player.getInventory().getPaperdollItemId(loc);
  568.     }
  569.    
  570.     /**
  571.      * Return the level of enchantment on the weapon of the player(Done specifically for weapon SA's)
  572.      * @param itemId : ID of the item to check enchantment
  573.      * @return int
  574.      */
  575.     public int getEnchantLevel(int itemId)
  576.     {
  577.         final ItemInstance enchanteditem = _player.getInventory().getItemByItemId(itemId);
  578.         if (enchanteditem == null)
  579.         {
  580.             return 0;
  581.         }
  582.        
  583.         return enchanteditem.getEnchantLevel();
  584.     }
  585.    
  586.     /**
  587.      * Give items to the player's inventory.
  588.      * @param itemId : Identifier of the item.
  589.      * @param itemCount : Quantity of items to add.
  590.      */
  591.     public void giveItems(int itemId, int itemCount)
  592.     {
  593.         giveItems(itemId, itemCount, 0);
  594.     }
  595.    
  596.     /**
  597.      * Give items to the player's inventory.
  598.      * @param itemId : Identifier of the item.
  599.      * @param itemCount : Quantity of items to add.
  600.      * @param enchantLevel : Enchant level of items to add.
  601.      */
  602.     public void giveItems(int itemId, int itemCount, int enchantLevel)
  603.     {
  604.         // Incorrect amount.
  605.         if (itemCount <= 0)
  606.         {
  607.             return;
  608.         }
  609.        
  610.         // Add items to player's inventory.
  611.         final ItemInstance item = _player.getInventory().addItem("Quest", itemId, itemCount, _player, _player);
  612.         if (item == null)
  613.         {
  614.             return;
  615.         }
  616.        
  617.         // Set enchant level for the item.
  618.         if (enchantLevel > 0)
  619.         {
  620.             item.setEnchantLevel(enchantLevel);
  621.         }
  622.        
  623.         // Send message to the client.
  624.         if (itemId == 57)
  625.         {
  626.             SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.EARNED_S1_ADENA);
  627.             smsg.addItemNumber(itemCount);
  628.             _player.sendPacket(smsg);
  629.         }
  630.         else
  631.         {
  632.             if (itemCount > 1)
  633.             {
  634.                 SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S);
  635.                 smsg.addItemName(itemId);
  636.                 smsg.addItemNumber(itemCount);
  637.                 _player.sendPacket(smsg);
  638.             }
  639.             else
  640.             {
  641.                 SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.EARNED_ITEM_S1);
  642.                 smsg.addItemName(itemId);
  643.                 _player.sendPacket(smsg);
  644.             }
  645.         }
  646.        
  647.         // Send status update packet.
  648.         StatusUpdate su = new StatusUpdate(_player);
  649.         su.addAttribute(StatusUpdate.CUR_LOAD, _player.getCurrentLoad());
  650.         _player.sendPacket(su);
  651.     }
  652.    
  653.     /**
  654.      * Remove items from the player's inventory.
  655.      * @param itemId : Identifier of the item.
  656.      * @param itemCount : Quantity of items to destroy.
  657.      */
  658.     public void takeItems(int itemId, int itemCount)
  659.     {
  660.         // Find item in player's inventory.
  661.         final ItemInstance item = _player.getInventory().getItemByItemId(itemId);
  662.         if (item == null)
  663.         {
  664.             return;
  665.         }
  666.        
  667.         // Tests on count value and set correct value if necessary.
  668.         if (itemCount < 0 || itemCount > item.getCount())
  669.         {
  670.             itemCount = item.getCount();
  671.         }
  672.        
  673.         // Disarm item, if equipped.
  674.         if (item.isEquipped())
  675.         {
  676.             ItemInstance[] unequiped = _player.getInventory().unEquipItemInBodySlotAndRecord(item.getItem().getBodyPart());
  677.             InventoryUpdate iu = new InventoryUpdate();
  678.             for (ItemInstance itm : unequiped)
  679.             {
  680.                 iu.addModifiedItem(itm);
  681.             }
  682.            
  683.             _player.sendPacket(iu);
  684.             _player.broadcastUserInfo();
  685.         }
  686.        
  687.         // Destroy the quantity of items wanted.
  688.         _player.destroyItemByItemId("Quest", itemId, itemCount, _player, true);
  689.     }
  690.    
  691.     /**
  692.      * Drop items to the player's inventory. Rate is 100%, amount is affected by Config.RATE_QUEST_DROP.
  693.      * @param itemId : Identifier of the item to be dropped.
  694.      * @param count : Quantity of items to be dropped.
  695.      * @param neededCount : Quantity of items needed to complete the task. If set to 0, unlimited amount is collected.
  696.      * @return boolean : Indicating whether item quantity has been reached.
  697.      */
  698.     public boolean dropItemsAlways(int itemId, int count, int neededCount)
  699.     {
  700.         return dropItems(itemId, count, neededCount, DropData.MAX_CHANCE, DROP_FIXED_RATE);
  701.     }
  702.    
  703.     /**
  704.      * Данный метод будет служить для РґСЂРѕРїР° квестовых предметов СЃ монстров РЅР° РїРѕР». (Авто-лут игнорируется)
  705.      *
  706.     * @param npc : Monster of items to be dropped.
  707.     * @param player : Players for dropped.
  708.     * @param itemId : Identifier of the item to be dropped.
  709.     * @param count : Quantity of items to be dropped.
  710.      */
  711.     public void dropItem(L2MonsterInstance npc, L2PcInstance player, int itemId, int count)
  712.     {
  713.         npc.dropItem(player, itemId, count);
  714.     }
  715.    
  716.     /**
  717.      * Drop items to the player's inventory. Rate and amount is affected by DIVMOD of Config.RATE_QUEST_DROP.
  718.      * @param itemId : Identifier of the item to be dropped.
  719.      * @param count : Quantity of items to be dropped.
  720.      * @param neededCount : Quantity of items needed to complete the task. If set to 0, unlimited amount is collected.
  721.      * @param dropChance : Item drop rate (100% chance is defined by the L2DropData.MAX_CHANCE = 1.000.000).
  722.      * @return boolean : Indicating whether item quantity has been reached.
  723.      */
  724.     public boolean dropItems(int itemId, int count, int neededCount, int dropChance)
  725.     {
  726.         return dropItems(itemId, count, neededCount, dropChance, DROP_DIVMOD);
  727.     }
  728.    
  729.     /**
  730.      * Drop items to the player's inventory.
  731.      * @param itemId : Identifier of the item to be dropped.
  732.      * @param count : Quantity of items to be dropped.
  733.      * @param neededCount : Quantity of items needed to complete the task. If set to 0, unlimited amount is collected.
  734.      * @param dropChance : Item drop rate (100% chance is defined by the L2DropData.MAX_CHANCE = 1.000.000).
  735.      * @param type : Item drop behavior: DROP_DIVMOD (rate and), DROP_FIXED_RATE, DROP_FIXED_COUNT or DROP_FIXED_BOTH
  736.      * @return boolean : Indicating whether item quantity has been reached.
  737.      */
  738.     public boolean dropItems(int itemId, int count, int neededCount, int dropChance, byte type)
  739.     {
  740.         // Get current amount of item.
  741.         final int currentCount = getQuestItemsCount(itemId);
  742.        
  743.         // Required amount reached already?
  744.         if (neededCount > 0 && currentCount >= neededCount)
  745.         {
  746.             return true;
  747.         }
  748.        
  749.         int amount = 0;
  750.         switch (type)
  751.         {
  752.             case DROP_DIVMOD:
  753.                 dropChance *= Config.RATE_QUEST_DROP;
  754.                 amount = count * (dropChance / DropData.MAX_CHANCE);
  755.                 if (Rnd.get(DropData.MAX_CHANCE) < dropChance % DropData.MAX_CHANCE)
  756.                 {
  757.                     amount += count;
  758.                 }
  759.                 break;
  760.            
  761.             case DROP_FIXED_RATE:
  762.                 if (Rnd.get(DropData.MAX_CHANCE) < dropChance)
  763.                 {
  764.                     amount = (int) (count * Config.RATE_QUEST_DROP);
  765.                 }
  766.                 break;
  767.            
  768.             case DROP_FIXED_COUNT:
  769.                 if (Rnd.get(DropData.MAX_CHANCE) < dropChance * Config.RATE_QUEST_DROP)
  770.                 {
  771.                     amount = count;
  772.                 }
  773.                 break;
  774.            
  775.             case DROP_FIXED_BOTH:
  776.                 if (Rnd.get(DropData.MAX_CHANCE) < dropChance)
  777.                 {
  778.                     amount = count;
  779.                 }
  780.                 break;
  781.         }
  782.        
  783.         boolean reached = false;
  784.         if (amount > 0)
  785.         {
  786.             // Limit count to reach required amount.
  787.             if (neededCount > 0)
  788.             {
  789.                 reached = (currentCount + amount) >= neededCount;
  790.                 amount = (reached) ? neededCount - currentCount : amount;
  791.             }
  792.            
  793.             // Inventory slot check.
  794.             if (!_player.getInventory().validateCapacityByItemId(itemId))
  795.             {
  796.                 return false;
  797.             }
  798.            
  799.             // Give items to the player.
  800.             giveItems(itemId, amount, 0);
  801.            
  802.             // Play the sound.
  803.             playSound(reached ? SOUND_MIDDLE : SOUND_ITEMGET);
  804.         }
  805.        
  806.         return neededCount > 0 && reached;
  807.     }
  808.    
  809.     /**
  810.      * Drop multiple items to the player's inventory. Rate and amount is affected by DIVMOD of Config.RATE_QUEST_DROP.
  811.      * @param rewardsInfos : Infos regarding drops (itemId, count, neededCount, dropChance).
  812.      * @return boolean : Indicating whether item quantity has been reached.
  813.      */
  814.     public boolean dropMultipleItems(int[][] rewardsInfos)
  815.     {
  816.         return dropMultipleItems(rewardsInfos, DROP_DIVMOD);
  817.     }
  818.    
  819.     /**
  820.      * Drop items to the player's inventory.
  821.      * @param rewardsInfos : Infos regarding drops (itemId, count, neededCount, dropChance).
  822.      * @param type : Item drop behavior: DROP_DIVMOD (rate and), DROP_FIXED_RATE, DROP_FIXED_COUNT or DROP_FIXED_BOTH
  823.      * @return boolean : Indicating whether item quantity has been reached.
  824.      */
  825.     public boolean dropMultipleItems(int[][] rewardsInfos, byte type)
  826.     {
  827.         // Used for the sound.
  828.         boolean sendSound = false;
  829.        
  830.         // Used for the reached state.
  831.         boolean reached = true;
  832.        
  833.         // For each reward type, calculate the probability of drop.
  834.         for (int[] info : rewardsInfos)
  835.         {
  836.             final int itemId = info[0];
  837.             final int currentCount = getQuestItemsCount(itemId);
  838.             final int neededCount = info[2];
  839.            
  840.             // Required amount reached already?
  841.             if (neededCount > 0 && currentCount >= neededCount)
  842.             {
  843.                 continue;
  844.             }
  845.            
  846.             final int count = info[1];
  847.            
  848.             int dropChance = info[3];
  849.             int amount = 0;
  850.            
  851.             switch (type)
  852.             {
  853.                 case DROP_DIVMOD:
  854.                     dropChance *= Config.RATE_QUEST_DROP;
  855.                     amount = count * (dropChance / DropData.MAX_CHANCE);
  856.                     if (Rnd.get(DropData.MAX_CHANCE) < dropChance % DropData.MAX_CHANCE)
  857.                     {
  858.                         amount += count;
  859.                     }
  860.                     break;
  861.                
  862.                 case DROP_FIXED_RATE:
  863.                     if (Rnd.get(DropData.MAX_CHANCE) < dropChance)
  864.                     {
  865.                         amount = (int) (count * Config.RATE_QUEST_DROP);
  866.                     }
  867.                     break;
  868.                
  869.                 case DROP_FIXED_COUNT:
  870.                     if (Rnd.get(DropData.MAX_CHANCE) < dropChance * Config.RATE_QUEST_DROP)
  871.                     {
  872.                         amount = count;
  873.                     }
  874.                     break;
  875.                
  876.                 case DROP_FIXED_BOTH:
  877.                     if (Rnd.get(DropData.MAX_CHANCE) < dropChance)
  878.                     {
  879.                         amount = count;
  880.                     }
  881.                     break;
  882.             }
  883.            
  884.             if (amount > 0)
  885.             {
  886.                 // Limit count to reach required amount.
  887.                 if (neededCount > 0)
  888.                 {
  889.                     amount = ((currentCount + amount) >= neededCount) ? neededCount - currentCount : amount;
  890.                 }
  891.                
  892.                 // Inventory slot check.
  893.                 if (!_player.getInventory().validateCapacityByItemId(itemId))
  894.                 {
  895.                     continue;
  896.                 }
  897.                
  898.                 // Give items to the player.
  899.                 giveItems(itemId, amount, 0);
  900.                
  901.                 // Send sound.
  902.                 sendSound = true;
  903.                
  904.                 // Illimited needed count or current count being inferior to needed count means the state isn't reached.
  905.                 if (neededCount <= 0 || ((currentCount + amount) < neededCount))
  906.                 {
  907.                     reached = false;
  908.                 }
  909.             }
  910.         }
  911.        
  912.         // Play the sound.
  913.         if (sendSound)
  914.         {
  915.             playSound((reached) ? SOUND_MIDDLE : SOUND_ITEMGET);
  916.         }
  917.        
  918.         return reached;
  919.     }
  920.    
  921.     /**
  922.      * Reward player with items. The amount is affected by Config.RATE_QUEST_REWARD or Config.RATE_QUEST_REWARD_ADENA.
  923.      * @param itemId : Identifier of the item.
  924.      * @param itemCount : Quantity of item to reward before applying multiplier.
  925.      */
  926.     public void rewardItems(int itemId, int itemCount)
  927.     {
  928.         if (itemId == 57)
  929.         {
  930.             giveItems(itemId, (int) (itemCount * Config.RATE_QUEST_REWARD_ADENA), 0);
  931.         }
  932.         else
  933.         {
  934.             double reward = itemCount * Config.RATE_QUEST_REWARD;
  935.             reward *= _player.getPremiumAttribute(Premium.MODIFIER_QUEST);
  936.            
  937.             giveItems(itemId, (int) reward, 0);
  938.         }
  939.     }
  940.    
  941.     /**
  942.      * Reward player with EXP and SP. The amount is affected by Config.RATE_QUEST_REWARD_XP and Config.RATE_QUEST_REWARD_SP
  943.      * @param exp : Experience amount.
  944.      * @param sp : Skill point amount.
  945.      */
  946.     public void rewardExpAndSp(long exp, int sp)
  947.     {
  948.         _player.addExpAndSp((long) (exp * Config.RATE_QUEST_REWARD_XP), (int) (sp * Config.RATE_QUEST_REWARD_SP));
  949.     }
  950.    
  951.     // TODO: More radar functions need to be added when the radar class is complete.
  952.     // BEGIN STUFF THAT WILL PROBABLY BE CHANGED
  953.    
  954.     public void addRadar(int x, int y, int z)
  955.     {
  956.         _player.getRadar().addMarker(x, y, z);
  957.     }
  958.    
  959.     public void removeRadar(int x, int y, int z)
  960.     {
  961.         _player.getRadar().removeMarker(x, y, z);
  962.     }
  963.    
  964.     public void clearRadar()
  965.     {
  966.         _player.getRadar().removeAllMarkers();
  967.     }
  968.    
  969.     // END STUFF THAT WILL PROBABLY BE CHANGED
  970.    
  971.     /**
  972.      * Send a packet in order to play sound at client terminal
  973.      * @param sound
  974.      */
  975.     public void playSound(String sound)
  976.     {
  977.         _player.sendPacket(new PlaySound(sound));
  978.     }
  979.    
  980.     public void showQuestionMark(int number)
  981.     {
  982.         _player.sendPacket(new TutorialShowQuestionMark(number));
  983.     }
  984.    
  985.     public void playTutorialVoice(String voice)
  986.     {
  987.         _player.sendPacket(new PlaySound(2, voice, 0, 0, _player.getX(), _player.getY(), _player.getZ()));
  988.     }
  989.    
  990.     public void showTutorialHTML(String html)
  991.     {
  992.         String text = HtmCache.getInstance().getHtm("data/scripts/quests/Q255_Tutorial/" + html);
  993.         if (text == null)
  994.         {
  995.             _log.warn("missing html page data/scripts/quests/Q255_Tutorial/" + html);
  996.             text = "<html><body>File data/scripts/quests/Q255_Tutorial/" + html + " not found or file is empty.</body></html>";
  997.         }
  998.         getPlayer().sendPacket(new TutorialShowHtml(text));
  999.     }
  1000.    
  1001.     public void closeTutorialHtml()
  1002.     {
  1003.         _player.sendPacket(new TutorialCloseHtml());
  1004.     }
  1005.    
  1006.     public void onTutorialClientEvent(int number)
  1007.     {
  1008.         _player.sendPacket(new TutorialEnableClientEvent(number));
  1009.     }
  1010. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement