Addition of rewards on enchant failure.
Contributed by Index.
This commit is contained in:
@@ -31,16 +31,19 @@ import org.w3c.dom.Node;
|
||||
import org.l2jmobius.commons.util.IXmlReader;
|
||||
import org.l2jmobius.gameserver.data.ItemTable;
|
||||
import org.l2jmobius.gameserver.enums.CrystallizationType;
|
||||
import org.l2jmobius.gameserver.model.StatSet;
|
||||
import org.l2jmobius.gameserver.model.actor.Player;
|
||||
import org.l2jmobius.gameserver.model.holders.CrystallizationDataHolder;
|
||||
import org.l2jmobius.gameserver.model.holders.ItemChanceHolder;
|
||||
import org.l2jmobius.gameserver.model.item.Armor;
|
||||
import org.l2jmobius.gameserver.model.item.ItemTemplate;
|
||||
import org.l2jmobius.gameserver.model.item.Weapon;
|
||||
import org.l2jmobius.gameserver.model.item.enchant.RewardItemsOnFailure;
|
||||
import org.l2jmobius.gameserver.model.item.instance.Item;
|
||||
import org.l2jmobius.gameserver.model.item.type.CrystalType;
|
||||
|
||||
/**
|
||||
* @author UnAfraid
|
||||
* @author UnAfraid, Index
|
||||
*/
|
||||
public class ItemCrystallizationData implements IXmlReader
|
||||
{
|
||||
@@ -49,6 +52,9 @@ public class ItemCrystallizationData implements IXmlReader
|
||||
private final Map<CrystalType, Map<CrystallizationType, List<ItemChanceHolder>>> _crystallizationTemplates = new EnumMap<>(CrystalType.class);
|
||||
private final Map<Integer, CrystallizationDataHolder> _items = new HashMap<>();
|
||||
|
||||
private RewardItemsOnFailure _weaponDestroyGroup = new RewardItemsOnFailure();
|
||||
private RewardItemsOnFailure _armorDestroyGroup = new RewardItemsOnFailure();
|
||||
|
||||
protected ItemCrystallizationData()
|
||||
{
|
||||
load();
|
||||
@@ -63,12 +69,32 @@ public class ItemCrystallizationData implements IXmlReader
|
||||
_crystallizationTemplates.put(crystalType, new EnumMap<>(CrystallizationType.class));
|
||||
}
|
||||
_items.clear();
|
||||
|
||||
_weaponDestroyGroup = new RewardItemsOnFailure();
|
||||
_armorDestroyGroup = new RewardItemsOnFailure();
|
||||
|
||||
parseDatapackFile("data/CrystallizableItems.xml");
|
||||
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _crystallizationTemplates.size() + " crystallization templates.");
|
||||
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _items.size() + " pre-defined crystallizable items.");
|
||||
|
||||
if (_crystallizationTemplates.size() > 0)
|
||||
{
|
||||
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _crystallizationTemplates.size() + " crystallization templates.");
|
||||
}
|
||||
if (_items.size() > 0)
|
||||
{
|
||||
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _items.size() + " pre-defined crystallizable items.");
|
||||
}
|
||||
|
||||
// Generate remaining data.
|
||||
generateCrystallizationData();
|
||||
|
||||
if (_weaponDestroyGroup.size() > 0)
|
||||
{
|
||||
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _weaponDestroyGroup.size() + " weapon enchant failure rewards.");
|
||||
}
|
||||
if (_armorDestroyGroup.size() > 0)
|
||||
{
|
||||
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _armorDestroyGroup.size() + " armor enchant failure rewards.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,6 +154,20 @@ public class ItemCrystallizationData implements IXmlReader
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ("itemsOnEnchantFailure".equals(o.getNodeName()))
|
||||
{
|
||||
for (Node d = o.getFirstChild(); d != null; d = d.getNextSibling())
|
||||
{
|
||||
if ("armor".equalsIgnoreCase(d.getNodeName()))
|
||||
{
|
||||
_armorDestroyGroup = getFormedHolder(d);
|
||||
}
|
||||
else if ("weapon".equalsIgnoreCase(d.getNodeName()))
|
||||
{
|
||||
_weaponDestroyGroup = getFormedHolder(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,7 +219,11 @@ public class ItemCrystallizationData implements IXmlReader
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info(getClass().getSimpleName() + ": Generated " + (_items.size() - previousCount) + " crystallizable items from templates.");
|
||||
final int generated = _items.size() - previousCount;
|
||||
if (generated > 0)
|
||||
{
|
||||
LOGGER.info(getClass().getSimpleName() + ": Generated " + generated + " crystallizable items from templates.");
|
||||
}
|
||||
}
|
||||
|
||||
public List<ItemChanceHolder> getCrystallizationTemplate(CrystalType crystalType, CrystallizationType crystallizationType)
|
||||
@@ -235,6 +279,49 @@ public class ItemCrystallizationData implements IXmlReader
|
||||
return result;
|
||||
}
|
||||
|
||||
private RewardItemsOnFailure getFormedHolder(Node node)
|
||||
{
|
||||
final RewardItemsOnFailure holder = new RewardItemsOnFailure();
|
||||
for (Node z = node.getFirstChild(); z != null; z = z.getNextSibling())
|
||||
{
|
||||
if ("item".equals(z.getNodeName()))
|
||||
{
|
||||
final StatSet failItems = new StatSet(parseAttributes(z));
|
||||
final int itemId = failItems.getInt("id");
|
||||
final int enchantLevel = failItems.getInt("enchant");
|
||||
final double chance = failItems.getDouble("chance");
|
||||
for (CrystalType grade : CrystalType.values())
|
||||
{
|
||||
final long count = failItems.getLong("amount" + grade.name(), Integer.MIN_VALUE);
|
||||
if (count == Integer.MIN_VALUE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
holder.addItemToHolder(itemId, grade, enchantLevel, count, chance);
|
||||
}
|
||||
}
|
||||
}
|
||||
return holder;
|
||||
}
|
||||
|
||||
public ItemChanceHolder getItemOnDestroy(Player player, Item item)
|
||||
{
|
||||
if ((player == null) || (item == null))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final RewardItemsOnFailure holder = item.isWeapon() ? _weaponDestroyGroup : _armorDestroyGroup;
|
||||
final CrystalType grade = item.getTemplate().getCrystalTypePlus();
|
||||
if (holder.checkIfRewardUnavailable(grade, item.getEnchantLevel()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return holder.getRewardItem(grade, item.getEnchantLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the single instance of ItemCrystalizationData.
|
||||
* @return single instance of ItemCrystalizationData
|
||||
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.gameserver.model.item.enchant;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.l2jmobius.gameserver.model.holders.ItemChanceHolder;
|
||||
import org.l2jmobius.gameserver.model.item.type.CrystalType;
|
||||
|
||||
/**
|
||||
* @author Index
|
||||
*/
|
||||
public class RewardItemsOnFailure
|
||||
{
|
||||
private final Map<CrystalType, Map<Integer, ItemChanceHolder>> _rewards = new EnumMap<>(CrystalType.class);
|
||||
private int _minEnchantLevel = Integer.MAX_VALUE;
|
||||
private int _maxEnchantLevel = Integer.MIN_VALUE;
|
||||
|
||||
public RewardItemsOnFailure()
|
||||
{
|
||||
}
|
||||
|
||||
public void addItemToHolder(int itemId, CrystalType grade, int enchantLevel, long count, double chance)
|
||||
{
|
||||
final ItemChanceHolder item = new ItemChanceHolder(itemId, chance, count);
|
||||
_rewards.computeIfAbsent(grade, v -> new HashMap<>()).put(enchantLevel, item);
|
||||
_minEnchantLevel = Math.min(_minEnchantLevel, enchantLevel);
|
||||
_maxEnchantLevel = Math.max(_maxEnchantLevel, enchantLevel);
|
||||
}
|
||||
|
||||
public ItemChanceHolder getRewardItem(CrystalType grade, int enchantLevel)
|
||||
{
|
||||
return _rewards.getOrDefault(grade, new HashMap<>()).getOrDefault(enchantLevel, null);
|
||||
}
|
||||
|
||||
public boolean checkIfRewardUnavailable(CrystalType grade, int enchantLevel)
|
||||
{
|
||||
// reversed available
|
||||
if (_minEnchantLevel > enchantLevel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_maxEnchantLevel < enchantLevel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_rewards.containsKey(grade))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return !_rewards.get(grade).containsKey(enchantLevel);
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
int count = 0;
|
||||
for (Map<Integer, ItemChanceHolder> rewards : _rewards.values())
|
||||
{
|
||||
count += rewards.size();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
@@ -22,11 +22,13 @@ import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.network.ReadablePacket;
|
||||
import org.l2jmobius.commons.util.Rnd;
|
||||
import org.l2jmobius.gameserver.data.xml.EnchantItemData;
|
||||
import org.l2jmobius.gameserver.data.xml.ItemCrystallizationData;
|
||||
import org.l2jmobius.gameserver.enums.ItemSkillType;
|
||||
import org.l2jmobius.gameserver.enums.UserInfoType;
|
||||
import org.l2jmobius.gameserver.model.World;
|
||||
import org.l2jmobius.gameserver.model.actor.Player;
|
||||
import org.l2jmobius.gameserver.model.actor.request.EnchantItemRequest;
|
||||
import org.l2jmobius.gameserver.model.holders.ItemChanceHolder;
|
||||
import org.l2jmobius.gameserver.model.item.ItemTemplate;
|
||||
import org.l2jmobius.gameserver.model.item.enchant.EnchantResultType;
|
||||
import org.l2jmobius.gameserver.model.item.enchant.EnchantScroll;
|
||||
@@ -353,6 +355,8 @@ public class RequestEnchantItem implements ClientPacket
|
||||
}
|
||||
else
|
||||
{
|
||||
final ItemChanceHolder destroyReward = ItemCrystallizationData.getInstance().getItemOnDestroy(player, item);
|
||||
|
||||
// enchant failed, destroy item
|
||||
if (player.getInventory().destroyItem("Enchant", item, player, null) == null)
|
||||
{
|
||||
@@ -420,6 +424,12 @@ public class RequestEnchantItem implements ClientPacket
|
||||
player.sendPacket(new EnchantResult(EnchantResult.FAIL, crystalId, count));
|
||||
}
|
||||
|
||||
if ((destroyReward != null) && (Rnd.get(100) < destroyReward.getChance()))
|
||||
{
|
||||
player.addItem("Enchant", destroyReward.getId(), destroyReward.getCount(), null, true);
|
||||
player.sendPacket(new EnchantResult(EnchantResult.FAIL, destroyReward.getId(), (int) destroyReward.getCount()));
|
||||
}
|
||||
|
||||
if (Config.LOG_ITEM_ENCHANTS)
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
Reference in New Issue
Block a user