All pastes #33992 Raw Edit

Unnamed

public text v1 · immutable
#33992 ·published 2005-12-17 19:51 UTC
rendered paste body

    /**
    * Calculates quantity of items for specific drop acording to current situation <br>
    * 
    * @param drop The L2DropData count is being calculated for
    * @param lastAttacker The L2PcInstance that has killed the L2Attackable
    * @param deepBlueDrop Factor to divide the drop chance
    * @param levelModifier level modifier in %'s (will be subtracted from drop chance)
    */
    private int calculateDropCount(L2DropData drop, L2PcInstance lastAttacker, int levelModifier)
    {
        // Roll the dice.. between 0 and MAX_CHANCE (=1000000)
        int roll = Rnd.get(1, L2DropData.MAX_CHANCE);

        float rate = (drop.isSweep()? Config.RATE_DROP_SPOIL:Config.RATE_DROP_ITEMS);
        
        // Get default drop chance
        float dropChance = drop.getChance() * rate;

        int deepBlueDrop = 1;
        if (Config.DEEPBLUE_DROP_RULES)
        {
            if (levelModifier > 0)
            {
                // We should multiply by the server's drop rate, so we always get a low chance of drop for deep blue mobs.
                // NOTE: This is valid only for adena drops! Others drops will still obey server's rate
                deepBlueDrop = 3;
                if (drop.getItemId() == 57) deepBlueDrop *= (int)Config.RATE_DROP_ITEMS;
            }
        }

        // Check if we should apply our maths so deep blue mobs will not drop that easy
        if (Config.DEEPBLUE_DROP_RULES) dropChance = ((drop.getChance() - ((drop.getChance() * levelModifier)/100)) * rate / deepBlueDrop);

        // Round drop chance
        dropChance = Math.round(dropChance);

        // Set our limits for chance of drop
        if (dropChance < 1) dropChance = 1;
        if (drop.getItemId() == 57 && dropChance > L2DropData.MAX_CHANCE) dropChance = L2DropData.MAX_CHANCE; // If item is adena, dont drop multiple time

        int itemCount = 0;

        // Check if the Item must be dropped
        while (roll < dropChance)
        {
            // Get min and max Item quantity that can be dropped in one time
            int min = drop.getMinDrop();
            int max = drop.getMaxDrop();

            // Get the item quantity dropped
            if (min < max)
                itemCount += Rnd.get(min, max);
            else if (min == max)
                itemCount += min;
            else
                itemCount++;

            // Calculate the Adena reward with the RATE_DROP_ADENA
            if (drop.getItemId() == 57) itemCount *= Config.RATE_DROP_ADENA;
            
            // Prepare for next iteration if dropChance > L2DropData.MAX_CHANCE
            dropChance -= L2DropData.MAX_CHANCE;
        }

        if (itemCount == 0 && Config.DEBUG) _log.fine("Roll produced 0 items to drop...");

        return itemCount;
    }

    /**
     * Calculates the level modifier for drop<br>
     * 
     * @param lastAttacker The L2PcInstance that has killed the L2Attackable
     */
    private int calculateLevelModifierForDrop(L2PcInstance lastAttacker)
    {
        if (Config.DEEPBLUE_DROP_RULES)
        {
            int highestLevel = lastAttacker.getLevel();

            // Check to prevent very high level player to nearly kill mob and let low level player do the last hit.
            if (getAttackByList() != null && getAttackByList().size() > 0)
            {
                for (L2Character atkChar: getAttackByList())
                    if (atkChar != null && atkChar.getLevel() > highestLevel) highestLevel = atkChar.getLevel();
            }

            // According to official data (Prima), deep blue mobs are 9 or more levels below players
            if (highestLevel - 9 >= getLevel()) return ((highestLevel - (getLevel() + 8)) * 9);
        }

        return 0;
    }

    private void dropItem(L2PcInstance player, int itemId, int itemCount)
    {
        L2ItemInstance dropit;
        int z;
        
        for (int i = 1; i <= itemCount; i++)
        {
            dropit = ItemTable.getInstance().createItem(itemId);

            // Set the Item quantity dropped if L2ItemInstance is stackable
            if (dropit.isStackable())
            {
                i = itemCount;                  // Set so loop won't happent again
                dropit.setCount(itemCount);     // Set item count
            }

            if (Config.DEBUG) _log.fine("Item id to drop: " + itemId + " amount: " + dropit.getCount());
            
            if(this instanceof L2RaidBossInstance)
            {
                SystemMessage sm = new SystemMessage(SystemMessage.S1_DIED_DROPPED_S3_S2);
                sm.addString(getName());
                sm.addNumber(dropit.getCount());
                sm.addItemName(itemId);
                broadcastPacket(sm);
            }
            
            // Check if the autoLoot mode is active
            if (Config.AUTO_LOOT)
                player.doAutoLoot(dropit); // Give this or these Item(s) to the L2PcInstance that has killed the L2Attackable
            else 
            {
                // Get the current Z position of the L2Character that has killed the L2Attackable
                z = getZ();
                if (player.getZ() > z) z = player.getZ();
                
                // Init the dropped L2ItemInstance and add it in the world as a visible object at the position where mob was last
                dropit.dropMe(this, getX(), getY(), z + 200);

                // Add drop to auto destroy item task
                if (Config.AUTODESTROY_ITEM_AFTER > 0) ItemsAutoDestroy.getInstance().addItem(dropit);
            }
        }
    }
    
    /**
     * Manage Sweep drops of L2Attackable.<BR><BR>
     * 
     * <B><U> Actions</U> : </B><BR><BR>
     * <li>Get all possible drops of this L2Attackable from L2NpcTemplate</li>
     * <li>For each possible drops (base including sweep), calculate which one can is spoiled (random) </li>
     * <li>Get each Item spoiled quantity (random) </li>
     * <li>Create this or these L2ItemInstance corresponding to each Item Identifier spoiled</li>
     * <li>Add each of those L2ItemInstance to the table _sweepItems of this L2Attackable containing all Items that can be spoiled </li><BR><BR>
     * 
     * @param lastAttacker The L2Character that has killed the L2Attackable
     */
    public void doSweepDrop(L2Character lastAttacker)
    {
        L2PcInstance player = null;
        if (lastAttacker instanceof L2PcInstance)
            player = (L2PcInstance)lastAttacker;
        else if (lastAttacker instanceof L2Summon)
            player = ((L2Summon)lastAttacker).getOwner();

        if (player == null) return; // Don't drop anything if the last attacker or ownere isn't L2PcInstance

        int levelModifier = calculateLevelModifierForDrop(player);;          // level modifier in %'s (will be subtracted from drop chance)
        
        // Create a table containing all possible drops of this L2Attackable from L2NpcTemplate
        List<L2DropData> drops = getTemplate().getDropData();
        if (Config.DEBUG) _log.finer("this npc has "+drops.size()+" drops defined");
        
        // Create a table that will contain all Items that can be spoiled
        List<L2ItemInstance> spoiled = new FastList<L2ItemInstance>();

        // Go Throw all possible drops (base including sweep) of this L2Attackable
        L2ItemInstance dropit;
        int itemCount;
        for (L2DropData drop: drops)
        {
            if (drop == null) continue;
			
			// If it's not a sweep drop, it will not appear on the ground only drop adena if seeded with low-grade seed
            if (!drop.isSweep() || (isSeeded() && !isSeededHigh() && drop.getItemId() != 57))
                continue;
            
            // Calculates Item drop count with current rates...
            itemCount = calculateDropCount(drop, player, levelModifier);

            for (int i = 1; i <= itemCount; i++)
            {
                dropit = ItemTable.getInstance().createItem(drop.getItemId());

                // Set the Item quantity dropped if L2ItemInstance is stackable
                if (dropit.isStackable())
                {
                    i = itemCount;                  // Set so loop won't happent again
                    dropit.setCount(itemCount);     // Set item count
                }

                spoiled.add(dropit);
                
                if (Config.DEBUG) _log.fine("Item id to spoil: " + drop.getItemId() + " amount: " + dropit.getCount());
            }
        }
        
        // Set the table _sweepItems of this L2Attackable
        if (spoiled.size() > 0) _sweepItems = spoiled.toArray(new L2ItemInstance[spoiled.size()]);
    }
    
	
    /**
     * Manage Special Events drops created by GM for a defined period.<BR><BR>
     *  
     * <B><U> Concept</U> :</B><BR><BR>
     * During a Special Event all L2Attackable can drop extra Items.
     * Those extra Items are defined in the table <B>allNpcDateDrops</B> of the EventDroplist. 
     * Each Special Event has a start and end date to stop to drop extra Items automaticaly. <BR><BR>
     * 
     * <B><U> Actions</U> : <I>If an extra drop must be generated</I></B><BR><BR>
     * <li>Get an Item Identifier (random) from the DateDrop Item table of this Event </li>
     * <li>Get the Item quantity dropped (random) </li>
     * <li>Create this or these L2ItemInstance corresponding to this Item Identifier</li>
     * <li>If the autoLoot mode is actif and if the L2Character that has killed the L2Attackable is a L2PcInstance, give this or these Item(s) to the L2PcInstance that has killed the L2Attackable</li>
     * <li>If the autoLoot mode isn't actif or if the L2Character that has killed the L2Attackable is not a L2PcInstance, add this or these Item(s) in the world as a visible object at the position where mob was last</li><BR><BR>
     * 
     * @param lastAttacker The L2Character that has killed the L2Attackable
     */
    public void doEventDrop(L2Character lastAttacker)
    {
        L2PcInstance player = null;
        if (lastAttacker instanceof L2PcInstance)
            player = (L2PcInstance)lastAttacker;
        else if (lastAttacker instanceof L2Summon)
            player = ((L2Summon)lastAttacker).getOwner();

        if (player == null) return; // Don't drop anything if the last attacker or ownere isn't L2PcInstance
        
        if (player.getLevel() - getLevel() > 9)
            return;
		
        // Go through DateDrop of EventDroplist allNpcDateDrops within the date range
        int itemCount;
        int max;
        int min;
        for (DateDrop drop : EventDroplist.getInstance().getAllDrops())
        {
            if (Rnd.get(1, L2DropData.MAX_CHANCE) < drop.chance)
            {
				// Get min and max Item quantity that can be dropped in one time
                max = drop.max;
			    min = drop.min;
				
				// Get the item quantity dropped
                itemCount = 0;
                if (min < max)
                    itemCount += Rnd.get(min, max);
                else if (min == max)
                    itemCount += min;
                else
                    itemCount++;
			    
                dropItem(player, drop.items[Rnd.get(0, drop.items.length - 1)], itemCount);
            }
        }
    }
	
	
    /**
     * Manage Base, Quests and Special Events drops of L2Attackable (called by calculateRewards).<BR><BR>
     *  
     * <B><U> Concept</U> :</B><BR><BR>
     * During a Special Event all L2Attackable can drop extra Items.
     * Those extra Items are defined in the table <B>allNpcDateDrops</B> of the EventDroplist. 
     * Each Special Event has a start and end date to stop to drop extra Items automaticaly. <BR><BR>
     * 
     * <B><U> Actions</U> : </B><BR><BR>
     * <li>Manage drop of Special Events created by GM for a defined period </li>
     * <li>Get all possible drops of this L2Attackable from L2NpcTemplate and add it Quest drops</li>
     * <li>For each possible drops (base + quests), calculate which one must be dropped (random) </li>
     * <li>Get each Item quantity dropped (random) </li>
     * <li>Create this or these L2ItemInstance corresponding to each Item Identifier dropped</li>
     * <li>If the autoLoot mode is actif and if the L2Character that has killed the L2Attackable is a L2PcInstance, give this or these Item(s) to the L2PcInstance that has killed the L2Attackable</li>
     * <li>If the autoLoot mode isn't actif or if the L2Character that has killed the L2Attackable is not a L2PcInstance, add this or these Item(s) in the world as a visible object at the position where mob was last</li><BR><BR>
     * 
     * @param lastAttacker The L2Character that has killed the L2Attackable
     */
    public void doItemDrop(L2Character lastAttacker)
    {
        L2PcInstance player = null;
        if (lastAttacker instanceof L2PcInstance)
            player = (L2PcInstance)lastAttacker;
        else if (lastAttacker instanceof L2Summon)
            player = ((L2Summon)lastAttacker).getOwner();

        if (player == null) return; // Don't drop anything if the last attacker or ownere isn't L2PcInstance

        int levelModifier = calculateLevelModifierForDrop(player);;          // level modifier in %'s (will be subtracted from drop chance)
        
		// Manage drop of Special Events created by GM for a defined period
        doEventDrop(lastAttacker);
		
        // Create a table containing all possible drops of this L2Attackable from L2NpcTemplate
        List<L2DropData> drops = new FastList<L2DropData>();
        drops.addAll(getTemplate().getDropData());
        if (Config.DEBUG) _log.finer("this npc has "+drops.size()+" drops defined");

        // Add Quest drops to the table containing all possible drops of this L2Attackable
        player.fillQuestDrops(this, drops);
        
        // Go Throw all possible drops (base + quests) of this L2Attackable
        for (L2DropData drop : drops)
        {
            if (drop == null) continue;
            
            // If it's a sweep drop, it will not appear on the ground
            if (drop.isSweep()) continue;
            
            dropItem(player, drop.getItemId(), calculateDropCount(drop, player, calculateDropCount(drop, player, levelModifier)));
        }
    }