Multisell, augment and tax zone rework.

Adapted from: L2jUnity free files.
This commit is contained in:
MobiusDev
2017-11-28 18:21:28 +00:00
parent 4f4dd3a736
commit 0c828bea2f
2474 changed files with 19097 additions and 27190 deletions

View File

@@ -28,15 +28,14 @@ import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.file.filter.NumericNameFilter;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.buylist.L2BuyList;
import com.l2jmobius.gameserver.model.buylist.Product;
import com.l2jmobius.gameserver.model.buylist.ProductList;
import com.l2jmobius.gameserver.model.items.L2Item;
/**
@@ -47,7 +46,7 @@ public final class BuyListData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(BuyListData.class.getName());
private final Map<Integer, L2BuyList> _buyLists = new HashMap<>();
private final Map<Integer, ProductList> _buyLists = new HashMap<>();
private static final FileFilter NUMERIC_FILTER = new NumericNameFilter();
protected BuyListData()
@@ -77,7 +76,7 @@ public final class BuyListData implements IGameXmlReader
final int itemId = rs.getInt("item_id");
final long count = rs.getLong("count");
final long nextRestockTime = rs.getLong("next_restock_time");
final L2BuyList buyList = getBuyList(buyListId);
final ProductList buyList = getBuyList(buyListId);
if (buyList == null)
{
LOGGER.warning("BuyList found in database but not loaded from xml! BuyListId: " + buyListId);
@@ -108,71 +107,44 @@ public final class BuyListData implements IGameXmlReader
try
{
final int buyListId = Integer.parseInt(f.getName().replaceAll(".xml", ""));
for (Node node = doc.getFirstChild(); node != null; node = node.getNextSibling())
forEach(doc, "list", (list) ->
{
if ("list".equalsIgnoreCase(node.getNodeName()))
final int defaultBaseTax = parseInteger(list.getAttributes(), "baseTax", 0);
final ProductList buyList = new ProductList(buyListId);
forEach(list, (node) ->
{
final L2BuyList buyList = new L2BuyList(buyListId);
for (Node list_node = node.getFirstChild(); list_node != null; list_node = list_node.getNextSibling())
switch (node.getNodeName())
{
if ("item".equalsIgnoreCase(list_node.getNodeName()))
case "item":
{
int itemId = -1;
long price = -1;
long restockDelay = -1;
long count = -1;
final NamedNodeMap attrs = list_node.getAttributes();
Node attr = attrs.getNamedItem("id");
itemId = Integer.parseInt(attr.getNodeValue());
attr = attrs.getNamedItem("price");
if (attr != null)
{
price = Long.parseLong(attr.getNodeValue());
}
attr = attrs.getNamedItem("restock_delay");
if (attr != null)
{
restockDelay = Long.parseLong(attr.getNodeValue());
}
attr = attrs.getNamedItem("count");
if (attr != null)
{
count = Long.parseLong(attr.getNodeValue());
}
final NamedNodeMap attrs = node.getAttributes();
final int itemId = parseInteger(attrs, "id");
final L2Item item = ItemTable.getInstance().getTemplate(itemId);
if (item != null)
{
if ((price > -1) && (item.getReferencePrice() > price) && (buyList.getNpcsAllowed() != null))
{
LOGGER.warning("Item price is too low. BuyList:" + buyList.getListId() + " ItemID:" + itemId + " File:" + f.getName());
LOGGER.warning("Setting price to reference price " + item.getReferencePrice() + " instead of " + price + ".");
buyList.addProduct(new Product(buyList.getListId(), item, item.getReferencePrice(), restockDelay, count));
}
else
{
buyList.addProduct(new Product(buyList.getListId(), item, price, restockDelay, count));
}
final long price = parseLong(attrs, "price", -1L);
final long restockDelay = parseLong(attrs, "restock_delay", -1L);
final long count = parseLong(attrs, "count", -1L);
final int baseTax = parseInteger(attrs, "baseTax", defaultBaseTax);
buyList.addProduct(new Product(buyListId, item, price, restockDelay, count, baseTax));
}
else
{
LOGGER.warning("Item not found. BuyList:" + buyList.getListId() + " ItemID:" + itemId + " File:" + f.getName());
LOGGER.warning("Item not found. BuyList:" + buyListId + " ItemID:" + itemId + " File:" + f);
}
break;
}
else if ("npcs".equalsIgnoreCase(list_node.getNodeName()))
case "npcs":
{
for (Node npcs_node = list_node.getFirstChild(); npcs_node != null; npcs_node = npcs_node.getNextSibling())
{
if ("npc".equalsIgnoreCase(npcs_node.getNodeName()))
{
buyList.addAllowedNpc(Integer.parseInt(npcs_node.getTextContent()));
}
}
forEach(node, "npc", (npcNode) -> buyList.addAllowedNpc(Integer.parseInt(npcNode.getTextContent())));
break;
}
}
_buyLists.put(buyList.getListId(), buyList);
}
}
});
_buyLists.put(buyListId, buyList);
});
}
catch (Exception e)
{
@@ -186,7 +158,7 @@ public final class BuyListData implements IGameXmlReader
return NUMERIC_FILTER;
}
public L2BuyList getBuyList(int listId)
public ProductList getBuyList(int listId)
{
return _buyLists.get(listId);
}

View File

@@ -18,50 +18,44 @@ package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.file.filter.NumericNameFilter;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.enums.SpecialItemType;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.multisell.Entry;
import com.l2jmobius.gameserver.model.multisell.Ingredient;
import com.l2jmobius.gameserver.model.multisell.ListContainer;
import com.l2jmobius.gameserver.model.multisell.PreparedListContainer;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExPCCafePointInfo;
import com.l2jmobius.gameserver.model.holders.ItemChanceHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MultisellEntryHolder;
import com.l2jmobius.gameserver.model.holders.MultisellListHolder;
import com.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.network.serverpackets.MultiSellList;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.network.serverpackets.UserInfo;
import com.l2jmobius.gameserver.util.Util;
public final class MultisellData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(MultisellData.class.getName());
private final Map<Integer, ListContainer> _entries = new HashMap<>();
public static final int PAGE_SIZE = 40;
// Special IDs.
public static final int PC_CAFE_POINTS = -100;
public static final int CLAN_REPUTATION = -200;
public static final int FAME = -300;
public static final int FIELD_CYCLE_POINTS = -400;
public static final int RAIDBOSS_POINTS = -500;
// Misc
private static final FileFilter NUMERIC_FILTER = new NumericNameFilter();
private final Map<Integer, MultisellListHolder> _multisells = new HashMap<>();
protected MultisellData()
{
load();
@@ -70,15 +64,14 @@ public final class MultisellData implements IGameXmlReader
@Override
public void load()
{
_entries.clear();
_multisells.clear();
parseDatapackDirectory("data/multisell", false);
if (Config.CUSTOM_MULTISELL_LOAD)
{
parseDatapackDirectory("data/multisell/custom", false);
}
verify();
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _entries.size() + " multisell lists.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _multisells.size() + " multisell lists.");
}
@Override
@@ -86,73 +79,88 @@ public final class MultisellData implements IGameXmlReader
{
try
{
final int id = Integer.parseInt(f.getName().replaceAll(".xml", ""));
int entryId = 1;
Node att;
final ListContainer list = new ListContainer(id);
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
forEach(doc, "list", listNode ->
{
if ("list".equalsIgnoreCase(n.getNodeName()))
final StatsSet set = new StatsSet(parseAttributes(listNode));
final int listId = Integer.parseInt(f.getName().substring(0, f.getName().length() - 4));
final List<MultisellEntryHolder> entries = new ArrayList<>(listNode.getChildNodes().getLength());
forEach(listNode, itemNode ->
{
list.setApplyTaxes(parseBoolean(n.getAttributes(), "applyTaxes", false));
list.setIsChanceMultisell(parseBoolean(n.getAttributes(), "isChanceMultisell", false));
list.setMaintainEnchantment(parseBoolean(n.getAttributes(), "maintainEnchantment", false));
att = n.getAttributes().getNamedItem("useRate");
if (att != null)
if ("item".equalsIgnoreCase(itemNode.getNodeName()))
{
try
final List<ItemHolder> ingredients = new ArrayList<>(1);
final List<ItemChanceHolder> products = new ArrayList<>(1);
final MultisellEntryHolder entry = new MultisellEntryHolder(ingredients, products);
for (Node d = itemNode.getFirstChild(); d != null; d = d.getNextSibling())
{
list.setUseRate(Double.valueOf(att.getNodeValue()));
if (list.getUseRate() <= 1e-6)
if ("ingredient".equalsIgnoreCase(d.getNodeName()))
{
throw new NumberFormatException("The value cannot be 0"); // threat 0 as invalid value
}
}
catch (NumberFormatException e)
{
try
{
list.setUseRate(Config.class.getField(att.getNodeValue()).getDouble(Config.class));
}
catch (Exception e1)
{
LOGGER.warning(e1.getMessage() + doc.getLocalName());
list.setUseRate(1.0);
}
}
catch (DOMException e)
{
LOGGER.warning(e.getMessage() + doc.getLocalName());
}
}
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("item".equalsIgnoreCase(d.getNodeName()))
{
final Entry e = parseEntry(d, entryId++, list);
list.getEntries().add(e);
}
else if ("npcs".equalsIgnoreCase(d.getNodeName()))
{
for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("npc".equalsIgnoreCase(b.getNodeName()))
final int id = parseInteger(d.getAttributes(), "id");
final long count = parseLong(d.getAttributes(), "count");
final ItemHolder ingredient = new ItemHolder(id, count);
if (itemExists(ingredient))
{
if (Util.isDigit(b.getTextContent()))
ingredients.add(ingredient);
}
else
{
LOGGER.warning("Invalid ingredient id or count for itemId: " + ingredient.getId() + ", count: " + ingredient.getCount() + " in list: " + listId);
continue;
}
}
else if ("production".equalsIgnoreCase(d.getNodeName()))
{
final int id = parseInteger(d.getAttributes(), "id");
final long count = parseLong(d.getAttributes(), "count");
final double chance = parseDouble(d.getAttributes(), "chance", Double.NaN);
final ItemChanceHolder product = new ItemChanceHolder(id, chance, count);
if (itemExists(product))
{
// Check chance only of items that have set chance. Items without chance (NaN) are used for displaying purposes.
if ((!Double.isNaN(chance) && (chance < 0)) || (chance > 100))
{
list.allowNpc(Integer.parseInt(b.getTextContent()));
LOGGER.warning("Invalid chance for itemId: " + product.getId() + ", count: " + product.getCount() + ", chance: " + chance + " in list: " + listId);
continue;
}
products.add(product);
}
else
{
LOGGER.warning("Invalid product id or count for itemId: " + product.getId() + ", count: " + product.getCount() + " in list: " + listId);
continue;
}
}
}
final double totalChance = products.stream().filter(i -> !Double.isNaN(i.getChance())).mapToDouble(ItemChanceHolder::getChance).sum();
if (totalChance > 100)
{
LOGGER.warning("Products' total chance of " + totalChance + "% exceeds 100% for list: " + listId + " at entry " + entries.size() + 1 + ".");
}
entries.add(entry);
}
}
}
_entries.put(id, list);
else if ("npcs".equalsIgnoreCase(itemNode.getNodeName()))
{
// Initialize NPCs with the size of child nodes.
final Set<Integer> allowNpc = new HashSet<>(itemNode.getChildNodes().getLength());
forEach(itemNode, n -> "npc".equalsIgnoreCase(n.getNodeName()) && Util.isDigit(n.getTextContent()), n -> allowNpc.add(Integer.parseInt(n.getTextContent())));
// Add npcs to stats set.
set.set("allowNpc", allowNpc);
}
});
set.set("listId", listId);
set.set("entries", entries);
_multisells.put(listId, new MultisellListHolder(set));
});
}
catch (Exception e)
{
@@ -166,44 +174,6 @@ public final class MultisellData implements IGameXmlReader
return NUMERIC_FILTER;
}
private final Entry parseEntry(Node n, int entryId, ListContainer list)
{
final Node first = n.getFirstChild();
final Entry entry = new Entry(entryId);
NamedNodeMap attrs;
Node att;
StatsSet set;
for (n = first; n != null; n = n.getNextSibling())
{
if ("ingredient".equalsIgnoreCase(n.getNodeName()))
{
attrs = n.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
entry.addIngredient(new Ingredient(set));
}
else if ("production".equalsIgnoreCase(n.getNodeName()))
{
attrs = n.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
entry.addProduct(new Ingredient(set));
}
}
return entry;
}
/**
* This will generate the multisell list for the items.<br>
* There exist various parameters in multisells that affect the way they will appear:
@@ -230,38 +200,36 @@ public final class MultisellData implements IGameXmlReader
* @param player
* @param npc
* @param inventoryOnly
* @param productMultiplier
* @param ingredientMultiplier
* @param productMultiplier
*/
public final void separateAndSend(int listId, L2PcInstance player, L2Npc npc, boolean inventoryOnly, double productMultiplier, double ingredientMultiplier)
public final void separateAndSend(int listId, L2PcInstance player, L2Npc npc, boolean inventoryOnly, double ingredientMultiplier, double productMultiplier)
{
final ListContainer template = _entries.get(listId);
final MultisellListHolder template = _multisells.get(listId);
if (template == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Cannot find list ID: " + listId + " requested by player: " + player.getName() + ", NPC ID:" + (npc != null ? npc.getId() : 0));
LOGGER.warning("Can't find list id: " + listId + " requested by player: " + player.getName() + ", npcId: " + (npc != null ? npc.getId() : 0));
return;
}
if (!template.isNpcAllowed(-1) && (((npc != null) && !template.isNpcAllowed(npc.getId())) || ((npc == null) && template.isNpcOnly())))
if (((npc != null) && !template.isNpcAllowed(npc.getId())) || ((npc == null) && template.isNpcOnly()))
{
LOGGER.warning(getClass().getSimpleName() + ": Player " + player + " attempted to open multisell " + listId + " from npc " + npc + " which is not allowed!");
return;
}
final PreparedListContainer list = new PreparedListContainer(template, inventoryOnly, player, npc);
// Pass through this only when multipliers are different from 1
if ((productMultiplier != 1) || (ingredientMultiplier != 1))
{
list.getEntries().forEach(entry ->
if (player.isGM())
{
// Math.max used here to avoid dropping count to 0
entry.getProducts().forEach(product -> product.setItemCount((long) Math.max(product.getItemCount() * productMultiplier, 1)));
// Math.max used here to avoid dropping count to 0
entry.getIngredients().forEach(ingredient -> ingredient.setItemCount((long) Math.max(ingredient.getItemCount() * ingredientMultiplier, 1)));
});
player.sendMessage("Multisell " + listId + " is restricted. Under current conditions cannot be used. Only GMs are allowed to use it.");
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Player " + player + " attempted to open multisell " + listId + " from npc " + npc + " which is not allowed!");
return;
}
}
// Check if ingredient/product multipliers are set, if not, set them to the template value.
ingredientMultiplier = (Double.isNaN(ingredientMultiplier) ? template.getIngredientMultiplier() : ingredientMultiplier);
productMultiplier = (Double.isNaN(productMultiplier) ? template.getProductMultiplier() : productMultiplier);
final PreparedMultisellListHolder list = new PreparedMultisellListHolder(template, inventoryOnly, player.getInventory(), npc, ingredientMultiplier, productMultiplier);
int index = 0;
do
{
@@ -276,172 +244,19 @@ public final class MultisellData implements IGameXmlReader
public final void separateAndSend(int listId, L2PcInstance player, L2Npc npc, boolean inventoryOnly)
{
separateAndSend(listId, player, npc, inventoryOnly, 1, 1);
separateAndSend(listId, player, npc, inventoryOnly, Double.NaN, Double.NaN);
}
public static boolean hasSpecialIngredient(int id, long amount, L2PcInstance player)
private final boolean itemExists(ItemHolder holder)
{
switch (id)
final SpecialItemType specialItem = SpecialItemType.getByClientId(holder.getId());
if (specialItem != null)
{
case PC_CAFE_POINTS:
{
if (player.getPcCafePoints() >= amount)
{
return true;
}
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_SHORT_OF_PC_POINTS));
break;
}
case CLAN_REPUTATION:
{
if (player.getClan() == null)
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_A_CLAN_MEMBER_AND_CANNOT_PERFORM_THIS_ACTION);
return false;
}
if (!player.isClanLeader())
{
player.sendPacket(SystemMessageId.ONLY_THE_CLAN_LEADER_IS_ENABLED);
return false;
}
if (player.getClan().getReputationScore() < amount)
{
player.sendPacket(SystemMessageId.THE_CLAN_REPUTATION_IS_TOO_LOW);
return false;
}
return true;
}
case FAME:
{
if (player.getFame() < amount)
{
player.sendPacket(SystemMessageId.YOU_DON_T_HAVE_ENOUGH_FAME_TO_DO_THAT);
return false;
}
return true;
}
case RAIDBOSS_POINTS:
{
if (player.getRaidbossPoints() < amount)
{
player.sendPacket(SystemMessageId.NOT_ENOUGH_RAID_POINTS);
return false;
}
return true;
}
}
return false;
}
public static boolean takeSpecialIngredient(int id, long amount, L2PcInstance player)
{
switch (id)
{
case PC_CAFE_POINTS:
{
final int cost = player.getPcCafePoints() - (int) amount;
player.setPcCafePoints(cost);
final SystemMessage smsgpc = SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_USING_S1_POINT);
smsgpc.addLong((int) amount);
player.sendPacket(smsgpc);
player.sendPacket(new ExPCCafePointInfo(player.getPcCafePoints(), (int) amount, 1));
return true;
}
case CLAN_REPUTATION:
{
player.getClan().takeReputationScore((int) amount, true);
final SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.S1_POINT_S_HAVE_BEEN_DEDUCTED_FROM_THE_CLAN_S_REPUTATION);
smsg.addLong(amount);
player.sendPacket(smsg);
return true;
}
case FAME:
{
player.setFame(player.getFame() - (int) amount);
player.sendPacket(new UserInfo(player));
// player.sendPacket(new ExBrExtraUserInfo(player));
return true;
}
case RAIDBOSS_POINTS:
{
player.setRaidbossPoints(player.getRaidbossPoints() - (int) amount);
player.sendPacket(new UserInfo(player));
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_CONSUMED_S1_RAID_POINTS).addLong(amount));
return true;
}
}
return false;
}
public static void giveSpecialProduct(int id, long amount, L2PcInstance player)
{
switch (id)
{
case CLAN_REPUTATION:
{
player.getClan().addReputationScore((int) amount, true);
break;
}
case FAME:
{
player.setFame((int) (player.getFame() + amount));
player.sendPacket(new UserInfo(player));
// player.sendPacket(new ExBrExtraUserInfo(player));
break;
}
case RAIDBOSS_POINTS:
{
player.increaseRaidbossPoints((int) amount);
player.sendPacket(new UserInfo(player));
break;
}
}
}
private final void verify()
{
ListContainer list;
final Iterator<ListContainer> iter = _entries.values().iterator();
while (iter.hasNext())
{
list = iter.next();
for (Entry ent : list.getEntries())
{
for (Ingredient ing : ent.getIngredients())
{
if (!verifyIngredient(ing))
{
LOGGER.warning(getClass().getSimpleName() + ": Cannot find ingredient with item ID: " + ing.getItemId() + " in list: " + list.getListId());
}
}
for (Ingredient ing : ent.getProducts())
{
if (!verifyIngredient(ing))
{
LOGGER.warning(getClass().getSimpleName() + ": Cannot find product with item ID: " + ing.getItemId() + " in list: " + list.getListId());
}
}
}
}
}
private final boolean verifyIngredient(Ingredient ing)
{
switch (ing.getItemId())
{
case PC_CAFE_POINTS:
case CLAN_REPUTATION:
case FAME:
case RAIDBOSS_POINTS:
{
return true;
}
default:
{
return ing.getTemplate() != null;
}
return true;
}
final L2Item template = ItemTable.getInstance().getTemplate(holder.getId());
return (template != null) && (template.isStackable() ? (holder.getCount() >= 1) : (holder.getCount() == 1));
}
public static MultisellData getInstance()

View File

@@ -83,12 +83,12 @@ public class OptionData implements IGameXmlReader
}
case "active_skill":
{
option.setActiveSkill(new SkillHolder(parseInteger(innerNode.getAttributes(), "id"), parseInteger(innerNode.getAttributes(), "level")));
option.addActiveSkill(new SkillHolder(parseInteger(innerNode.getAttributes(), "id"), parseInteger(innerNode.getAttributes(), "level")));
break;
}
case "passive_skill":
{
option.setPassiveSkill(new SkillHolder(parseInteger(innerNode.getAttributes(), "id"), parseInteger(innerNode.getAttributes(), "level")));
option.addPassiveSkill(new SkillHolder(parseInteger(innerNode.getAttributes(), "id"), parseInteger(innerNode.getAttributes(), "level")));
break;
}
case "attack_skill":

View File

@@ -33,8 +33,7 @@ import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.data.xml.impl.OptionData;
import com.l2jmobius.gameserver.model.L2Augmentation;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.options.Options;
@@ -86,12 +85,11 @@ public class AugmentationData
private final List<List<Integer>> _redSkills = new ArrayList<>();
private final List<List<Integer>> _yellowSkills = new ArrayList<>();
private final Map<Integer, Augmentation> _augmentations = new HashMap<>();
private final List<AugmentationChance> _augmentationChances = new ArrayList<>();
private final List<augmentationChanceAcc> _augmentationChancesAcc = new ArrayList<>();
private final List<Integer> _augmentationStones = new ArrayList<>();
private final Map<Integer, SkillHolder> _allSkills = new HashMap<>();
protected AugmentationData()
{
for (int i = 0; i < 10; i++)
@@ -297,8 +295,6 @@ public class AugmentationData
{
_redSkills.get(k).add(augmentationId);
}
_allSkills.put(augmentationId, new SkillHolder(skillId, skillLvL));
}
}
}
@@ -520,6 +516,11 @@ public class AugmentationData
}
}
public Augmentation getAugmentation(int id)
{
return _augmentations.computeIfAbsent(id, k -> new Augmentation(k));
}
/**
* Generate a new random augmentation
* @param lifeStoneLevel
@@ -529,7 +530,7 @@ public class AugmentationData
* @param targetItem
* @return
*/
public L2Augmentation generateRandomAugmentation(int lifeStoneLevel, int lifeStoneGrade, int bodyPart, int lifeStoneId, L2ItemInstance targetItem)
public Augmentation generateRandomAugmentation(int lifeStoneLevel, int lifeStoneGrade, int bodyPart, int lifeStoneId, L2ItemInstance targetItem)
{
switch (bodyPart)
{
@@ -546,7 +547,7 @@ public class AugmentationData
}
}
private L2Augmentation generateRandomWeaponAugmentation(int lifeStoneLevel, int lifeStoneGrade, int lifeStoneId, L2ItemInstance item)
private Augmentation generateRandomWeaponAugmentation(int lifeStoneLevel, int lifeStoneGrade, int lifeStoneId, L2ItemInstance item)
{
int stat12 = 0;
int stat34 = 0;
@@ -739,7 +740,8 @@ public class AugmentationData
}
}
}
return new L2Augmentation(((stat34 << 16) + stat12));
final int augmentationId = ((stat34 << 16) + stat12);
return getAugmentation(augmentationId);
}
boolean generateSkill = false;
boolean generateGlow = false;
@@ -916,10 +918,10 @@ public class AugmentationData
{
LOGGER.info(getClass().getSimpleName() + ": Augmentation success: stat12=" + stat12 + "; stat34=" + stat34 + "; resultColor=" + resultColor + "; level=" + lifeStoneLevel + "; grade=" + lifeStoneGrade);
}
return new L2Augmentation(((stat34 << 16) + stat12));
return new Augmentation(((stat34 << 16) + stat12));
}
private L2Augmentation generateRandomAccessoryAugmentation(int lifeStoneLevel, int bodyPart, int lifeStoneId)
private Augmentation generateRandomAccessoryAugmentation(int lifeStoneLevel, int bodyPart, int lifeStoneId)
{
int stat12 = 0;
int stat34 = 0;
@@ -987,7 +989,8 @@ public class AugmentationData
}
}
return new L2Augmentation(((stat34 << 16) + stat12));
final int augmentationId = ((stat34 << 16) + stat12);
return getAugmentation(augmentationId);
}
lifeStoneLevel = Math.min(lifeStoneLevel, 9);
int base = 0;
@@ -1031,7 +1034,7 @@ public class AugmentationData
op = OptionData.getInstance().getOptions(stat34);
}
if ((op == null) || (!op.hasActiveSkill() && !op.hasPassiveSkill() && !op.hasActivationSkills()))
if ((op == null) || (!op.hasActiveSkills() && !op.hasPassiveSkills() && !op.hasActivationSkills()))
{
// second augmentation (stats)
// calculating any different from stat12 value inside sub-block
@@ -1048,7 +1051,8 @@ public class AugmentationData
{
LOGGER.info(getClass().getSimpleName() + ": Accessory augmentation success: stat12=" + stat12 + "; stat34=" + stat34 + "; level=" + lifeStoneLevel);
}
return new L2Augmentation(((stat34 << 16) + stat12));
final int augmentationId = ((stat34 << 16) + stat12);
return getAugmentation(augmentationId);
}
public boolean isAugmentaionStoneValid(int stoneId)

View File

@@ -74,7 +74,6 @@ public final class MapRegionManager implements IGameXmlReader
String name;
String town;
int locId;
int castle;
int bbs;
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
@@ -89,10 +88,9 @@ public final class MapRegionManager implements IGameXmlReader
name = attrs.getNamedItem("name").getNodeValue();
town = attrs.getNamedItem("town").getNodeValue();
locId = parseInteger(attrs, "locId");
castle = parseInteger(attrs, "castle");
bbs = parseInteger(attrs, "bbs");
final L2MapRegion region = new L2MapRegion(name, town, locId, castle, bbs);
final L2MapRegion region = new L2MapRegion(name, town, locId, bbs);
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
attrs = c.getAttributes();
@@ -224,22 +222,6 @@ public final class MapRegionManager implements IGameXmlReader
return region.getTown();
}
/**
* @param activeChar
* @return
*/
public int getAreaCastle(L2Character activeChar)
{
final L2MapRegion region = getMapRegion(activeChar);
if (region == null)
{
return 0;
}
return region.getCastle();
}
/**
* @param activeChar
* @param teleportWhere

View File

@@ -1,121 +0,0 @@
/*
* 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 com.l2jmobius.gameserver.instancemanager;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.type.L2TownZone;
public final class TownManager
{
public static int getTownCastle(int townId)
{
switch (townId)
{
case 912:
{
return 1;
}
case 916:
{
return 2;
}
case 918:
{
return 3;
}
case 922:
{
return 4;
}
case 924:
{
return 5;
}
case 926:
{
return 6;
}
case 1538:
{
return 7;
}
case 1537:
{
return 8;
}
case 1714:
{
return 9;
}
default:
{
return 0;
}
}
}
public static boolean townHasCastleInSiege(int townId)
{
final int castleId = getTownCastle(townId);
if (castleId > 0)
{
final Castle castle = CastleManager.getInstance().getCastleById(castleId);
if (castle != null)
{
return castle.getSiege().isInProgress();
}
}
return false;
}
public static boolean townHasCastleInSiege(int x, int y)
{
return townHasCastleInSiege(MapRegionManager.getInstance().getMapRegionLocId(x, y));
}
public static L2TownZone getTown(int townId)
{
for (L2TownZone temp : ZoneManager.getInstance().getAllZones(L2TownZone.class))
{
if (temp.getTownId() == townId)
{
return temp;
}
}
return null;
}
/**
* Returns the town at that position (if any)
* @param x
* @param y
* @param z
* @return
*/
public static L2TownZone getTown(int x, int y, int z)
{
for (L2ZoneType temp : ZoneManager.getInstance().getZones(x, y, z))
{
if (temp instanceof L2TownZone)
{
return (L2TownZone) temp;
}
}
return null;
}
}

View File

@@ -1,107 +1,95 @@
/*
* 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 com.l2jmobius.gameserver.model;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.data.xml.impl.OptionData;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.options.Options;
/**
* Used to store an augmentation and its bonuses.
* @author durgus, UnAfraid
*/
public final class L2Augmentation
{
private static final Logger LOGGER = Logger.getLogger(L2Augmentation.class.getName());
private final List<Options> _options = new ArrayList<>();
private boolean _active;
private final int _id;
public L2Augmentation(int id)
{
_id = id;
_active = false;
final int[] stats = new int[2];
stats[0] = 0x0000FFFF & id;
stats[1] = (id >> 16);
for (int stat : stats)
{
final Options op = OptionData.getInstance().getOptions(stat);
if (op != null)
{
_options.add(op);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Couldn't find option: " + stat);
}
}
}
/**
* Get the augmentation "id" used in serverpackets.
* @return augmentationId
*/
public int getId()
{
return _id;
}
public List<Options> getOptions()
{
return _options;
}
public void applyBonus(L2PcInstance player)
{
// make sure the bonuses are not applied twice..
if (_active)
{
return;
}
for (Options op : _options)
{
op.apply(player);
}
player.getStat().recalculateStats(true);
_active = true;
}
public void removeBonus(L2PcInstance player)
{
// make sure the bonuses are not removed twice
if (!_active)
{
return;
}
for (Options op : _options)
{
op.remove(player);
}
player.getStat().recalculateStats(true);
_active = false;
}
}
/*
* 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 com.l2jmobius.gameserver.model;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.data.xml.impl.OptionData;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.options.Options;
/**
* Used to store an augmentation and its bonuses.
* @author durgus, UnAfraid
*/
public final class Augmentation
{
private static final Logger LOGGER = Logger.getLogger(Augmentation.class.getName());
private final Options[] _options;
private final int _id;
public Augmentation(int id)
{
_id = id;
final int[] stats = new int[2];
stats[0] = 0x0000FFFF & id;
stats[1] = (id >> 16);
_options = new Options[stats.length];
for (int i = 0; i < stats.length; i++)
{
final Options op = OptionData.getInstance().getOptions(stats[i]);
if (op != null)
{
_options[i] = op;
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Couldn't find option: " + stats[i]);
}
}
}
/**
* Get the augmentation "id" used in serverpackets.
* @return augmentationId
*/
public int getId()
{
return _id;
}
public Options[] getOptions()
{
return _options;
}
public int getOptionId(int index)
{
if ((index >= 0) && (index < _options.length) && (_options[index] != null))
{
return _options[index].getId();
}
return 0;
}
public void applyBonus(L2PcInstance player)
{
for (Options op : _options)
{
op.apply(player);
}
}
public void removeBonus(L2PcInstance player)
{
for (Options op : _options)
{
op.remove(player);
}
}
}

View File

@@ -50,7 +50,7 @@ public class CharSelectInfoPackage
private int _reputation = 0;
private int _pkKills = 0;
private int _pvpKills = 0;
private int _augmentationId = 0;
private Augmentation _augmentation;
private int _x = 0;
private int _y = 0;
private int _z = 0;
@@ -336,14 +336,14 @@ public class CharSelectInfoPackage
return _reputation;
}
public void setAugmentationId(int augmentationId)
public void setAugmentation(Augmentation augmentation)
{
_augmentationId = augmentationId;
_augmentation = augmentation;
}
public int getAugmentationId()
public Augmentation getAugmentation()
{
return _augmentationId;
return _augmentation;
}
public void setPkKills(int PkKills)

View File

@@ -39,10 +39,10 @@ public class ItemInfo
private L2Item _item;
/** The level of enchant on the L2ItemInstance */
private int _enchant;
private int _enchantLevel;
/** The augmentation of the item */
private int _augmentation;
private Augmentation _augmentation;
/** The quantity of L2ItemInstance */
private long _count;
@@ -68,7 +68,7 @@ public class ItemInfo
private byte _elemAtkType = -2;
private int _elemAtkPower = 0;
private final int[] _elemDefAttr =
private final int[] _attributeDefence =
{
0,
0,
@@ -99,17 +99,10 @@ public class ItemInfo
_item = item.getItem();
// Get the enchant level of the L2ItemInstance
_enchant = item.getEnchantLevel();
_enchantLevel = item.getEnchantLevel();
// Get the augmentation boni
if (item.isAugmented())
{
_augmentation = item.getAugmentation().getId();
}
else
{
_augmentation = 0;
}
// Get the augmentation bonus
_augmentation = item.getAugmentation();
// Get the quantity of the L2ItemInstance
_count = item.getCount();
@@ -150,7 +143,7 @@ public class ItemInfo
_elemAtkPower = item.getAttackAttributePower();
for (AttributeType type : AttributeType.ATTRIBUTE_TYPES)
{
_elemDefAttr[type.getClientId()] = item.getDefenceAttribute(type);
_attributeDefence[type.getClientId()] = item.getDefenceAttribute(type);
}
_option = item.getEnchantOptions();
_soulCrystalOptions = item.getSpecialAbilities();
@@ -179,10 +172,10 @@ public class ItemInfo
_item = item.getItem();
// Get the enchant level of the L2ItemInstance
_enchant = item.getEnchant();
_enchantLevel = item.getEnchant();
// Get the augmentation bonus
_augmentation = item.getAugmentId();
_augmentation = item.getAugmentation();
// Get the quantity of the L2ItemInstance
_count = item.getCount();
@@ -207,7 +200,7 @@ public class ItemInfo
_elemAtkPower = item.getAttackElementPower();
for (byte i = 0; i < 6; i++)
{
_elemDefAttr[i] = item.getElementDefAttr(i);
_attributeDefence[i] = item.getElementDefAttr(i);
}
_option = item.getEnchantOptions();
@@ -230,10 +223,10 @@ public class ItemInfo
_item = item.getItem();
// Get the enchant level of the L2ItemInstance
_enchant = 0;
_enchantLevel = 0;
// Get the augmentation boni
_augmentation = 0;
// Get the augmentation bonus
_augmentation = null;
// Get the quantity of the L2ItemInstance
_count = item.getCount();
@@ -272,17 +265,10 @@ public class ItemInfo
_item = item.getItem();
// Get the enchant level of the L2ItemInstance
_enchant = item.getEnchantLevel();
_enchantLevel = item.getEnchantLevel();
// Get the augmentation boni
if (item.isAugmented())
{
_augmentation = item.getAugmentationId();
}
else
{
_augmentation = 0;
}
// Get the augmentation bonus
_augmentation = item.getAugmentation();
// Get the quantity of the L2ItemInstance
_count = item.getCount();
@@ -303,7 +289,7 @@ public class ItemInfo
_elemAtkPower = item.getAttackElementPower();
for (byte i = 0; i < 6; i++)
{
_elemDefAttr[i] = item.getElementDefAttr(i);
_attributeDefence[i] = item.getElementDefAttr(i);
}
_option = item.getEnchantOptions();
_soulCrystalOptions = item.getSoulCrystalOptions();
@@ -320,26 +306,16 @@ public class ItemInfo
return _item;
}
public int getEnchant()
public int getEnchantLevel()
{
return _enchant;
return _enchantLevel;
}
public int getAugmentationBonus()
public Augmentation getAugmentation()
{
return _augmentation;
}
public int get1stAugmentationId()
{
return 0x0000FFFF & getAugmentationBonus();
}
public int get2ndAugmentationId()
{
return getAugmentationBonus() >> 16;
}
public long getCount()
{
return _count;
@@ -395,9 +371,9 @@ public class ItemInfo
return _elemAtkPower;
}
public int getElementDefAttr(byte i)
public int getAttributeDefence(AttributeType attribute)
{
return _elemDefAttr[i];
return _attributeDefence[attribute.getClientId()];
}
public int[] getEnchantOptions()
@@ -412,12 +388,12 @@ public class ItemInfo
public Collection<EnsoulOption> getSoulCrystalOptions()
{
return _soulCrystalOptions;
return _soulCrystalOptions != null ? _soulCrystalOptions : Collections.emptyList();
}
public Collection<EnsoulOption> getSoulCrystalSpecialOptions()
{
return _soulCrystalSpecialOptions;
return _soulCrystalSpecialOptions != null ? _soulCrystalSpecialOptions : Collections.emptyList();
}
public long getVisualExpiration()

View File

@@ -33,7 +33,6 @@ public class L2MapRegion
private final String _name;
private final String _town;
private final int _locId;
private final int _castle;
private final int _bbs;
private List<int[]> _maps = null;
@@ -44,12 +43,11 @@ public class L2MapRegion
private final Map<Race, String> _bannedRace = new HashMap<>();
public L2MapRegion(String name, String town, int locId, int castle, int bbs)
public L2MapRegion(String name, String town, int locId, int bbs)
{
_name = name;
_town = town;
_locId = locId;
_castle = castle;
_bbs = bbs;
}
@@ -68,11 +66,6 @@ public class L2MapRegion
return _locId;
}
public final int getCastle()
{
return _castle;
}
public final int getBbs()
{
return _bbs;

View File

@@ -711,6 +711,20 @@ public class StatsSet implements IParserAdvUtils
return (A) obj;
}
@SuppressWarnings("unchecked")
public final <A> A getObject(String name, Class<A> type, A defaultValue)
{
Objects.requireNonNull(name);
Objects.requireNonNull(type);
final Object obj = _set.get(name);
if ((obj == null) || !type.isAssignableFrom(obj.getClass()))
{
return defaultValue;
}
return (A) obj;
}
public SkillHolder getSkillHolder(String key)
{
Objects.requireNonNull(key);

View File

@@ -51,7 +51,7 @@ public class TradeItem
private final Collection<EnsoulOption> _soulCrystalOptions;
private final Collection<EnsoulOption> _soulCrystalSpecialOptions;
private int _visualId;
private int _augmentId;
private Augmentation _augmentation;
public TradeItem(L2ItemInstance item, long count, long price)
{
@@ -74,7 +74,7 @@ public class TradeItem
_soulCrystalOptions = item.getSpecialAbilities();
_soulCrystalSpecialOptions = item.getAdditionalSpecialAbilities();
_visualId = item.getVisualId();
_augmentId = item.isAugmented() ? item.getAugmentation().getId() : 0;
_augmentation = item.getAugmentation();
}
public TradeItem(L2Item item, long count, long price)
@@ -215,9 +215,9 @@ public class TradeItem
return _soulCrystalSpecialOptions;
}
public int getAugmentId()
public Augmentation getAugmentation()
{
return _augmentId;
return _augmentation;
}
public int getVisualId()

View File

@@ -323,6 +323,12 @@ public class TradeList
return null;
}
if (count < 0)
{
_log.warning(_owner.getName() + ": Attempt to remove " + count + " items from TradeList!");
return null;
}
for (TradeItem titem : _items)
{
if ((titem.getObjectId() == objectId) || (titem.getItem().getId() == itemId))
@@ -881,10 +887,10 @@ public class TradeList
/**
* Sell items to this PrivateStore list
* @param player
* @param items
* @param requestedItems
* @return : boolean true if success
*/
public synchronized boolean privateStoreSell(L2PcInstance player, ItemRequest[] items)
public synchronized boolean privateStoreSell(L2PcInstance player, ItemRequest[] requestedItems)
{
if (_locked)
{
@@ -907,12 +913,14 @@ public class TradeList
long totalPrice = 0;
for (ItemRequest item : items)
final TradeItem[] sellerItems = _items.toArray(new TradeItem[0]);
for (ItemRequest item : requestedItems)
{
// searching item in tradelist using itemId
boolean found = false;
for (TradeItem ti : _items)
for (TradeItem ti : sellerItems)
{
if (ti.getItem().getId() == item.getItemId())
{
@@ -956,8 +964,19 @@ public class TradeList
continue;
}
if ((item.getObjectId() < 1) || (item.getObjectId() > sellerItems.length))
{
continue;
}
final TradeItem tradeItem = sellerItems[item.getObjectId() - 1];
if ((tradeItem == null) || (tradeItem.getItem().getId() != item.getItemId()))
{
continue;
}
// Check if requested item is available for manipulation
int objectId = item.getObjectId();
int objectId = tradeItem.getObjectId();
L2ItemInstance oldItem = player.checkItemManipulation(objectId, item.getCount(), "sell");
// private store - buy use same objectId for buying several non-stackable items
if (oldItem == null)

View File

@@ -34,6 +34,7 @@ import com.l2jmobius.gameserver.enums.MpRewardAffectType;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.enums.Race;
import com.l2jmobius.gameserver.enums.ShotType;
import com.l2jmobius.gameserver.enums.TaxType;
import com.l2jmobius.gameserver.enums.Team;
import com.l2jmobius.gameserver.enums.UserInfoType;
import com.l2jmobius.gameserver.handler.BypassHandler;
@@ -42,7 +43,6 @@ import com.l2jmobius.gameserver.instancemanager.CastleManager;
import com.l2jmobius.gameserver.instancemanager.DBSpawnManager;
import com.l2jmobius.gameserver.instancemanager.DBSpawnManager.DBStatusType;
import com.l2jmobius.gameserver.instancemanager.FortManager;
import com.l2jmobius.gameserver.instancemanager.TownManager;
import com.l2jmobius.gameserver.instancemanager.WalkingManager;
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
import com.l2jmobius.gameserver.model.L2Object;
@@ -83,6 +83,7 @@ import com.l2jmobius.gameserver.model.spawns.NpcSpawnTemplate;
import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.variables.NpcVariables;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.model.zone.type.L2TaxZone;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
@@ -154,6 +155,9 @@ public class L2Npc extends L2Character
private StatsSet _params;
private DBSpawnManager.DBStatusType _raidStatus;
/** Contains information about local tax payments. */
private L2TaxZone _taxZone = null;
/**
* Constructor of L2NpcInstance (use L2Character constructor).<br>
* <B><U>Actions</U>:</B>
@@ -519,6 +523,48 @@ public class L2Npc extends L2Character
return true;
}
/**
* Set another tax zone which will be used for tax payments.
* @param zone newly entered tax zone
*/
public final void setTaxZone(L2TaxZone zone)
{
_taxZone = ((zone != null) && !isInInstance()) ? zone : null;
}
/**
* Gets castle for tax payments.
* @return instance of {@link Castle} when NPC is inside {@link L2TaxZone} otherwise {@code null}
*/
public final Castle getTaxCastle()
{
return (_taxZone != null) ? _taxZone.getCastle() : null;
}
/**
* Gets castle tax rate
* @param type type of tax
* @return tax rate when NPC is inside tax zone otherwise {@code 0}
*/
public final double getCastleTaxRate(TaxType type)
{
final Castle castle = getTaxCastle();
return (castle != null) ? (castle.getTaxPercent(type) / 100.0) : 0;
}
/**
* Increase castle vault by specified tax amount.
* @param amount tax amount
*/
public final void handleTaxPayment(long amount)
{
final Castle taxCastle = getTaxCastle();
if (taxCastle != null)
{
taxCastle.addToTreasury(amount);
}
}
/**
* @return the nearest L2Castle this L2NpcInstance belongs to. Otherwise null.
*/
@@ -560,11 +606,6 @@ public class L2Npc extends L2Character
return FortManager.getInstance().findNearestFort(this, maxDistance);
}
public final boolean isInTown()
{
return TownManager.getTown(getX(), getY(), getZ()) != null;
}
/**
* Open a quest or chat window on client with the text of the L2NpcInstance in function of the command.<br>
* <B><U> Example of use </U> :</B>
@@ -1063,14 +1104,9 @@ public class L2Npc extends L2Character
WalkingManager.getInstance().onSpawn(this);
}
// Display clan flag
if (isInsideZone(ZoneId.TOWN) && (getCastle() != null) && (Config.SHOW_CREST_WITHOUT_QUEST || getCastle().getShowNpcCrest()) && (getCastle().getOwnerId() != 0))
if (isInsideZone(ZoneId.TAX) && (getCastle() != null) && (Config.SHOW_CREST_WITHOUT_QUEST || getCastle().getShowNpcCrest()) && (getCastle().getOwnerId() != 0))
{
final int townId = TownManager.getTown(getX(), getY(), getZ()).getTownId();
if ((townId != 33) && (townId != 22))
{
setClanId(getCastle().getOwnerId());
}
setClanId(getCastle().getOwnerId());
}
}
@@ -1079,12 +1115,12 @@ public class L2Npc extends L2Character
*/
public void onRespawn()
{
// Stop all effects and recalculate stats without broadcasting.
getEffectList().stopAllEffects(false);
// Make it alive
setIsDead(false);
// Stop all effects and recalculate stats without broadcasting.
getEffectList().stopAllEffects(false);
// Reset decay info
setDecayed(false);
@@ -1827,11 +1863,17 @@ public class L2Npc extends L2Character
initSeenCreatures(getTemplate().getAggroRange());
}
/**
* @return the NpcStringId for name
*/
public NpcStringId getNameString()
{
return _nameString;
}
/**
* @return the NpcStringId for title
*/
public NpcStringId getTitleString()
{
return _titleString;

View File

@@ -21,7 +21,7 @@ import com.l2jmobius.gameserver.enums.InstanceType;
import com.l2jmobius.gameserver.enums.TaxType;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.model.buylist.L2BuyList;
import com.l2jmobius.gameserver.model.buylist.ProductList;
import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import com.l2jmobius.gameserver.network.serverpackets.BuyList;
import com.l2jmobius.gameserver.network.serverpackets.ExBuySellList;
@@ -52,8 +52,7 @@ public class L2MerchantInstance extends L2NpcInstance
@Override
public String getHtmlPath(int npcId, int val)
{
String pom = "";
String pom;
if (val == 0)
{
pom = "" + npcId;
@@ -62,7 +61,6 @@ public class L2MerchantInstance extends L2NpcInstance
{
pom = npcId + "-" + val;
}
return "data/html/merchant/" + pom + ".htm";
}
@@ -71,9 +69,9 @@ public class L2MerchantInstance extends L2NpcInstance
showBuyWindow(player, val, true);
}
public final void showBuyWindow(L2PcInstance player, int val, boolean applyTax)
public final void showBuyWindow(L2PcInstance player, int val, boolean applyCastleTax)
{
final L2BuyList buyList = BuyListData.getInstance().getBuyList(val);
final ProductList buyList = BuyListData.getInstance().getBuyList(val);
if (buyList == null)
{
_log.warning("BuyList not found! BuyListId:" + val);
@@ -90,23 +88,7 @@ public class L2MerchantInstance extends L2NpcInstance
player.setInventoryBlockingStatus(true);
player.sendPacket(new BuyList(buyList, player.getAdena(), (applyTax) ? getTotalTaxRate(TaxType.BUY) : 0));
player.sendPacket(new ExBuySellList(player, false, (applyTax) ? getTotalTaxRate(TaxType.SELL) : 0));
player.sendPacket(ActionFailed.STATIC_PACKET);
}
public boolean hasCastle()
{
return getCastle() != null;
}
public int getTotalTax(TaxType taxType)
{
return hasCastle() ? getCastle().getTaxPercent(taxType) : 0;
}
public double getTotalTaxRate(TaxType taxType)
{
return getTotalTax(taxType) / 100.0;
player.sendPacket(new BuyList(buyList, player, (applyCastleTax) ? getCastleTaxRate(TaxType.BUY) : 0));
player.sendPacket(new ExBuySellList(player, false, (applyCastleTax) ? getCastleTaxRate(TaxType.SELL) : 0));
}
}

View File

@@ -161,7 +161,6 @@ import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.actor.status.PcStatus;
import com.l2jmobius.gameserver.model.actor.tasks.player.DismountTask;
import com.l2jmobius.gameserver.model.actor.tasks.player.FameTask;
import com.l2jmobius.gameserver.model.actor.tasks.player.GameGuardCheckTask;
import com.l2jmobius.gameserver.model.actor.tasks.player.HennaDurationTask;
import com.l2jmobius.gameserver.model.actor.tasks.player.InventoryEnableTask;
import com.l2jmobius.gameserver.model.actor.tasks.player.PetFeedTask;
@@ -211,6 +210,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubCh
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MovieHolder;
import com.l2jmobius.gameserver.model.holders.PlayerEventHolder;
import com.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder;
import com.l2jmobius.gameserver.model.holders.SellBuffHolder;
import com.l2jmobius.gameserver.model.holders.SkillUseHolder;
import com.l2jmobius.gameserver.model.holders.TrainingHolder;
@@ -234,7 +234,6 @@ import com.l2jmobius.gameserver.model.items.type.ArmorType;
import com.l2jmobius.gameserver.model.items.type.EtcItemType;
import com.l2jmobius.gameserver.model.items.type.WeaponType;
import com.l2jmobius.gameserver.model.matching.MatchingRoom;
import com.l2jmobius.gameserver.model.multisell.PreparedListContainer;
import com.l2jmobius.gameserver.model.olympiad.OlympiadGameManager;
import com.l2jmobius.gameserver.model.olympiad.OlympiadGameTask;
import com.l2jmobius.gameserver.model.olympiad.OlympiadManager;
@@ -288,7 +287,6 @@ import com.l2jmobius.gameserver.network.serverpackets.ExUseSharedGroupItem;
import com.l2jmobius.gameserver.network.serverpackets.ExUserInfoAbnormalVisualEffect;
import com.l2jmobius.gameserver.network.serverpackets.ExUserInfoCubic;
import com.l2jmobius.gameserver.network.serverpackets.ExUserInfoInvenWeight;
import com.l2jmobius.gameserver.network.serverpackets.GameGuardQuery;
import com.l2jmobius.gameserver.network.serverpackets.GetOnVehicle;
import com.l2jmobius.gameserver.network.serverpackets.HennaInfo;
import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
@@ -559,7 +557,7 @@ public final class L2PcInstance extends L2Playable
private TradeList _buyList;
// Multisell
private PreparedListContainer _currentMultiSell = null;
private PreparedMultisellListHolder _currentMultiSell = null;
private int _nobleLevel = 0;
private boolean _hero = false;
@@ -4334,6 +4332,8 @@ public final class L2PcInstance extends L2Playable
return getClan().getAllyCrestId();
}
//@formatter:off
/*
public void queryGameGuard()
{
if (getClient() != null)
@@ -4343,9 +4343,10 @@ public final class L2PcInstance extends L2Playable
}
if (Config.GAMEGUARD_ENFORCE)
{
ThreadPoolManager.schedule(new GameGuardCheckTask(this), 30 * 1000);
ThreadPoolManager.scheduleGeneral(new GameGuardCheckTask(this), 30 * 1000);
}
}
}*/
//@formatter:on
/**
* Send a Server->Client packet StatusUpdate to the L2PcInstance.
@@ -4710,12 +4711,12 @@ public final class L2PcInstance extends L2Playable
}
}
public final PreparedListContainer getMultiSell()
public final PreparedMultisellListHolder getMultiSell()
{
return _currentMultiSell;
}
public final void setMultiSell(PreparedListContainer list)
public final void setMultiSell(PreparedMultisellListHolder list)
{
_currentMultiSell = list;
}

View File

@@ -25,9 +25,11 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.items.type.EtcItemType;
/**
* @author NosBit
@@ -41,28 +43,25 @@ public final class Product
private final long _price;
private final long _restockDelay;
private final long _maxCount;
private final double _baseTax;
private AtomicLong _count = null;
private ScheduledFuture<?> _restockTask = null;
public Product(int buyListId, L2Item item, long price, long restockDelay, long maxCount)
public Product(int buyListId, L2Item item, long price, long restockDelay, long maxCount, int baseTax)
{
Objects.requireNonNull(item);
_buyListId = buyListId;
_item = item;
_price = price;
_price = (price < 0) ? item.getReferencePrice() : price;
_restockDelay = restockDelay * 60000;
_maxCount = maxCount;
_baseTax = baseTax / 100.0;
if (hasLimitedStock())
{
_count = new AtomicLong(maxCount);
}
}
public int getBuyListId()
{
return _buyListId;
}
public L2Item getItem()
{
return _item;
@@ -75,11 +74,17 @@ public final class Product
public long getPrice()
{
if (_price < 0)
long price = _price;
if (_item.getItemType().equals(EtcItemType.CASTLE_GUARD))
{
return getItem().getReferencePrice();
price *= Config.RATE_SIEGE_GUARDS_PRICE;
}
return _price;
return price;
}
public double getBaseTaxRate()
{
return _baseTax;
}
public long getRestockDelay()
@@ -155,7 +160,7 @@ public final class Product
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO `buylists`(`buylist_id`, `item_id`, `count`, `next_restock_time`) VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE `count` = ?, `next_restock_time` = ?"))
{
statement.setInt(1, getBuyListId());
statement.setInt(1, _buyListId);
statement.setInt(2, getItemId());
statement.setLong(3, getCount());
statement.setLong(5, getCount());
@@ -174,7 +179,7 @@ public final class Product
}
catch (Exception e)
{
_log.log(Level.WARNING, "Failed to save Product buylist_id:" + getBuyListId() + " item_id:" + getItemId(), e);
_log.log(Level.WARNING, "Failed to save Product buylist_id:" + _buyListId + " item_id:" + getItemId(), e);
}
}
}

View File

@@ -25,13 +25,13 @@ import java.util.Set;
/**
* @author NosBit
*/
public final class L2BuyList
public final class ProductList
{
private final int _listId;
private final Map<Integer, Product> _products = new LinkedHashMap<>();
private Set<Integer> _allowedNpcs = null;
public L2BuyList(int listId)
public ProductList(int listId)
{
_listId = listId;
}
@@ -70,8 +70,8 @@ public final class L2BuyList
return (_allowedNpcs != null) && _allowedNpcs.contains(npcId);
}
public Set<Integer> getNpcsAllowed()
{
return _allowedNpcs;
}
//public Set<Integer> getNpcsAllowed()
//{
// return _allowedNpcs;
//}
}

View File

@@ -49,4 +49,10 @@ public class EnsoulOption extends SkillHolder
{
return _desc;
}
@Override
public String toString()
{
return "Ensoul Id: " + _id + " Name: " + _name + " Desc: " + _desc;
}
}

View File

@@ -78,7 +78,6 @@ public final class Castle extends AbstractResidence
private boolean _isTimeRegistrationOver = true; // true if Castle Lords set the time, or 24h is elapsed after the siege
private Calendar _siegeTimeRegistrationEndDate; // last siege end date + 1 day
private CastleSide _castleSide = null;
private double _taxRate;
private long _treasury = 0;
private boolean _showNpcCrest = false;
private L2SiegeZone _zone = null;
@@ -301,7 +300,7 @@ public final class Castle extends AbstractResidence
final Castle rune = CastleManager.getInstance().getCastle("rune");
if (rune != null)
{
final long runeTax = (long) (amount * rune.getTaxRate());
final long runeTax = (long) (amount * rune.getTaxRate(TaxType.BUY));
if (rune.getOwnerId() > 0)
{
rune.addToTreasury(runeTax);
@@ -319,7 +318,7 @@ public final class Castle extends AbstractResidence
final Castle aden = CastleManager.getInstance().getCastle("aden");
if (aden != null)
{
final long adenTax = (long) (amount * aden.getTaxRate()); // Find out what Aden gets from the current castle instance's income
final long adenTax = (long) (amount * aden.getTaxRate(TaxType.BUY)); // Find out what Aden gets from the current castle instance's income
if (aden.getOwnerId() > 0)
{
aden.addToTreasury(adenTax); // Only bother to really add the tax to the treasury if not npc owned
@@ -673,7 +672,6 @@ public final class Castle extends AbstractResidence
}
}
setTaxRate(getTaxPercent(TaxType.BUY) / 100);
ps2.setInt(1, getResidenceId());
try (ResultSet rs = ps2.executeQuery())
{
@@ -980,14 +978,9 @@ public final class Castle extends AbstractResidence
return taxPercent;
}
public void setTaxRate(double taxRate)
public final double getTaxRate(TaxType taxType)
{
_taxRate = taxRate;
}
public final double getTaxRate()
{
return _taxRate;
return getTaxPercent(taxType) / 100.0;
}
public final long getTreasury()
@@ -1229,7 +1222,6 @@ public final class Castle extends AbstractResidence
_log.log(Level.WARNING, e.getMessage(), e);
}
_castleSide = side;
setTaxRate(getTaxPercent(TaxType.BUY) / 100);
Broadcast.toAllOnlinePlayers(new ExCastleState(this));
spawnSideNpcs();
}

View File

@@ -2700,7 +2700,7 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime
// set enchant level for item if that item is not adena
if ((attributeType != null) && (attributeValue > 0))
{
item.setAttribute(new AttributeHolder(attributeType, attributeValue));
item.setAttribute(new AttributeHolder(attributeType, attributeValue), true);
if (item.isEquipped())
{
// Recalculate all stats

View File

@@ -16,7 +16,7 @@
*/
package com.l2jmobius.gameserver.model.events.impl.character.player;
import com.l2jmobius.gameserver.model.L2Augmentation;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.impl.IBaseEvent;
@@ -29,10 +29,10 @@ public class OnPlayerAugment implements IBaseEvent
{
private final L2PcInstance _activeChar;
private final L2ItemInstance _item;
private final L2Augmentation _augmentation;
private final Augmentation _augmentation;
private final boolean _isAugment; // true = is being augmented // false = augment is being removed
public OnPlayerAugment(L2PcInstance activeChar, L2ItemInstance item, L2Augmentation augment, boolean isAugment)
public OnPlayerAugment(L2PcInstance activeChar, L2ItemInstance item, Augmentation augment, boolean isAugment)
{
_activeChar = activeChar;
_item = item;
@@ -50,7 +50,7 @@ public class OnPlayerAugment implements IBaseEvent
return _item;
}
public L2Augmentation getAugmentation()
public Augmentation getAugmentation()
{
return _augmentation;
}

View File

@@ -16,6 +16,10 @@
*/
package com.l2jmobius.gameserver.model.holders;
import java.util.List;
import com.l2jmobius.commons.util.Rnd;
/**
* A DTO for items; contains item ID, count and chance.<br>
* Complemented by {@link QuestItemHolder}.
@@ -45,6 +49,34 @@ public class ItemChanceHolder extends ItemHolder
return _chance;
}
/**
* Calculates a cumulative chance of all given holders. If all holders' chance sum up to 100% or above, there is 100% guarantee a holder will be selected.
* @param holders list of holders to calculate chance from.
* @return {@code ItemChanceHolder} of the successful random roll or {@code null} if there was no lucky holder selected.
*/
public static ItemChanceHolder getRandomHolder(List<ItemChanceHolder> holders)
{
double itemRandom = 100 * Rnd.nextDouble();
for (ItemChanceHolder holder : holders)
{
// Any mathmatical expression including NaN will result in either NaN or 0 of converted to something other than double.
// We would usually want to skip calculating any holders that include NaN as a chance, because that ruins the overall process.
if (!Double.isNaN(holder.getChance()))
{
// Calculate chance
if (holder.getChance() > itemRandom)
{
return holder;
}
itemRandom -= holder.getChance();
}
}
return null;
}
@Override
public String toString()
{

View File

@@ -0,0 +1,56 @@
/*
* 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 com.l2jmobius.gameserver.model.holders;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.items.L2Item;
/**
* @author Nik
*/
public class MultisellEntryHolder
{
private final boolean _stackable;
private final List<ItemHolder> _ingredients;
private final List<ItemChanceHolder> _products;
public MultisellEntryHolder(List<ItemHolder> ingredients, List<ItemChanceHolder> products)
{
_ingredients = Collections.unmodifiableList(ingredients);
_products = Collections.unmodifiableList(products);
_stackable = products.stream().map(i -> ItemTable.getInstance().getTemplate(i.getId())).filter(Objects::nonNull).allMatch(L2Item::isStackable);
}
public final List<ItemHolder> getIngredients()
{
return _ingredients;
}
public final List<ItemChanceHolder> getProducts()
{
return _products;
}
public final boolean isStackable()
{
return _stackable;
}
}

View File

@@ -0,0 +1,112 @@
/*
* 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 com.l2jmobius.gameserver.model.holders;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.interfaces.IIdentifiable;
/**
* A static list container of all multisell entries of a given list.
* @author Nik
*/
public class MultisellListHolder implements IIdentifiable
{
private final int _listId;
private final boolean _isChanceMultisell;
private final boolean _applyTaxes;
private final boolean _maintainEnchantment;
private final double _ingredientMultiplier;
private final double _productMultiplier;
protected List<MultisellEntryHolder> _entries;
protected final Set<Integer> _npcsAllowed;
public MultisellListHolder(int listId, boolean isChanceMultisell, boolean applyTaxes, boolean maintainEnchantment, double ingredientMultiplier, double productMultiplier, List<MultisellEntryHolder> entries, Set<Integer> npcsAllowed)
{
_listId = listId;
_isChanceMultisell = isChanceMultisell;
_applyTaxes = applyTaxes;
_maintainEnchantment = maintainEnchantment;
_ingredientMultiplier = ingredientMultiplier;
_productMultiplier = productMultiplier;
_entries = entries;
_npcsAllowed = npcsAllowed;
}
@SuppressWarnings("unchecked")
public MultisellListHolder(StatsSet set)
{
_listId = set.getInt("listId");
_isChanceMultisell = set.getBoolean("isChanceMultisell", false);
_applyTaxes = set.getBoolean("applyTaxes", false);
_maintainEnchantment = set.getBoolean("maintainEnchantment", false);
_ingredientMultiplier = set.getDouble("ingredientMultiplier", 1.0);
_productMultiplier = set.getDouble("productMultiplier", 1.0);
_entries = Collections.unmodifiableList(set.getList("entries", MultisellEntryHolder.class, Collections.emptyList()));
_npcsAllowed = set.getObject("allowNpc", Set.class);
}
public List<MultisellEntryHolder> getEntries()
{
return _entries;
}
@Override
public final int getId()
{
return _listId;
}
public final boolean isChanceMultisell()
{
return _isChanceMultisell;
}
public final boolean isApplyTaxes()
{
return _applyTaxes;
}
public final boolean isMaintainEnchantment()
{
return _maintainEnchantment;
}
public final double getIngredientMultiplier()
{
return _ingredientMultiplier;
}
public final double getProductMultiplier()
{
return _productMultiplier;
}
public final boolean isNpcAllowed(int npcId)
{
return (_npcsAllowed == null) || _npcsAllowed.contains(npcId);
}
public final boolean isNpcOnly()
{
return _npcsAllowed != null;
}
}

View File

@@ -0,0 +1,107 @@
/*
* 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 com.l2jmobius.gameserver.model.holders;
import java.util.ArrayList;
import java.util.List;
import com.l2jmobius.gameserver.enums.TaxType;
import com.l2jmobius.gameserver.model.ItemInfo;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
import com.l2jmobius.gameserver.model.itemcontainer.ItemContainer;
/**
* A modified version of {@link MultisellListHolder} that may include altered data of the original and other dynamic data resulted from players' interraction.
* @author Nik
*/
public class PreparedMultisellListHolder extends MultisellListHolder
{
private int _npcObjectId;
private final boolean _inventoryOnly;
private double _taxRate;
private List<ItemInfo> _itemInfos;
public PreparedMultisellListHolder(MultisellListHolder list, boolean inventoryOnly, ItemContainer inventory, L2Npc npc, double ingredientMultiplier, double productMultiplier)
{
super(list.getId(), list.isChanceMultisell(), list.isApplyTaxes(), list.isMaintainEnchantment(), list.getIngredientMultiplier(), list.getProductMultiplier(), list._entries, list._npcsAllowed);
_inventoryOnly = inventoryOnly;
if (npc != null)
{
_npcObjectId = npc.getObjectId();
_taxRate = npc.getCastleTaxRate(TaxType.BUY);
}
// Display items from inventory that are available for exchange.
if (inventoryOnly)
{
_entries = new ArrayList<>();
_itemInfos = new ArrayList<>();
// Only do the match up on equippable items that are not currently equipped. For each appropriate item, produce a set of entries for the multisell list.
inventory.getItems(item -> !item.isEquipped() && (item.isArmor() || item.isWeapon())).forEach(item ->
{
// Check ingredients of each entry to see if it's an entry we'd like to include.
list.getEntries().stream().filter(e -> e.getIngredients().stream().anyMatch(i -> i.getId() == item.getId())).forEach(e ->
{
_entries.add(e);
_itemInfos.add(new ItemInfo(item));
});
});
}
}
public ItemInfo getItemEnchantment(int index)
{
return _itemInfos != null ? _itemInfos.get(index) : null;
}
public double getTaxRate()
{
return isApplyTaxes() ? _taxRate : 0;
}
public boolean isInventoryOnly()
{
return _inventoryOnly;
}
public final boolean checkNpcObjectId(int npcObjectId)
{
return (_npcObjectId == 0) || (_npcObjectId == npcObjectId);
}
/**
* @param ingredient
* @return the new count of the given ingredient after applying ingredient multiplier and adena tax rate.
*/
public long getIngredientCount(ItemHolder ingredient)
{
return (ingredient.getId() == Inventory.ADENA_ID) ? Math.round(ingredient.getCount() * getIngredientMultiplier() * (1 + _taxRate)) : Math.round(ingredient.getCount() * getIngredientMultiplier());
}
/**
* @param product
* @return the new count of the given product after applying product multiplier.
*/
public long getProductCount(ItemChanceHolder product)
{
return Math.round(product.getCount() * getProductMultiplier());
}
}

View File

@@ -16,9 +16,10 @@
*/
package com.l2jmobius.gameserver.model.itemauction;
import com.l2jmobius.gameserver.datatables.AugmentationData;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.model.L2Augmentation;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
@@ -83,10 +84,10 @@ public final class AuctionItem
L2World.getInstance().storeObject(item);
item.setCount(_itemCount);
item.setEnchantLevel(item.getItem().getDefaultEnchantLevel());
final int augmentationId = _itemExtra.getInt("augmentation_id", 0);
if (augmentationId > 0)
final Augmentation augmentation = AugmentationData.getInstance().getAugmentation(_itemExtra.getInt("augmentation_id", 0));
if (augmentation != null)
{
item.setAugmentation(new L2Augmentation(augmentationId));
item.setAugmentation(augmentation, false);
}
return item;
}

View File

@@ -42,6 +42,7 @@ import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.enums.ItemLocation;
import com.l2jmobius.gameserver.enums.ItemSkillType;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.L2ArmorSet;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.PcCondOverride;
@@ -1021,10 +1022,10 @@ public abstract class Inventory extends ItemContainer
return (item != null) ? item.getVisualId() : 0;
}
public int getPaperdollAugmentationId(int slot)
public Augmentation getPaperdollAugmentation(int slot)
{
final L2ItemInstance item = _paperdoll[slot];
return ((item != null) && (item.getAugmentation() != null)) ? item.getAugmentation().getId() : 0;
return (item != null) ? item.getAugmentation() : null;
}
/**

View File

@@ -159,50 +159,6 @@ public class PcInventory extends Inventory
return list;
}
/**
* Returns the list of items in inventory available for transaction Allows an item to appear twice if and only if there is a difference in enchantment level.
* @param allowAdena
* @param allowAncientAdena
* @return L2ItemInstance : items in inventory
*/
public Collection<L2ItemInstance> getUniqueItemsByEnchantLevel(boolean allowAdena, boolean allowAncientAdena)
{
return getUniqueItemsByEnchantLevel(allowAdena, allowAncientAdena, true);
}
public Collection<L2ItemInstance> getUniqueItemsByEnchantLevel(boolean allowAdena, boolean allowAncientAdena, boolean onlyAvailable)
{
final Collection<L2ItemInstance> list = new LinkedList<>();
for (L2ItemInstance item : _items.values())
{
if (!allowAdena && (item.getId() == ADENA_ID))
{
continue;
}
if (!allowAncientAdena && (item.getId() == ANCIENT_ADENA_ID))
{
continue;
}
boolean isDuplicate = false;
for (L2ItemInstance litem : list)
{
if ((litem.getId() == item.getId()) && (litem.getEnchantLevel() == item.getEnchantLevel()))
{
isDuplicate = true;
break;
}
}
if (!isDuplicate && (!onlyAvailable || (item.isSellable() && item.isAvailable(getOwner(), false, false))))
{
list.add(item);
}
}
return list;
}
/**
* @param itemId
* @return

View File

@@ -20,6 +20,7 @@ import java.util.Collection;
import java.util.Objects;
import com.l2jmobius.gameserver.enums.AttributeType;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.ensoul.EnsoulOption;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.items.type.CrystalType;
@@ -44,8 +45,7 @@ public class L2WarehouseItem
private final int _locationSlot;
private final int _enchant;
private final CrystalType _grade;
private boolean _isAugmented;
private int _augmentationId;
private final Augmentation _augmentation;
private final int _customType1;
private final int _customType2;
private final int _mana;
@@ -81,15 +81,7 @@ public class L2WarehouseItem
_customType1 = item.getCustomType1();
_customType2 = item.getCustomType2();
_grade = item.getItem().getCrystalType();
if (item.isAugmented())
{
_isAugmented = true;
_augmentationId = item.getAugmentation().getId();
}
else
{
_isAugmented = false;
}
_augmentation = item.getAugmentation();
_mana = item.getMana();
_time = item.isTimeLimitedItem() ? (int) (item.getRemainingTime() / 1000) : -1;
@@ -232,20 +224,12 @@ public class L2WarehouseItem
return _item.getName();
}
/**
* @return {@code true} if the item is augmented, {@code false} otherwise.
*/
public boolean isAugmented()
{
return _isAugmented;
}
/**
* @return the augmentation If.
*/
public int getAugmentationId()
public Augmentation getAugmentation()
{
return _augmentationId;
return _augmentation;
}
/**

View File

@@ -42,6 +42,7 @@ import com.l2jmobius.gameserver.data.xml.impl.AppearanceItemData;
import com.l2jmobius.gameserver.data.xml.impl.EnchantItemOptionsData;
import com.l2jmobius.gameserver.data.xml.impl.EnsoulData;
import com.l2jmobius.gameserver.data.xml.impl.OptionData;
import com.l2jmobius.gameserver.datatables.AugmentationData;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.enums.AttributeType;
import com.l2jmobius.gameserver.enums.InstanceType;
@@ -53,8 +54,8 @@ import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.instancemanager.CastleManager;
import com.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager;
import com.l2jmobius.gameserver.instancemanager.SiegeGuardManager;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.DropProtection;
import com.l2jmobius.gameserver.model.L2Augmentation;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.L2WorldRegion;
@@ -135,7 +136,7 @@ public final class L2ItemInstance extends L2Object
private boolean _wear;
/** Augmented Item */
private L2Augmentation _augmentation = null;
private Augmentation _augmentation = null;
/** Shadow item */
private int _mana = -1;
@@ -948,7 +949,7 @@ public final class L2ItemInstance extends L2Object
* Returns the augmentation object for this item
* @return augmentation
*/
public L2Augmentation getAugmentation()
public Augmentation getAugmentation()
{
return _augmentation;
}
@@ -956,9 +957,10 @@ public final class L2ItemInstance extends L2Object
/**
* Sets a new augmentation
* @param augmentation
* @param updateDatabase
* @return return true if successfully
*/
public boolean setAugmentation(L2Augmentation augmentation)
public boolean setAugmentation(Augmentation augmentation, boolean updateDatabase)
{
// there shall be no previous augmentation..
if (_augmentation != null)
@@ -968,13 +970,9 @@ public final class L2ItemInstance extends L2Object
}
_augmentation = augmentation;
try (Connection con = DatabaseFactory.getInstance().getConnection())
if (updateDatabase)
{
updateItemAttributes(con);
}
catch (SQLException e)
{
LOGGER.log(Level.SEVERE, "Could not update atributes for item: " + this + " from DB:", e);
updateItemOptions();
}
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerAugment(getActingPlayer(), this, augmentation, true), getItem());
return true;
@@ -991,7 +989,7 @@ public final class L2ItemInstance extends L2Object
}
// Copy augmentation before removing it.
final L2Augmentation augment = _augmentation;
final Augmentation augment = _augmentation;
_augmentation = null;
try (Connection con = DatabaseFactory.getInstance().getConnection();
@@ -1023,7 +1021,7 @@ public final class L2ItemInstance extends L2Object
final int aug_attributes = rs.getInt(1);
if (aug_attributes != -1)
{
_augmentation = new L2Augmentation(rs.getInt("augAttributes"));
_augmentation = AugmentationData.getInstance().getAugmentation(rs.getInt("augAttributes"));
}
}
}
@@ -1048,7 +1046,19 @@ public final class L2ItemInstance extends L2Object
}
}
private void updateItemAttributes(Connection con)
public void updateItemOptions()
{
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
updateItemOptions(con);
}
catch (SQLException e)
{
LOGGER.log(Level.SEVERE, "Could not update atributes for item: " + toString() + " from DB:", e);
}
}
private void updateItemOptions(Connection con)
{
try (PreparedStatement ps = con.prepareStatement("REPLACE INTO item_attributes VALUES(?,?)"))
{
@@ -1062,6 +1072,18 @@ public final class L2ItemInstance extends L2Object
}
}
public void updateItemElementals()
{
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
updateItemElements(con);
}
catch (SQLException e)
{
LOGGER.log(Level.SEVERE, "Could not update elementals for item: " + toString() + " from DB: ", e);
}
}
private void updateItemElements(Connection con)
{
try (PreparedStatement ps = con.prepareStatement("DELETE FROM item_elementals WHERE itemId = ?"))
@@ -1187,17 +1209,14 @@ public final class L2ItemInstance extends L2Object
/**
* Add elemental attribute to item and save to db
* @param holder
* @param updateDatabase
*/
public void setAttribute(AttributeHolder holder)
public void setAttribute(AttributeHolder holder, boolean updateDatabase)
{
applyAttribute(holder);
try (Connection con = DatabaseFactory.getInstance().getConnection())
if (updateDatabase)
{
updateItemElements(con);
}
catch (SQLException e)
{
LOGGER.log(Level.SEVERE, "Could not update elementals for item: " + this + " from DB:", e);
updateItemElementals();
}
}
@@ -1646,12 +1665,16 @@ public final class L2ItemInstance extends L2Object
if (_augmentation != null)
{
updateItemAttributes(con);
updateItemOptions(con);
}
if (_elementals != null)
{
updateItemElements(con);
}
if ((_ensoulOptions != null) || (_ensoulSpecialOptions != null))
{
updateSpecialAbilities(con);
}
}
catch (Exception e)
{
@@ -2217,10 +2240,21 @@ public final class L2ItemInstance extends L2Object
}
}
private void updateSpecialAbilities()
public void updateSpecialAbilities()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO item_special_abilities (`objectId`, `type`, `optionId`, `position`) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE type = ?, optionId = ?, position = ?"))
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
updateSpecialAbilities(con);
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Couldn't update item special abilities", e);
}
}
private void updateSpecialAbilities(Connection con)
{
try (PreparedStatement ps = con.prepareStatement("INSERT INTO item_special_abilities (`objectId`, `type`, `optionId`, `position`) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE type = ?, optionId = ?, position = ?"))
{
ps.setInt(1, getObjectId());
for (Entry<Integer, EnsoulOption> entry : _ensoulOptions.entrySet())

View File

@@ -1,91 +0,0 @@
/*
* 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 com.l2jmobius.gameserver.model.multisell;
import java.util.ArrayList;
import java.util.List;
/**
* @author DS
*/
public class Entry
{
protected int _entryId;
protected boolean _stackable = true;
protected List<Ingredient> _products;
protected List<Ingredient> _ingredients;
public Entry(int entryId)
{
_entryId = entryId;
_products = new ArrayList<>();
_ingredients = new ArrayList<>();
}
/**
* This constructor used in PreparedEntry only, ArrayLists not created.
*/
protected Entry()
{
}
public final void setEntryId(int id)
{
_entryId = id;
}
public final int getEntryId()
{
return _entryId;
}
public final void addProduct(Ingredient product)
{
_products.add(product);
if (!product.isStackable())
{
_stackable = false;
}
}
public final List<Ingredient> getProducts()
{
return _products;
}
public final void addIngredient(Ingredient ingredient)
{
_ingredients.add(ingredient);
}
public final List<Ingredient> getIngredients()
{
return _ingredients;
}
public final boolean isStackable()
{
return _stackable;
}
public long getTaxAmount()
{
return 0;
}
}

View File

@@ -1,151 +0,0 @@
/*
* 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 com.l2jmobius.gameserver.model.multisell;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.items.L2Armor;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.items.L2Weapon;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
/**
* @author DS
*/
public class Ingredient
{
private int _itemId;
private long _itemCount;
private final int _enchantmentLevel;
private boolean _isTaxIngredient;
private boolean _maintainIngredient;
private L2Item _template = null;
private ItemInfo _itemInfo = null;
private final double _chance;
public Ingredient(StatsSet set)
{
this(set.getInt("id"), set.getLong("count"), set.getInt("enchantmentLevel", 0), set.getDouble("chance", 0), set.getBoolean("isTaxIngredient", false), set.getBoolean("maintainIngredient", false));
}
public Ingredient(int itemId, long itemCount, int enchantmentLevel, double chance, boolean isTaxIngredient, boolean maintainIngredient)
{
_itemId = itemId;
_itemCount = itemCount;
_enchantmentLevel = enchantmentLevel;
_chance = chance;
_isTaxIngredient = isTaxIngredient;
_maintainIngredient = maintainIngredient;
if (_itemId > 0)
{
_template = ItemTable.getInstance().getTemplate(_itemId);
}
}
/**
* @return a new Ingredient instance with the same values as this.
*/
public Ingredient getCopy()
{
return new Ingredient(_itemId, _itemCount, _enchantmentLevel, _chance, _isTaxIngredient, _maintainIngredient);
}
public final L2Item getTemplate()
{
return _template;
}
public final void setItemInfo(L2ItemInstance item)
{
_itemInfo = new ItemInfo(item);
}
public final void setItemInfo(ItemInfo info)
{
_itemInfo = info;
}
public final ItemInfo getItemInfo()
{
return _itemInfo;
}
public final int getEnchantLevel()
{
return _itemInfo == null ? _enchantmentLevel : _itemInfo.getEnchantLevel();
}
public final void setItemId(int itemId)
{
_itemId = itemId;
}
public final int getItemId()
{
return _itemId;
}
public final void setItemCount(long itemCount)
{
_itemCount = itemCount;
}
public final long getItemCount()
{
return _itemCount;
}
public double getChance()
{
return _chance;
}
public final void setIsTaxIngredient(boolean isTaxIngredient)
{
_isTaxIngredient = isTaxIngredient;
}
public final boolean isTaxIngredient()
{
return _isTaxIngredient;
}
public final void setMaintainIngredient(boolean maintainIngredient)
{
_maintainIngredient = maintainIngredient;
}
public final boolean getMaintainIngredient()
{
return _maintainIngredient;
}
public final boolean isStackable()
{
return (_template == null) || _template.isStackable();
}
public final boolean isArmorOrWeapon()
{
return (_template != null) && ((_template instanceof L2Armor) || (_template instanceof L2Weapon));
}
public final int getWeight()
{
return _template == null ? 0 : _template.getWeight();
}
}

View File

@@ -1,104 +0,0 @@
/*
* 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 com.l2jmobius.gameserver.model.multisell;
import java.util.Collection;
import com.l2jmobius.gameserver.model.ensoul.EnsoulOption;
import com.l2jmobius.gameserver.model.items.enchant.attribute.AttributeHolder;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.variables.ItemVariables;
/**
* @author DS
*/
public class ItemInfo
{
private final int _enchantLevel, _augmentId;
private final byte _elementId;
private final int _elementPower;
private final AttributeHolder[] _attributes;
private final int _visualId;
private final int _visualStoneId;
private final long _visualIdLifetime;
private final Collection<EnsoulOption> _specialAbilities;
private final Collection<EnsoulOption> _additionalSpecialAbilities;
public ItemInfo(L2ItemInstance item)
{
_enchantLevel = item.getEnchantLevel();
_augmentId = item.getAugmentation() != null ? item.getAugmentation().getId() : 0;
_elementId = item.getAttackAttributeType().getClientId();
_elementPower = item.getAttackAttributePower();
_attributes = item.getAttributes() != null ? item.getAttributes().toArray(new AttributeHolder[6]) : new AttributeHolder[6];
_visualId = item.getVisualId();
_visualStoneId = item.getVariables().getInt(ItemVariables.VISUAL_APPEARANCE_STONE_ID, 0);
_visualIdLifetime = item.getVisualLifeTime();
_specialAbilities = item.getSpecialAbilities();
_additionalSpecialAbilities = item.getAdditionalSpecialAbilities();
}
public final int getEnchantLevel()
{
return _enchantLevel;
}
public final int getAugmentId()
{
return _augmentId;
}
public final byte getElementId()
{
return _elementId;
}
public final int getElementPower()
{
return _elementPower;
}
public final AttributeHolder[] getElementals()
{
return _attributes;
}
public int getVisualId()
{
return _visualId;
}
public int getVisualStoneId()
{
return _visualStoneId;
}
public long getVisualIdLifeTime()
{
return _visualIdLifetime;
}
public Collection<EnsoulOption> getSpecialAbilities()
{
return _specialAbilities;
}
public Collection<EnsoulOption> getAdditionalSpecialAbilities()
{
return _additionalSpecialAbilities;
}
}

View File

@@ -1,123 +0,0 @@
/*
* 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 com.l2jmobius.gameserver.model.multisell;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author DS
*/
public class ListContainer
{
private final int _listId;
private boolean _isChanceMultisell;
private boolean _applyTaxes = false;
private boolean _maintainEnchantment = false;
private double _useRate = 1.0;
protected List<Entry> _entries = new ArrayList<>();
protected Set<Integer> _npcsAllowed = null;
public ListContainer(int listId)
{
_listId = listId;
}
public ListContainer(ListContainer container)
{
_listId = container.getListId();
_isChanceMultisell = container.isChanceMultisell();
_maintainEnchantment = container.getMaintainEnchantment();
}
public final List<Entry> getEntries()
{
return _entries;
}
public final int getListId()
{
return _listId;
}
public boolean isChanceMultisell()
{
return _isChanceMultisell;
}
public void setIsChanceMultisell(boolean val)
{
_isChanceMultisell = val;
}
public final void setApplyTaxes(boolean applyTaxes)
{
_applyTaxes = applyTaxes;
}
public final boolean getApplyTaxes()
{
return _applyTaxes;
}
public final void setMaintainEnchantment(boolean maintainEnchantment)
{
_maintainEnchantment = maintainEnchantment;
}
public double getUseRate()
{
return _useRate;
}
/**
* Set this to create multisell with increased products, all product counts will be multiplied by the rate specified.<br>
* <b>NOTE:</b> It affects only parser, it won't change values of already parsed multisell since MultiSells' parseEntry method handles this feature.
* @param rate
*/
public void setUseRate(double rate)
{
_useRate = rate;
}
public final boolean getMaintainEnchantment()
{
return _maintainEnchantment;
}
public void allowNpc(int npcId)
{
if (_npcsAllowed == null)
{
_npcsAllowed = new HashSet<>();
}
_npcsAllowed.add(npcId);
}
public boolean isNpcAllowed(int npcId)
{
return (_npcsAllowed == null) || _npcsAllowed.contains(npcId);
}
public boolean isNpcOnly()
{
return _npcsAllowed != null;
}
}

View File

@@ -1,107 +0,0 @@
/*
* 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 com.l2jmobius.gameserver.model.multisell;
import static com.l2jmobius.gameserver.model.itemcontainer.Inventory.ADENA_ID;
import java.util.ArrayList;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
/**
* @author DS
*/
public class PreparedEntry extends Entry
{
private long _taxAmount = 0;
public PreparedEntry(Entry template, L2ItemInstance item, boolean applyTaxes, boolean maintainEnchantment, double taxRate)
{
_entryId = template.getEntryId() * 100000;
if (maintainEnchantment && (item != null))
{
_entryId += item.getEnchantLevel();
}
ItemInfo info = null;
long adenaAmount = 0;
_ingredients = new ArrayList<>(template.getIngredients().size());
for (Ingredient ing : template.getIngredients())
{
if (ing.getItemId() == ADENA_ID)
{
// Tax ingredients added only if taxes enabled
if (ing.isTaxIngredient())
{
// if taxes are to be applied, modify/add the adena count based on the template adena/ancient adena count
if (applyTaxes)
{
_taxAmount += Math.round(ing.getItemCount() * taxRate);
}
}
else
{
adenaAmount += ing.getItemCount();
}
// do not yet add this adena amount to the list as non-taxIngredient adena might be entered later (order not guaranteed)
continue;
}
if (maintainEnchantment && (item != null) && ing.isArmorOrWeapon())
{
info = new ItemInfo(item);
final Ingredient newIngredient = ing.getCopy();
newIngredient.setItemInfo(info);
_ingredients.add(newIngredient);
}
else
{
_ingredients.add(ing.getCopy());
}
}
// now add the adena, if any.
adenaAmount += _taxAmount; // do not forget tax
if (adenaAmount > 0)
{
_ingredients.add(new Ingredient(ADENA_ID, adenaAmount, 0, 0, false, false));
}
// now copy products
_products = new ArrayList<>(template.getProducts().size());
for (Ingredient ing : template.getProducts())
{
if (!ing.isStackable())
{
_stackable = false;
}
final Ingredient newProduct = ing.getCopy();
if (maintainEnchantment && ing.isArmorOrWeapon())
{
newProduct.setItemInfo(info);
}
_products.add(newProduct);
}
}
@Override
public final long getTaxAmount()
{
return _taxAmount;
}
}

View File

@@ -1,104 +0,0 @@
/*
* 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 com.l2jmobius.gameserver.model.multisell;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.items.L2Armor;
import com.l2jmobius.gameserver.model.items.L2Weapon;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
public class PreparedListContainer extends ListContainer
{
private int _npcObjectId = 0;
public PreparedListContainer(ListContainer template, boolean inventoryOnly, L2PcInstance player, L2Npc npc)
{
super(template);
setMaintainEnchantment(template.getMaintainEnchantment());
setApplyTaxes(false);
double taxRate = 0;
if (npc != null)
{
_npcObjectId = npc.getObjectId();
if (template.getApplyTaxes() && npc.isInTown() && (npc.getCastle().getOwnerId() > 0))
{
setApplyTaxes(true);
taxRate = npc.getCastle().getTaxRate();
}
}
if (inventoryOnly)
{
if (player == null)
{
return;
}
final Collection<L2ItemInstance> items;
if (getMaintainEnchantment())
{
items = player.getInventory().getUniqueItemsByEnchantLevel(false, false, false);
}
else
{
items = player.getInventory().getUniqueItems(false, false, false);
}
_entries = new LinkedList<>();
for (L2ItemInstance item : items)
{
// only do the match up on equippable items that are not currently equipped
// so for each appropriate item, produce a set of entries for the multisell list.
if (!item.isEquipped() && ((item.getItem() instanceof L2Armor) || (item.getItem() instanceof L2Weapon)))
{
// loop through the entries to see which ones we wish to include
for (Entry ent : template.getEntries())
{
// check ingredients of this entry to see if it's an entry we'd like to include.
for (Ingredient ing : ent.getIngredients())
{
if (item.getId() == ing.getItemId())
{
_entries.add(new PreparedEntry(ent, item, getApplyTaxes(), getMaintainEnchantment(), taxRate));
break; // next entry
}
}
}
}
}
}
else
{
_entries = new ArrayList<>(template.getEntries().size());
for (Entry ent : template.getEntries())
{
_entries.add(new PreparedEntry(ent, null, getApplyTaxes(), false, taxRate));
}
}
}
public final boolean checkNpcObjectId(int npcObjectId)
{
return (_npcObjectId == 0) || (_npcObjectId == npcObjectId);
}
}

View File

@@ -32,12 +32,10 @@ import com.l2jmobius.gameserver.network.serverpackets.SkillCoolTime;
public class Options
{
private final int _id;
private final List<AbstractEffect> _effects = new ArrayList<>();
private SkillHolder _activeSkill = null;
private SkillHolder _passiveSkill = null;
private final List<OptionsSkillHolder> _activationSkills = new ArrayList<>();
private List<AbstractEffect> _effects = null;
private List<SkillHolder> _activeSkill = null;
private List<SkillHolder> _passiveSkill = null;
private List<OptionsSkillHolder> _activationSkills = null;
/**
* @param id
@@ -54,6 +52,10 @@ public class Options
public void addEffect(AbstractEffect effect)
{
if (_effects == null)
{
_effects = new ArrayList<>();
}
_effects.add(effect);
}
@@ -64,51 +66,62 @@ public class Options
public boolean hasEffects()
{
return !_effects.isEmpty();
return _effects != null;
}
public boolean hasActiveSkill()
public boolean hasActiveSkills()
{
return _activeSkill != null;
}
public SkillHolder getActiveSkill()
public List<SkillHolder> getActiveSkills()
{
return _activeSkill;
}
public void setActiveSkill(SkillHolder holder)
public void addActiveSkill(SkillHolder holder)
{
_activeSkill = holder;
if (_activeSkill == null)
{
_activeSkill = new ArrayList<>();
}
_activeSkill.add(holder);
}
public boolean hasPassiveSkill()
public boolean hasPassiveSkills()
{
return _passiveSkill != null;
}
public SkillHolder getPassiveSkill()
public List<SkillHolder> getPassiveSkills()
{
return _passiveSkill;
}
public void setPassiveSkill(SkillHolder holder)
public void addPassiveSkill(SkillHolder holder)
{
_passiveSkill = holder;
if (_passiveSkill == null)
{
_passiveSkill = new ArrayList<>();
}
_passiveSkill.add(holder);
}
public boolean hasActivationSkills()
{
return !_activationSkills.isEmpty();
return _activationSkills != null;
}
public boolean hasActivationSkills(OptionsSkillType type)
{
for (OptionsSkillHolder holder : _activationSkills)
if (_activationSkills != null)
{
if (holder.getSkillType() == type)
for (OptionsSkillHolder holder : _activationSkills)
{
return true;
if (holder.getSkillType() == type)
{
return true;
}
}
}
return false;
@@ -121,12 +134,15 @@ public class Options
public List<OptionsSkillHolder> getActivationsSkills(OptionsSkillType type)
{
final List<OptionsSkillHolder> temp = new ArrayList<>();
for (OptionsSkillHolder holder : _activationSkills)
List<OptionsSkillHolder> temp = new ArrayList<>();
if (_activationSkills != null)
{
if (holder.getSkillType() == type)
for (OptionsSkillHolder holder : _activationSkills)
{
temp.add(holder);
if (holder.getSkillType() == type)
{
temp.add(holder);
}
}
}
return temp;
@@ -134,6 +150,10 @@ public class Options
public void addActivationSkill(OptionsSkillHolder holder)
{
if (_activationSkills == null)
{
_activationSkills = new ArrayList<>();
}
_activationSkills.add(holder);
}
@@ -171,15 +191,21 @@ public class Options
player.getEffectList().add(info);
}
}
if (hasActiveSkill())
if (hasActiveSkills())
{
addSkill(player, getActiveSkill().getSkill());
player.sendDebugMessage("Adding active skill: " + getActiveSkill());
for (SkillHolder holder : getActiveSkills())
{
addSkill(player, holder.getSkill());
player.sendDebugMessage("Adding active skill: " + getActiveSkills());
}
}
if (hasPassiveSkill())
if (hasPassiveSkills())
{
addSkill(player, getPassiveSkill().getSkill());
player.sendDebugMessage("Adding passive skill: " + getPassiveSkill());
for (SkillHolder holder : getPassiveSkills())
{
addSkill(player, holder.getSkill());
player.sendDebugMessage("Adding passive skill: " + getPassiveSkills());
}
}
if (hasActivationSkills())
{
@@ -208,15 +234,21 @@ public class Options
}
}
}
if (hasActiveSkill())
if (hasActiveSkills())
{
player.removeSkill(getActiveSkill().getSkill(), false, false);
player.sendDebugMessage("Removing active skill: " + getActiveSkill());
for (SkillHolder holder : getActiveSkills())
{
player.removeSkill(holder.getSkill(), false, false);
player.sendDebugMessage("Removing active skill: " + getActiveSkills());
}
}
if (hasPassiveSkill())
if (hasPassiveSkills())
{
player.removeSkill(getPassiveSkill().getSkill(), false, true);
player.sendDebugMessage("Removing passive skill: " + getPassiveSkill());
for (SkillHolder holder : getPassiveSkills())
{
player.removeSkill(holder.getSkill(), false, true);
player.sendDebugMessage("Removing passive skill: " + getPassiveSkills());
}
}
if (hasActivationSkills())
{

View File

@@ -59,6 +59,7 @@ public class PlayerVariables extends AbstractVariables
public static final String EXTEND_DROP = "EXTEND_DROP";
public static final String FORTUNE_TELLING_VARIABLE = "FortuneTelling";
public static final String FORTUNE_TELLING_BLACK_CAT_VARIABLE = "FortuneTellingBlackCat";
public static final String DELUSION_RETURN = "DELUSION_RETURN";
private final int _objectId;

View File

@@ -37,7 +37,6 @@ public enum ZoneId
NO_SUMMON_FRIEND,
FORT,
NO_STORE,
TOWN,
SCRIPT,
HQ,
DANGER_AREA,
@@ -47,7 +46,8 @@ public enum ZoneId
NO_RESTART,
SAYUNE,
FISHING,
UNDYING;
UNDYING,
TAX;
public static int getZoneCount()
{

View File

@@ -1,85 +1,86 @@
/*
* 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 com.l2jmobius.gameserver.model.zone.type;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
/**
* A Town zone
* @author durgus
*/
public class L2TownZone extends L2ZoneType
{
private int _townId;
private int _taxById;
public L2TownZone(int id)
{
super(id);
_taxById = 0;
}
@Override
public void setParameter(String name, String value)
{
if (name.equals("townId"))
{
_townId = Integer.parseInt(value);
}
else if (name.equals("taxById"))
{
_taxById = Integer.parseInt(value);
}
else
{
super.setParameter(name, value);
}
}
@Override
protected void onEnter(L2Character character)
{
character.setInsideZone(ZoneId.TOWN, true);
}
@Override
protected void onExit(L2Character character)
{
character.setInsideZone(ZoneId.TOWN, false);
}
/**
* Returns this zones town id (if any)
* @return
*/
public int getTownId()
{
return _townId;
}
/**
* Returns this town zones castle id
* @return
*/
public final int getTaxById()
{
return _taxById;
}
}
/*
* 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 com.l2jmobius.gameserver.model.zone.type;
import com.l2jmobius.gameserver.instancemanager.CastleManager;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
/**
* Tax zone type.
* @author malyelfik
*/
public class L2TaxZone extends L2ZoneType
{
private int _domainId;
private Castle _castle;
public L2TaxZone(int id)
{
super(id);
}
@Override
public void setParameter(String name, String value)
{
if (name.equalsIgnoreCase("domainId"))
{
_domainId = Integer.parseInt(value);
}
else
{
super.setParameter(name, value);
}
}
@Override
protected void onEnter(L2Character character)
{
character.setInsideZone(ZoneId.TAX, true);
if (character.isNpc())
{
((L2Npc) character).setTaxZone(this);
}
}
@Override
protected void onExit(L2Character character)
{
character.setInsideZone(ZoneId.TAX, false);
if (character.isNpc())
{
((L2Npc) character).setTaxZone(null);
}
}
/**
* Gets castle associated with tax zone.<br>
* @return instance of {@link Castle} if found otherwise {@code null}
*/
public Castle getCastle()
{
// Lazy loading is used because zone is loaded before residence
if (_castle == null)
{
_castle = CastleManager.getInstance().getCastleById(_domainId);
}
return _castle;
}
}

View File

@@ -16,31 +16,39 @@
*/
package com.l2jmobius.gameserver.network.clientpackets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Map.Entry;
import java.util.OptionalLong;
import java.util.stream.Collectors;
import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.commons.util.CommonUtil;
import com.l2jmobius.gameserver.data.xml.impl.EnsoulData;
import com.l2jmobius.gameserver.data.xml.impl.MultisellData;
import com.l2jmobius.gameserver.model.L2Augmentation;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.enums.AttributeType;
import com.l2jmobius.gameserver.enums.SpecialItemType;
import com.l2jmobius.gameserver.model.ItemInfo;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.ensoul.EnsoulOption;
import com.l2jmobius.gameserver.model.holders.ItemChanceHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MultisellEntryHolder;
import com.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder;
import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
import com.l2jmobius.gameserver.model.itemcontainer.PcInventory;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.items.enchant.attribute.AttributeHolder;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.multisell.Entry;
import com.l2jmobius.gameserver.model.multisell.Ingredient;
import com.l2jmobius.gameserver.model.multisell.ItemInfo;
import com.l2jmobius.gameserver.model.multisell.PreparedListContainer;
import com.l2jmobius.gameserver.model.variables.ItemVariables;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.network.serverpackets.UserInfo;
/**
* The Class MultiSellChoose.
@@ -50,6 +58,19 @@ public class MultiSellChoose implements IClientIncomingPacket
private int _listId;
private int _entryId;
private long _amount;
private int _enchantLevel;
private int _augmentOption1;
private int _augmentOption2;
private short _attackAttribute;
private short _attributePower;
private short _fireDefence;
private short _waterDefence;
private short _windDefence;
private short _earthDefence;
private short _holyDefence;
private short _darkDefence;
private EnsoulOption[] _soulCrystalOptions;
private EnsoulOption[] _soulCrystalSpecialOptions;
@Override
public boolean read(L2GameClient client, PacketReader packet)
@@ -57,17 +78,29 @@ public class MultiSellChoose implements IClientIncomingPacket
_listId = packet.readD();
_entryId = packet.readD();
_amount = packet.readQ();
// _unk1 = packet.readH();
// _unk2 = packet.readD();
// _unk3 = packet.readD();
// _unk4 = packet.readH(); // elemental attributes
// _unk5 = packet.readH(); // elemental attributes
// _unk6 = packet.readH(); // elemental attributes
// _unk7 = packet.readH(); // elemental attributes
// _unk8 = packet.readH(); // elemental attributes
// _unk9 = packet.readH(); // elemental attributes
// _unk10 = packet.readH(); // elemental attributes
// _unk11 = packet.readH(); // elemental attributes
_enchantLevel = packet.readH();
_augmentOption1 = packet.readD();
_augmentOption2 = packet.readD();
_attackAttribute = (short) packet.readH();
_attributePower = (short) packet.readH();
_fireDefence = (short) packet.readH();
_waterDefence = (short) packet.readH();
_windDefence = (short) packet.readH();
_earthDefence = (short) packet.readH();
_holyDefence = (short) packet.readH();
_darkDefence = (short) packet.readH();
_soulCrystalOptions = new EnsoulOption[packet.readC()]; // Ensoul size
for (int i = 0; i < _soulCrystalOptions.length; i++)
{
final int ensoulId = packet.readD(); // Ensoul option id
_soulCrystalOptions[i] = EnsoulData.getInstance().getOption(ensoulId);
}
_soulCrystalSpecialOptions = new EnsoulOption[packet.readC()]; // Special ensoul size
for (int i = 0; i < _soulCrystalSpecialOptions.length; i++)
{
final int ensoulId = packet.readD(); // Special ensoul option id.
_soulCrystalSpecialOptions[i] = EnsoulData.getInstance().getOption(ensoulId);
}
return true;
}
@@ -86,411 +119,471 @@ public class MultiSellChoose implements IClientIncomingPacket
return;
}
if ((_amount < 1) || (_amount > 5000))
if ((_amount < 1) || (_amount > 999999)) // 999 999 is client max.
{
player.setMultiSell(null);
player.sendPacket(SystemMessageId.YOU_HAVE_EXCEEDED_THE_QUANTITY_THAT_CAN_BE_INPUTTED);
return;
}
final PreparedListContainer list = player.getMultiSell();
if ((list == null) || (list.getListId() != _listId))
PreparedMultisellListHolder list = player.getMultiSell();
if ((list == null) || (list.getId() != _listId))
{
player.setMultiSell(null);
return;
}
final L2Npc npc = player.getLastFolkNPC();
if (!list.isNpcAllowed(-1) && !isAllowedToUse(player, npc, list))
if (!isAllowedToUse(player, npc, list))
{
if (player.isGM())
{
player.sendMessage("Multisell " + _listId + " is restricted. Under current conditions cannot be used. Only GMs are allowed to use it.");
}
else
{
player.setMultiSell(null);
return;
}
}
if (((_soulCrystalOptions != null) && CommonUtil.contains(_soulCrystalOptions, null)) || ((_soulCrystalSpecialOptions != null) && CommonUtil.contains(_soulCrystalSpecialOptions, null)))
{
_log.severe("Character: " + player.getName() + " requested multisell entry with invalid soul crystal options. Multisell: " + _listId + " entry: " + _entryId);
player.setMultiSell(null);
return;
}
for (Entry entry : list.getEntries())
final MultisellEntryHolder entry = list.getEntries().get(_entryId - 1); // Entry Id begins from 1. We currently use entry IDs as index pointer.
if (entry == null)
{
if (entry.getEntryId() == _entryId)
_log.severe("Character: " + player.getName() + " requested inexistant prepared multisell entry. Multisell: " + _listId + " entry: " + _entryId);
player.setMultiSell(null);
return;
}
if (!entry.isStackable() && (_amount > 1))
{
_log.severe("Character: " + player.getName() + " is trying to set amount > 1 on non-stackable multisell. Id: " + _listId + " entry: " + _entryId);
player.setMultiSell(null);
return;
}
final ItemInfo itemEnchantment = list.getItemEnchantment(_entryId - 1); // Entry Id begins from 1. We currently use entry IDs as index pointer.
// Validate the requested item with its full stats.
//@formatter:off
if ((itemEnchantment != null) && ((_amount > 1)
|| (itemEnchantment.getEnchantLevel() != _enchantLevel)
|| (itemEnchantment.getAttackElementType() != _attackAttribute)
|| (itemEnchantment.getAttackElementPower() != _attributePower)
|| (itemEnchantment.getAttributeDefence(AttributeType.FIRE) != _fireDefence)
|| (itemEnchantment.getAttributeDefence(AttributeType.WATER) != _waterDefence)
|| (itemEnchantment.getAttributeDefence(AttributeType.WIND) != _windDefence)
|| (itemEnchantment.getAttributeDefence(AttributeType.EARTH) != _earthDefence)
|| (itemEnchantment.getAttributeDefence(AttributeType.HOLY) != _holyDefence)
|| (itemEnchantment.getAttributeDefence(AttributeType.DARK) != _darkDefence)
|| ((itemEnchantment.getAugmentation() == null) && ((_augmentOption1 != 0) || (_augmentOption2 != 0)))
|| ((itemEnchantment.getAugmentation() != null) && ((itemEnchantment.getAugmentation().getOptionId(0) != _augmentOption1) || (itemEnchantment.getAugmentation().getOptionId(1) != _augmentOption2)))
|| ((_soulCrystalOptions != null) && itemEnchantment.getSoulCrystalOptions().stream().anyMatch(e -> !CommonUtil.contains(_soulCrystalOptions, e)))
|| ((_soulCrystalOptions == null) && !itemEnchantment.getSoulCrystalOptions().isEmpty())
|| ((_soulCrystalSpecialOptions != null) && itemEnchantment.getSoulCrystalOptions().stream().anyMatch(e -> !CommonUtil.contains(_soulCrystalSpecialOptions, e)))
|| ((_soulCrystalSpecialOptions == null) && !itemEnchantment.getSoulCrystalSpecialOptions().isEmpty())
))
//@formatter:on
{
_log.severe("Character: " + player.getName() + " is trying to upgrade equippable item, but the stats doesn't match. Id: " + _listId + " entry: " + _entryId);
player.setMultiSell(null);
return;
}
final L2Clan clan = player.getClan();
final PcInventory inventory = player.getInventory();
try
{
int slots = 0;
int weight = 0;
for (ItemChanceHolder product : entry.getProducts())
{
if (!entry.isStackable() && (_amount > 1))
if (product.getId() < 0)
{
// Check if clan exists for clan reputation products.
if ((clan == null) && (SpecialItemType.CLAN_REPUTATION.getClientId() == product.getId()))
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_A_CLAN_MEMBER_AND_CANNOT_PERFORM_THIS_ACTION);
return;
}
continue;
}
final L2Item template = ItemTable.getInstance().getTemplate(product.getId());
if (template == null)
{
_log.severe("Character: " + player.getName() + " is trying to set amount > 1 on non-stackable multisell, id:" + _listId + ":" + _entryId);
player.setMultiSell(null);
return;
}
final PcInventory inv = player.getInventory();
final long totalCount = Math.multiplyExact(list.getProductCount(product), _amount);
int slots = 0;
int weight = 0;
for (Ingredient e : entry.getProducts())
if (!(totalCount >= 0) && (totalCount <= Integer.MAX_VALUE))
{
if (e.getItemId() < 0)
{
continue;
}
if (!e.isStackable())
{
slots += e.getItemCount() * _amount;
}
else if (player.getInventory().getItemByItemId(e.getItemId()) == null)
{
slots++;
}
weight += e.getItemCount() * _amount * e.getWeight();
player.sendPacket(SystemMessageId.YOU_HAVE_EXCEEDED_THE_QUANTITY_THAT_CAN_BE_INPUTTED);
return;
}
if (!inv.validateWeight(weight))
if (!template.isStackable() || (player.getInventory().getItemByItemId(product.getId()) == null))
{
slots++;
}
weight += totalCount * template.getWeight();
if (!inventory.validateWeight(weight))
{
player.sendPacket(SystemMessageId.YOU_HAVE_EXCEEDED_THE_WEIGHT_LIMIT);
return;
}
if (!inv.validateCapacity(slots))
if ((slots > 0) && !inventory.validateCapacity(slots))
{
player.sendPacket(SystemMessageId.YOUR_INVENTORY_IS_FULL);
return;
}
final ArrayList<Ingredient> ingredientsList = new ArrayList<>(entry.getIngredients().size());
// Generate a list of distinct ingredients and counts in order to check if the correct item-counts are possessed by the player
boolean newIng;
for (Ingredient e : entry.getIngredients())
// If this is a chance multisell, reset slots and weight because only one item should be seleted. We just need to check if conditions for every item is met.
if (list.isChanceMultisell())
{
newIng = true;
// at this point, the template has already been modified so that enchantments are properly included
// whenever they need to be applied. Uniqueness of items is thus judged by item id AND enchantment level
for (int i = ingredientsList.size(); --i >= 0;)
slots = 0;
weight = 0;
}
}
// Check for enchanted item if its present in the inventory.
if ((itemEnchantment != null) && (inventory.getItemByObjectId(itemEnchantment.getObjectId()) == null))
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_NEED_A_N_S1);
sm.addItemName(itemEnchantment.getItem().getId());
player.sendPacket(sm);
return;
}
// Summarize all item counts into one map. That would include non-stackable items under 1 id and multiple count.
final Map<Integer, Long> itemIdCount = entry.getIngredients().stream().collect(Collectors.toMap(i -> i.getId(), i -> list.getIngredientCount(i), (k1, k2) -> Math.addExact(k1, k2)));
// Now check if the player has sufficient items in the inventory to cover the ingredients' expences. Take care for non-stackable items like 2 swords to dual.
boolean allOk = true;
for (Entry<Integer, Long> idCount : itemIdCount.entrySet())
{
allOk &= checkIngredients(player, list, inventory, clan, idCount.getKey(), Math.multiplyExact(idCount.getValue(), _amount));
}
// The above operation should not be short-circuited, in order to show all missing ingredients.
if (!allOk)
{
return;
}
final InventoryUpdate iu = new InventoryUpdate();
boolean itemEnchantmentProcessed = (itemEnchantment == null);
// Take all ingredients
for (ItemHolder ingredient : entry.getIngredients())
{
final long totalCount = Math.multiplyExact(list.getIngredientCount(ingredient), _amount);
final SpecialItemType specialItem = SpecialItemType.getByClientId(ingredient.getId());
if (specialItem != null)
{
// Take special item.
switch (specialItem)
{
final Ingredient ex = ingredientsList.get(i);
// if the item was already added in the list, merely increment the count
// this happens if 1 list entry has the same ingredient twice (example 2 swords = 1 dual)
if ((ex.getItemId() == e.getItemId()) && (ex.getEnchantLevel() == e.getEnchantLevel()))
case CLAN_REPUTATION:
{
if ((ex.getItemCount() + e.getItemCount()) > Integer.MAX_VALUE)
if (clan != null)
{
player.sendPacket(SystemMessageId.YOU_HAVE_EXCEEDED_THE_QUANTITY_THAT_CAN_BE_INPUTTED);
return;
clan.takeReputationScore((int) totalCount, true);
SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.S1_POINT_S_HAVE_BEEN_DEDUCTED_FROM_THE_CLAN_S_REPUTATION);
smsg.addLong(totalCount);
player.sendPacket(smsg);
}
// two same ingredients, merge into one and replace old
final Ingredient ing = ex.getCopy();
ing.setItemCount(ex.getItemCount() + e.getItemCount());
ingredientsList.set(i, ing);
newIng = false;
break;
}
}
if (newIng)
{
// if it's a new ingredient, just store its info directly (item id, count, enchantment)
ingredientsList.add(e);
case FAME:
{
player.setFame(player.getFame() - (int) totalCount);
player.sendPacket(new UserInfo(player));
// player.sendPacket(new ExBrExtraUserInfo(player));
break;
}
case RAIDBOSS_POINTS:
{
player.setRaidbossPoints(player.getRaidbossPoints() - (int) totalCount);
player.sendPacket(new UserInfo(player));
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_CONSUMED_S1_RAID_POINTS).addLong(totalCount));
break;
}
case PC_CAFE_POINTS:
{
player.setPcCafePoints((int) (player.getPcCafePoints() - totalCount));
break;
}
default:
{
_log.severe("Character: " + player.getName() + " has suffered possible item loss by using multisell " + _listId + " which has non-implemented special ingredient with id: " + ingredient.getId() + ".");
return;
}
}
}
// now check if the player has sufficient items in the inventory to cover the ingredient expenses
for (Ingredient e : ingredientsList)
else if (!itemEnchantmentProcessed && (itemEnchantment != null) && (itemEnchantment.getItem().getId() == ingredient.getId()))
{
if ((e.getItemCount() * _amount) > Integer.MAX_VALUE)
// Take the enchanted item.
final L2ItemInstance destroyedItem = inventory.destroyItem("Multisell", itemEnchantment.getObjectId(), totalCount, player, npc);
if (destroyedItem != null)
{
player.sendPacket(SystemMessageId.YOU_HAVE_EXCEEDED_THE_QUANTITY_THAT_CAN_BE_INPUTTED);
itemEnchantmentProcessed = true;
iu.addItem(destroyedItem);
}
else
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_NEED_A_N_S1);
sm.addItemName(ingredient.getId());
player.sendPacket(sm);
return;
}
if (e.getItemId() < 0)
}
else
{
// Take a regular item.
final L2ItemInstance destroyedItem = inventory.destroyItemByItemId("Multisell", ingredient.getId(), totalCount, player, npc);
if (destroyedItem != null)
{
if (!MultisellData.hasSpecialIngredient(e.getItemId(), e.getItemCount() * _amount, player))
{
return;
}
iu.addItem(destroyedItem);
}
else
{
// if this is not a list that maintains enchantment, check the count of all items that have the given id.
// otherwise, check only the count of items with exactly the needed enchantment level
final long required = (Config.ALT_BLACKSMITH_USE_RECIPES || !e.getMaintainIngredient()) ? (e.getItemCount() * _amount) : e.getItemCount();
if (inv.getInventoryItemCount(e.getItemId(), (list.getMaintainEnchantment() || (e.getEnchantLevel() > 0)) ? e.getEnchantLevel() : -1, false) < required)
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_NEED_S2_S1_S);
sm.addItemName(ingredient.getId());
sm.addLong(totalCount);
player.sendPacket(sm);
return;
}
}
}
// Generate the appropriate items
List<ItemChanceHolder> products = entry.getProducts();
if (list.isChanceMultisell())
{
final ItemChanceHolder randomProduct = ItemChanceHolder.getRandomHolder(entry.getProducts());
products = randomProduct != null ? Collections.singletonList(randomProduct) : Collections.emptyList();
}
for (ItemChanceHolder product : products)
{
final long totalCount = Math.multiplyExact(list.getProductCount(product), _amount);
final SpecialItemType specialItem = SpecialItemType.getByClientId(product.getId());
if (specialItem != null)
{
// Give special item.
switch (specialItem)
{
case CLAN_REPUTATION:
{
if (e.getEnchantLevel() > 0)
if (clan != null)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_NEED_S2_S1_S);
sm.addString("+" + e.getEnchantLevel() + " " + e.getTemplate().getName());
sm.addLong(required);
player.sendPacket(sm);
}
else
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_NEED_S2_S1_S);
sm.addItemName(e.getTemplate());
sm.addLong(required);
player.sendPacket(sm);
clan.addReputationScore((int) totalCount, true);
}
break;
}
case FAME:
{
player.setFame((int) (player.getFame() + totalCount));
player.sendPacket(new UserInfo(player));
// player.sendPacket(new ExBrExtraUserInfo(player));
break;
}
case RAIDBOSS_POINTS:
{
player.increaseRaidbossPoints((int) totalCount);
player.sendPacket(new UserInfo(player));
break;
}
default:
{
_log.severe("Character: " + player.getName() + " has suffered possible item loss by using multisell " + _listId + " which has non-implemented special product with id: " + product.getId() + ".");
return;
}
}
}
final Map<Integer, ItemInfo> originalInfos = new LinkedHashMap<>();
/** All ok, remove items and add final product */
for (Ingredient e : entry.getIngredients())
else
{
if (e.getItemId() < 0)
// Give item.
final L2ItemInstance addedItem = inventory.addItem("Multisell", product.getId(), totalCount, player, npc);
iu.addItem(addedItem);
// Check if the newly given item should be enchanted.
if (itemEnchantmentProcessed && list.isMaintainEnchantment() && (itemEnchantment != null) && addedItem.isEquipable() && addedItem.getItem().getClass().equals(itemEnchantment.getItem().getClass()))
{
if (!MultisellData.takeSpecialIngredient(e.getItemId(), e.getItemCount() * _amount, player))
addedItem.setEnchantLevel(itemEnchantment.getEnchantLevel());
addedItem.setAugmentation(itemEnchantment.getAugmentation(), false);
addedItem.setAttribute(new AttributeHolder(AttributeType.findByClientId(itemEnchantment.getAttackElementType()), itemEnchantment.getAttackElementPower()), false);
addedItem.setAttribute(new AttributeHolder(AttributeType.FIRE, itemEnchantment.getAttributeDefence(AttributeType.FIRE)), false);
addedItem.setAttribute(new AttributeHolder(AttributeType.WATER, itemEnchantment.getAttributeDefence(AttributeType.WATER)), false);
addedItem.setAttribute(new AttributeHolder(AttributeType.WIND, itemEnchantment.getAttributeDefence(AttributeType.WIND)), false);
addedItem.setAttribute(new AttributeHolder(AttributeType.EARTH, itemEnchantment.getAttributeDefence(AttributeType.EARTH)), false);
addedItem.setAttribute(new AttributeHolder(AttributeType.HOLY, itemEnchantment.getAttributeDefence(AttributeType.HOLY)), false);
addedItem.setAttribute(new AttributeHolder(AttributeType.DARK, itemEnchantment.getAttributeDefence(AttributeType.DARK)), false);
if (_soulCrystalOptions != null)
{
return;
}
}
else
{
L2ItemInstance itemToTake = inv.getItemByItemId(e.getItemId()); // initialize and initial guess for the item to take.
if (itemToTake == null)
{ // this is a cheat, transaction will be aborted and if any items already taken will not be returned back to inventory!
_log.severe("Character: " + player.getName() + " is trying to cheat in multisell, id:" + _listId + ":" + _entryId);
player.setMultiSell(null);
return;
}
// if (itemToTake.isEquipped())
// {
// this is a cheat, transaction will be aborted and if any items already taken will not be returned back to inventory!
// LOGGER.severe("Character: " + player.getName() + " is trying to cheat in multisell, exchanging equipped item, merchatnt id:" + merchant.getNpcId());
// player.setMultiSell(null);
// return;
// }
if (Config.ALT_BLACKSMITH_USE_RECIPES || !e.getMaintainIngredient())
{
// if it's a stackable item, just reduce the amount from the first (only) instance that is found in the inventory
if (itemToTake.isStackable())
for (int i = 0; i < _soulCrystalOptions.length; i++)
{
if (!player.destroyItem("Multisell", itemToTake.getObjectId(), e.getItemCount() * _amount, player.getTarget(), true))
{
player.setMultiSell(null);
return;
}
}
else
{
// for non-stackable items, one of two scenaria are possible:
// a) list maintains enchantment: get the instances that exactly match the requested enchantment level
// b) list does not maintain enchantment: get the instances with the LOWEST enchantment level
// a) if enchantment is maintained, then get a list of items that exactly match this enchantment
if (list.getMaintainEnchantment() || (e.getEnchantLevel() > 0))
{
// loop through this list and remove (one by one) each item until the required amount is taken.
final L2ItemInstance[] inventoryContents = inv.getAllItemsByItemId(e.getItemId(), e.getEnchantLevel(), false).toArray(new L2ItemInstance[0]);
for (int i = 0; i < (e.getItemCount() * _amount); i++)
{
originalInfos.put(i, new ItemInfo(inventoryContents[i]));
if (!player.destroyItem("Multisell", inventoryContents[i].getObjectId(), 1, player.getTarget(), true))
{
player.setMultiSell(null);
return;
}
}
}
else
// b) enchantment is not maintained. Get the instances with the LOWEST enchantment level
{
// NOTE: There are 2 ways to achieve the above goal.
// 1) Get all items that have the correct itemId, loop through them until the lowest enchantment
// level is found. Repeat all this for the next item until proper count of items is reached.
// 2) Get all items that have the correct itemId, sort them once based on enchantment level,
// and get the range of items that is necessary.
// Method 1 is faster for a small number of items to be exchanged.
// Method 2 is faster for large amounts.
//
// EXPLANATION:
// Worst case scenario for algorithm 1 will make it run in a number of cycles given by:
// m*(2n-m+1)/2 where m is the number of items to be exchanged and n is the total
// number of inventory items that have a matching id.
// With algorithm 2 (sort), sorting takes n*log(n) time and the choice is done in a single cycle
// for case b (just grab the m first items) or in linear time for case a (find the beginning of items
// with correct enchantment, index x, and take all items from x to x+m).
// Basically, whenever m > log(n) we have: m*(2n-m+1)/2 = (2nm-m*m+m)/2 >
// (2nlogn-logn*logn+logn)/2 = nlog(n) - log(n*n) + log(n) = nlog(n) + log(n/n*n) =
// nlog(n) + log(1/n) = nlog(n) - log(n) = (n-1)log(n)
// So for m < log(n) then m*(2n-m+1)/2 > (n-1)log(n) and m*(2n-m+1)/2 > nlog(n)
//
// IDEALLY:
// In order to best optimize the performance, choose which algorithm to run, based on whether 2^m > n
// if ( (2<<(e.getItemCount()// _amount)) < inventoryContents.length )
// // do Algorithm 1, no sorting
// else
// // do Algorithm 2, sorting
//
// CURRENT IMPLEMENTATION:
// In general, it is going to be very rare for a person to do a massive exchange of non-stackable items
// For this reason, we assume that algorithm 1 will always suffice and we keep things simple.
// If, in the future, it becomes necessary that we optimize, the above discussion should make it clear
// what optimization exactly is necessary (based on the comments under "IDEALLY").
//
// choice 1. Small number of items exchanged. No sorting.
for (int i = 1; i <= (e.getItemCount() * _amount); i++)
{
final Collection<L2ItemInstance> inventoryContents = inv.getAllItemsByItemId(e.getItemId(), false);
itemToTake = inventoryContents.iterator().next();
// get item with the LOWEST enchantment level from the inventory...
// +0 is lowest by default...
if (itemToTake.getEnchantLevel() > 0)
{
for (L2ItemInstance item : inventoryContents)
{
if ((item.getEnchantLevel() < itemToTake.getEnchantLevel()) && (item.getEnchantLevel() >= e.getEnchantLevel()))
{
itemToTake = item;
// nothing will have enchantment less than 0. If a zero-enchanted
// item is found, just take it
if (itemToTake.getEnchantLevel() == 0)
{
break;
}
}
}
}
if (!player.destroyItem("Multisell", itemToTake.getObjectId(), 1, player.getTarget(), true))
{
player.setMultiSell(null);
return;
}
}
}
addedItem.addSpecialAbility(_soulCrystalOptions[i], i + 1, 1, false);
}
}
}
}
final double itemRandom = 100 * Rnd.nextDouble();
float cumulativeChance = 0;
boolean matched = false;
// Generate the appropriate items
for (Ingredient e : entry.getProducts())
{
if (list.isChanceMultisell())
{
// Skip first entry.
if (e.getChance() < 1)
if (_soulCrystalSpecialOptions != null)
{
continue;
for (int i = 0; i < _soulCrystalSpecialOptions.length; i++)
{
addedItem.addSpecialAbility(_soulCrystalSpecialOptions[i], i + 1, 2, false);
}
}
// Calculate chance
matched = itemRandom < (cumulativeChance += e.getChance());
if (!matched)
{
continue;
}
addedItem.updateDatabase();
// Mark that we have already upgraded the item.
itemEnchantmentProcessed = false;
}
if (e.getItemId() < 0)
if (addedItem.getCount() > 1)
{
MultisellData.giveSpecialProduct(e.getItemId(), e.getItemCount() * _amount, player);
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
sm.addItemName(addedItem.getId());
sm.addLong(totalCount);
player.sendPacket(sm);
}
else if (addedItem.getEnchantLevel() > 0)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.ACQUIRED_S1_S2);
sm.addLong(addedItem.getEnchantLevel());
sm.addItemName(addedItem.getId());
player.sendPacket(sm);
}
else
{
if (e.isStackable())
{
inv.addItem("Multisell", e.getItemId(), e.getItemCount() * _amount, player, player.getTarget());
}
else
{
L2ItemInstance product = null;
for (int i = 0; i < (e.getItemCount() * _amount); i++)
{
product = inv.addItem("Multisell", e.getItemId(), 1, player, player.getTarget());
if ((product != null) && (list.getMaintainEnchantment() || (e.getEnchantLevel() > 0)))
{
final ItemInfo info = originalInfos.get(i);
if (info != null)
{
if (info.getAugmentId() > 0)
{
product.setAugmentation(new L2Augmentation(info.getAugmentId()));
}
if (info.getElementals().length > 0)
{
Arrays.stream(info.getElementals()).filter(Objects::nonNull).forEach(product::setAttribute);
}
if (info.getVisualId() > 0)
{
product.setVisualId(info.getVisualId());
if (info.getVisualStoneId() > 0)
{
product.getVariables().set(ItemVariables.VISUAL_APPEARANCE_STONE_ID, info.getVisualStoneId());
}
if (info.getVisualIdLifeTime() > 0)
{
product.getVariables().set(ItemVariables.VISUAL_APPEARANCE_LIFE_TIME, info.getVisualIdLifeTime());
product.scheduleVisualLifeTime();
}
}
if (!info.getSpecialAbilities().isEmpty())
{
int position = 0;
for (EnsoulOption option : info.getSpecialAbilities())
{
product.addSpecialAbility(option, position++, 1, true);
}
}
if (!info.getAdditionalSpecialAbilities().isEmpty())
{
int position = 0;
for (EnsoulOption option : info.getAdditionalSpecialAbilities())
{
product.addSpecialAbility(option, position++, 2, true);
}
}
}
product.setEnchantLevel(e.getEnchantLevel());
product.updateDatabase();
}
}
}
final SystemMessage sm;
if ((e.getItemCount() * _amount) > 1)
{
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
sm.addItemName(e.getItemId());
sm.addLong(e.getItemCount() * _amount);
player.sendPacket(sm);
}
else
{
if (list.getMaintainEnchantment() && (e.getEnchantLevel() > 0))
{
sm = SystemMessage.getSystemMessage(SystemMessageId.ACQUIRED_S1_S2);
sm.addLong(e.getEnchantLevel());
sm.addItemName(e.getItemId());
}
else
{
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
sm.addItemName(e.getItemId());
}
player.sendPacket(sm);
}
}
if (matched)
{
break;
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
sm.addItemName(addedItem);
player.sendPacket(sm);
}
}
player.sendItemList(false);
// finally, give the tax to the castle...
if ((npc != null) && (entry.getTaxAmount() > 0))
}
// Update inventory and weight.
player.sendInventoryUpdate(iu);
// finally, give the tax to the castle...
if ((npc != null) && list.isApplyTaxes())
{
final OptionalLong taxPaid = entry.getIngredients().stream().filter(i -> i.getId() == Inventory.ADENA_ID).mapToLong(i -> Math.round(i.getCount() * list.getIngredientMultiplier() * list.getTaxRate()) * _amount).reduce(Math::multiplyExact);
if (taxPaid.isPresent())
{
npc.getCastle().addToTreasury(entry.getTaxAmount() * _amount);
npc.handleTaxPayment(taxPaid.getAsLong());
}
break;
}
}
catch (ArithmeticException ae)
{
player.sendPacket(SystemMessageId.YOU_HAVE_EXCEEDED_THE_QUANTITY_THAT_CAN_BE_INPUTTED);
return;
}
// Re-send multisell after successful exchange of inventory-only shown items.
if (list.isInventoryOnly())
{
MultisellData.getInstance().separateAndSend(list.getId(), player, npc, list.isInventoryOnly(), list.getProductMultiplier(), list.getIngredientMultiplier());
}
}
/**
* @param player
* @param list
* @param inventory
* @param clan
* @param ingredientId
* @param totalCount
* @return {@code false} if ingredient amount is not enough, {@code true} otherwise.
*/
private boolean checkIngredients(final L2PcInstance player, PreparedMultisellListHolder list, final PcInventory inventory, final L2Clan clan, final int ingredientId, final long totalCount)
{
final SpecialItemType specialItem = SpecialItemType.getByClientId(ingredientId);
if (specialItem != null)
{
// Check special item.
switch (specialItem)
{
case CLAN_REPUTATION:
{
if (clan == null)
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_A_CLAN_MEMBER_AND_CANNOT_PERFORM_THIS_ACTION);
return false;
}
else if (!player.isClanLeader())
{
player.sendPacket(SystemMessageId.ONLY_THE_CLAN_LEADER_IS_ENABLED);
return false;
}
else if (clan.getReputationScore() < totalCount)
{
player.sendPacket(SystemMessageId.THE_CLAN_REPUTATION_IS_TOO_LOW);
return false;
}
return true;
}
case FAME:
{
if (player.getFame() < totalCount)
{
player.sendPacket(SystemMessageId.YOU_DON_T_HAVE_ENOUGH_FAME_TO_DO_THAT);
return false;
}
return true;
}
case RAIDBOSS_POINTS:
{
if (player.getRaidbossPoints() < totalCount)
{
player.sendPacket(SystemMessageId.NOT_ENOUGH_RAID_POINTS);
return false;
}
return true;
}
case PC_CAFE_POINTS:
{
if (player.getPcCafePoints() < totalCount)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_SHORT_OF_PC_POINTS));
return false;
}
return true;
}
default:
{
_log.severe("Multisell: " + _listId + " is using a non-implemented special ingredient with id: " + ingredientId + ".");
return false;
}
}
}
// Check if the necessary items are there. If list maintains enchantment, allow all enchanted items, otherwise only unenchanted. TODO: Check how retail does it.
else if (inventory.getInventoryItemCount(ingredientId, list.isMaintainEnchantment() ? -1 : 0, false) < totalCount)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_NEED_S2_S1_S);
sm.addItemName(ingredientId);
sm.addLong(totalCount);
player.sendPacket(sm);
return false;
}
return true;
}
/**
@@ -499,7 +592,7 @@ public class MultiSellChoose implements IClientIncomingPacket
* @param list
* @return {@code true} if player can buy stuff from the multisell, {@code false} otherwise.
*/
private boolean isAllowedToUse(L2PcInstance player, L2Npc npc, PreparedListContainer list)
private boolean isAllowedToUse(L2PcInstance player, L2Npc npc, PreparedMultisellListHolder list)
{
if (npc != null)
{
@@ -507,7 +600,7 @@ public class MultiSellChoose implements IClientIncomingPacket
{
return false;
}
else if (list.isNpcOnly() && ((npc.getInstanceWorld() != player.getInstanceWorld()) || !player.isInsideRadius(npc, L2Npc.INTERACTION_DISTANCE, true, false)))
else if (list.isNpcOnly() && (!list.checkNpcObjectId(npc.getObjectId()) || (npc.getInstanceWorld() != player.getInstanceWorld()) || !player.isInsideRadius(npc, L2Npc.INTERACTION_DISTANCE, true, false)))
{
return false;
}
@@ -518,4 +611,4 @@ public class MultiSellChoose implements IClientIncomingPacket
}
return true;
}
}
}

View File

@@ -29,8 +29,8 @@ import com.l2jmobius.gameserver.enums.TaxType;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.instance.L2MerchantInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.buylist.L2BuyList;
import com.l2jmobius.gameserver.model.buylist.Product;
import com.l2jmobius.gameserver.model.buylist.ProductList;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
@@ -110,7 +110,7 @@ public final class RequestBuyItem implements IClientIncomingPacket
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
merchant = (L2MerchantInstance) target;
merchant = (L2MerchantInstance) target; // FIXME: Doesn't work for GMs.
}
if ((merchant == null) && !player.isGM() && (_listId != CUSTOM_CB_SELL_LIST))
@@ -119,7 +119,7 @@ public final class RequestBuyItem implements IClientIncomingPacket
return;
}
final L2BuyList buyList = BuyListData.getInstance().getBuyList(_listId);
final ProductList buyList = BuyListData.getInstance().getBuyList(_listId);
if (buyList == null)
{
Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false BuyList list_id " + _listId, Config.DEFAULT_PUNISH);
@@ -134,7 +134,7 @@ public final class RequestBuyItem implements IClientIncomingPacket
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
castleTaxRate = merchant.getTotalTaxRate(TaxType.BUY);
castleTaxRate = merchant.getCastleTaxRate(TaxType.BUY);
}
long subTotal = 0;
@@ -159,11 +159,6 @@ public final class RequestBuyItem implements IClientIncomingPacket
}
long price = product.getPrice();
if ((product.getItemId() >= 3960) && (product.getItemId() <= 4026))
{
price *= Config.RATE_SIEGE_GUARDS_PRICE;
}
if (price < 0)
{
_log.warning("ERROR, no price found .. wrong buylist ??");
@@ -194,7 +189,7 @@ public final class RequestBuyItem implements IClientIncomingPacket
return;
}
// first calculate price per item with tax, then multiply by count
price = (long) (price * (1 + castleTaxRate));
price = (long) (price * (1 + castleTaxRate + product.getBaseTaxRate()));
subTotal += i.getCount() * price;
if (subTotal > MAX_ADENA)
{
@@ -257,7 +252,7 @@ public final class RequestBuyItem implements IClientIncomingPacket
// add to castle treasury
if (merchant != null)
{
merchant.getCastle().addToTreasury((long) (subTotal * castleTaxRate));
merchant.handleTaxPayment((long) (subTotal * castleTaxRate));
}
client.sendPacket(new ExUserInfoInvenWeight(player));

View File

@@ -202,6 +202,7 @@ public class RequestExEnchantItemAttribute implements IClientIncomingPacket
}
}
item.updateItemElementals();
player.destroyItem("AttrEnchant", stone, usedStones, player, true);
final AttributeHolder newElement = item.getAttribute(elementToAdd);
final int newValue = newElement != null ? newElement.getValue() : 0;
@@ -350,7 +351,7 @@ public class RequestExEnchantItemAttribute implements IClientIncomingPacket
if (success)
{
item.setAttribute(new AttributeHolder(elementToAdd, newPower));
item.setAttribute(new AttributeHolder(elementToAdd, newPower), false);
}
return success ? 1 : 0;

View File

@@ -29,7 +29,7 @@ import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2MerchantInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.buylist.L2BuyList;
import com.l2jmobius.gameserver.model.buylist.ProductList;
import com.l2jmobius.gameserver.model.buylist.Product;
import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
import com.l2jmobius.gameserver.model.items.L2Armor;
@@ -157,7 +157,7 @@ public final class RequestPreviewItem implements IClientIncomingPacket
return;
}
final L2BuyList buyList = BuyListData.getInstance().getBuyList(_listId);
final ProductList buyList = BuyListData.getInstance().getBuyList(_listId);
if (buyList == null)
{
Util.handleIllegalPlayerAction(activeChar, "Warning!! Character " + activeChar.getName() + " of account " + activeChar.getAccountName() + " sent a false BuyList list_id " + _listId, Config.DEFAULT_PUNISH);

View File

@@ -18,7 +18,7 @@ package com.l2jmobius.gameserver.network.clientpackets;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.datatables.AugmentationData;
import com.l2jmobius.gameserver.model.L2Augmentation;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.L2GameClient;
@@ -118,12 +118,10 @@ public final class RequestRefine extends AbstractRefinePacket
return;
}
final L2Augmentation aug = AugmentationData.getInstance().generateRandomAugmentation(lifeStoneLevel, lifeStoneGrade, targetItem.getItem().getBodyPart(), refinerItem.getId(), targetItem);
targetItem.setAugmentation(aug);
final Augmentation aug = AugmentationData.getInstance().generateRandomAugmentation(lifeStoneLevel, lifeStoneGrade, targetItem.getItem().getBodyPart(), refinerItem.getId(), targetItem);
targetItem.setAugmentation(aug, true);
final int stat12 = 0x0000FFFF & aug.getId();
final int stat34 = aug.getId() >> 16;
activeChar.sendPacket(new ExVariationResult(stat12, stat34, 1));
activeChar.sendPacket(new ExVariationResult(aug.getOptionId(0), aug.getOptionId(1), 1));
final InventoryUpdate iu = new InventoryUpdate();
iu.addModifiedItem(targetItem);

View File

@@ -21,11 +21,10 @@ import static com.l2jmobius.gameserver.model.actor.L2Npc.INTERACTION_DISTANCE;
import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.data.xml.impl.BuyListData;
import com.l2jmobius.gameserver.enums.TaxType;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.instance.L2MerchantInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.buylist.L2BuyList;
import com.l2jmobius.gameserver.model.buylist.ProductList;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.L2GameClient;
@@ -79,13 +78,7 @@ public final class RequestRefundItem implements IClientIncomingPacket
return;
}
if (_items == null)
{
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (!player.hasRefund())
if ((_items == null) || !player.hasRefund())
{
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
@@ -109,7 +102,7 @@ public final class RequestRefundItem implements IClientIncomingPacket
return;
}
final L2BuyList buyList = BuyListData.getInstance().getBuyList(_listId);
final ProductList buyList = BuyListData.getInstance().getBuyList(_listId);
if (buyList == null)
{
Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false BuyList list_id " + _listId, Config.DEFAULT_PUNISH);
@@ -164,12 +157,7 @@ public final class RequestRefundItem implements IClientIncomingPacket
final long count = item.getCount();
weight += count * template.getWeight();
long price = item.getReferencePrice() / 2;
if (merchant != null)
{
price -= (price * merchant.getTotalTaxRate(TaxType.SELL));
}
adena += price * count;
adena += (count * template.getReferencePrice()) / 2;
if (!template.isStackable())
{
slots += count;
@@ -213,6 +201,6 @@ public final class RequestRefundItem implements IClientIncomingPacket
// Update current load status on player
client.sendPacket(new ExUserInfoInvenWeight(player));
client.sendPacket(new ExBuySellList(player, true, merchant != null ? merchant.getTotalTaxRate(TaxType.SELL) : 0));
client.sendPacket(new ExBuySellList(player, true));
}
}

View File

@@ -29,7 +29,7 @@ import com.l2jmobius.gameserver.enums.TaxType;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.instance.L2MerchantInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.buylist.L2BuyList;
import com.l2jmobius.gameserver.model.buylist.ProductList;
import com.l2jmobius.gameserver.model.holders.UniqueItemHolder;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.L2GameClient;
@@ -129,7 +129,7 @@ public final class RequestSellItem implements IClientIncomingPacket
return;
}
final L2BuyList buyList = BuyListData.getInstance().getBuyList(_listId);
final ProductList buyList = BuyListData.getInstance().getBuyList(_listId);
if (buyList == null)
{
Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false BuyList list_id " + _listId, Config.DEFAULT_PUNISH);
@@ -153,10 +153,6 @@ public final class RequestSellItem implements IClientIncomingPacket
}
long price = item.getReferencePrice() / 2;
if (merchant != null)
{
price -= (price * merchant.getTotalTaxRate(TaxType.SELL));
}
totalPrice += price * i.getCount();
if (((MAX_ADENA / i.getCount()) < price) || (totalPrice > MAX_ADENA))
{
@@ -166,25 +162,27 @@ public final class RequestSellItem implements IClientIncomingPacket
if (Config.ALLOW_REFUND)
{
item = player.getInventory().transferItem("Sell", i.getObjectId(), i.getCount(), player.getRefund(), player, merchant);
player.getInventory().transferItem("Sell", i.getObjectId(), i.getCount(), player.getRefund(), player, merchant);
}
else
{
item = player.getInventory().destroyItem("Sell", i.getObjectId(), i.getCount(), player, merchant);
player.getInventory().destroyItem("Sell", i.getObjectId(), i.getCount(), player, merchant);
}
}
// add to castle treasury
if (merchant != null)
{
// Keep here same formula as in {@link ExBuySellList} to produce same result.
final long profit = (long) (totalPrice * (1.0 - merchant.getCastleTaxRate(TaxType.SELL)));
merchant.handleTaxPayment(totalPrice - profit);
totalPrice = profit;
}
player.addAdena("Sell", totalPrice, merchant, false);
// add to castle treasury?
if (merchant != null)
{
final long taxCollection = (long) (totalPrice * (1.0 - merchant.getTotalTaxRate(TaxType.SELL)));
merchant.getCastle().addToTreasury(taxCollection);
}
// Update current load as well
client.sendPacket(new ExUserInfoInvenWeight(player));
client.sendPacket(new ExBuySellList(player, true, merchant != null ? merchant.getTotalTaxRate(TaxType.SELL) : 0));
client.sendPacket(new ExBuySellList(player, true));
}
}

View File

@@ -75,7 +75,7 @@ public class RequestChangeAttributeItem implements IClientIncomingPacket
final int oldElementId = item.getAttackAttributeType().getClientId();
final int elementValue = item.getAttackAttribute().getValue();
item.clearAllAttributes();
item.setAttribute(new AttributeHolder(AttributeType.findByClientId(_newElementId), elementValue));
item.setAttribute(new AttributeHolder(AttributeType.findByClientId(_newElementId), elementValue), true);
// send packets
final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.S1_S_S2_ATTRIBUTE_HAS_SUCCESSFULLY_CHANGED_TO_S3_ATTRIBUTE);

View File

@@ -17,6 +17,7 @@
package com.l2jmobius.gameserver.network.serverpackets;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.enums.AttributeType;
import com.l2jmobius.gameserver.enums.ItemListType;
import com.l2jmobius.gameserver.model.ItemInfo;
import com.l2jmobius.gameserver.model.TradeItem;
@@ -62,22 +63,6 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
writeItem(packet, new ItemInfo(item));
}
protected void writeTradeItem(PacketWriter packet, TradeItem item)
{
packet.writeH(item.getItem().getType1());
packet.writeD(item.getObjectId()); // ObjectId
packet.writeD(item.getItem().getDisplayId()); // ItemId
packet.writeQ(item.getCount()); // Quantity
packet.writeC(item.getItem().getType2()); // Item Type 2 : 00-weapon, 01-shield/armor, 02-ring/earring/necklace, 03-questitem, 04-adena, 05-item
packet.writeC(item.getCustomType1()); // Filler (always 0)
packet.writeQ(item.getItem().getBodyPart()); // Slot : 0006-lr.ear, 0008-neck, 0030-lr.finger, 0040-head, 0100-l.hand, 0200-gloves, 0400-chest, 0800-pants, 1000-feet, 4000-r.hand, 8000-r.hand
packet.writeC(item.getEnchant()); // Enchant level (pet level shown in control item)
packet.writeC(0x00); // TODO : Find me
packet.writeH(0x00); // Equipped : 00-No, 01-yes
packet.writeH(item.getCustomType2());
writeItemElementalAndEnchant(packet, new ItemInfo(item));
}
protected void writeItem(PacketWriter packet, ItemInfo item)
{
final int mask = calculateMask(item);
@@ -91,15 +76,14 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
packet.writeC(item.getCustomType1()); // Filler (always 0)
packet.writeH(item.getEquipped()); // Equipped : 00-No, 01-yes
packet.writeQ(item.getItem().getBodyPart()); // Slot : 0006-lr.ear, 0008-neck, 0030-lr.finger, 0040-head, 0100-l.hand, 0200-gloves, 0400-chest, 0800-pants, 1000-feet, 4000-r.hand, 8000-r.hand
packet.writeC(item.getEnchant()); // Enchant level (pet level shown in control item)
packet.writeC(item.getEnchantLevel()); // Enchant level (pet level shown in control item)
packet.writeC(0x01); // TODO : Find me
packet.writeD(item.getMana());
packet.writeD(item.getTime());
packet.writeC(0x01); // GOD Item enabled = 1 disabled (red) = 0
if (containsMask(mask, ItemListType.AUGMENT_BONUS))
{
packet.writeD(item.get1stAugmentationId());
packet.writeD(item.get2ndAugmentationId());
writeItemAugment(packet, item);
}
if (containsMask(mask, ItemListType.ELEMENTAL_ATTRIBUTE))
{
@@ -115,43 +99,22 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
}
if (containsMask(mask, ItemListType.SOUL_CRYSTAL))
{
packet.writeC(item.getSoulCrystalOptions().size()); // Size of regular soul crystal options.
for (EnsoulOption option : item.getSoulCrystalOptions())
{
packet.writeD(option.getId()); // Regular Soul Crystal Ability ID.
}
packet.writeC(item.getSoulCrystalSpecialOptions().size()); // Size of special soul crystal options.
for (EnsoulOption option : item.getSoulCrystalSpecialOptions())
{
packet.writeD(option.getId()); // Special Soul Crystal Ability ID.
}
writeItemEnsoulOptions(packet, item);
}
}
protected static int calculateMask(ItemInfo item)
{
int mask = 0;
if (item.getAugmentationBonus() > 0)
if (item.getAugmentation() != null)
{
mask |= ItemListType.AUGMENT_BONUS.getMask();
}
if (item.getAttackElementType() >= 0)
if ((item.getAttackElementType() >= 0) || (item.getAttributeDefence(AttributeType.FIRE) > 0) || (item.getAttributeDefence(AttributeType.WATER) > 0) || (item.getAttributeDefence(AttributeType.WIND) > 0) || (item.getAttributeDefence(AttributeType.EARTH) > 0) || (item.getAttributeDefence(AttributeType.HOLY) > 0) || (item.getAttributeDefence(AttributeType.DARK) > 0))
{
mask |= ItemListType.ELEMENTAL_ATTRIBUTE.getMask();
}
else
{
for (byte i = 0; i < 6; i++)
{
if (item.getElementDefAttr(i) > 0)
{
mask |= ItemListType.ELEMENTAL_ATTRIBUTE.getMask();
break;
}
}
}
if (item.getEnchantOptions() != null)
{
@@ -178,6 +141,20 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
return mask;
}
protected void writeItemAugment(PacketWriter packet, ItemInfo item)
{
if ((item != null) && (item.getAugmentation() != null))
{
packet.writeD(item.getAugmentation().getOptionId(0));
packet.writeD(item.getAugmentation().getOptionId(1));
}
else
{
packet.writeD(0);
packet.writeD(0);
}
}
protected void writeItemElementalAndEnchant(PacketWriter packet, ItemInfo item)
{
writeItemElemental(packet, item);
@@ -186,11 +163,27 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
protected void writeItemElemental(PacketWriter packet, ItemInfo item)
{
packet.writeH(item.getAttackElementType());
packet.writeH(item.getAttackElementPower());
for (byte i = 0; i < 6; i++)
if (item != null)
{
packet.writeH(item.getElementDefAttr(i));
packet.writeH(item.getAttackElementType());
packet.writeH(item.getAttackElementPower());
packet.writeH(item.getAttributeDefence(AttributeType.FIRE));
packet.writeH(item.getAttributeDefence(AttributeType.WATER));
packet.writeH(item.getAttributeDefence(AttributeType.WIND));
packet.writeH(item.getAttributeDefence(AttributeType.EARTH));
packet.writeH(item.getAttributeDefence(AttributeType.HOLY));
packet.writeH(item.getAttributeDefence(AttributeType.DARK));
}
else
{
packet.writeH(0);
packet.writeH(0);
packet.writeH(0);
packet.writeH(0);
packet.writeH(0);
packet.writeH(0);
packet.writeH(0);
packet.writeH(0);
}
}
@@ -203,6 +196,29 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
}
}
protected void writeItemEnsoulOptions(PacketWriter packet, ItemInfo item)
{
if (item != null)
{
packet.writeC(item.getSoulCrystalOptions().size()); // Size of regular soul crystal options.
for (EnsoulOption option : item.getSoulCrystalOptions())
{
packet.writeD(option.getId()); // Regular Soul Crystal Ability ID.
}
packet.writeC(item.getSoulCrystalSpecialOptions().size()); // Size of special soul crystal options.
for (EnsoulOption option : item.getSoulCrystalSpecialOptions())
{
packet.writeD(option.getId()); // Special Soul Crystal Ability ID.
}
}
else
{
packet.writeC(0); // Size of regular soul crystal options.
packet.writeC(0); // Size of special soul crystal options.
}
}
protected void writeInventoryBlock(PacketWriter packet, PcInventory inventory)
{
if (inventory.hasInventoryBlock())
@@ -219,29 +235,4 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
packet.writeH(0x00);
}
}
protected void writeCommissionItem(PacketWriter packet, ItemInfo item)
{
packet.writeD(0); // Always 0
packet.writeD(item.getItem().getId());
packet.writeQ(item.getCount());
packet.writeH(item.getItem().getType2());
packet.writeQ(item.getItem().getBodyPart());
packet.writeC(item.getEnchant());
packet.writeC(0x00); // TODO: Find me
packet.writeH(item.getCustomType2());
writeItemElementalAndEnchant(packet, item);
packet.writeD(item.getVisualId());
packet.writeC(item.getSoulCrystalOptions().size()); // Size of regular soul crystal options.
for (EnsoulOption option : item.getSoulCrystalOptions())
{
packet.writeD(option.getId()); // Regular Soul Crystal Ability ID.
}
packet.writeC(item.getSoulCrystalSpecialOptions().size()); // Size of special soul crystal options.
for (EnsoulOption option : item.getSoulCrystalSpecialOptions())
{
packet.writeD(option.getId()); // Special Soul Crystal Ability ID.
}
}
}

View File

@@ -18,10 +18,10 @@ package com.l2jmobius.gameserver.network.serverpackets;
import java.util.Collection;
import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.buylist.L2BuyList;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.buylist.Product;
import com.l2jmobius.gameserver.model.buylist.ProductList;
import com.l2jmobius.gameserver.network.OutgoingPackets;
public final class BuyList extends AbstractItemPacket
@@ -29,14 +29,16 @@ public final class BuyList extends AbstractItemPacket
private final int _listId;
private final Collection<Product> _list;
private final long _money;
private double _taxRate = 0;
private final int _inventorySlots;
private final double _castleTaxRate;
public BuyList(L2BuyList list, long currentMoney, double taxRate)
public BuyList(ProductList list, L2PcInstance player, double castleTaxRate)
{
_listId = list.getListId();
_list = list.getProducts();
_money = currentMoney;
_taxRate = taxRate;
_money = player.getAdena();
_inventorySlots = player.getInventory().getItems((item) -> !item.isQuestItem()).size();
_castleTaxRate = castleTaxRate;
}
@Override
@@ -47,23 +49,14 @@ public final class BuyList extends AbstractItemPacket
packet.writeD(0x00); // Type BUY
packet.writeQ(_money); // current money
packet.writeD(_listId);
packet.writeD(0x00); // TODO: inventory count
packet.writeD(_inventorySlots);
packet.writeH(_list.size());
for (Product product : _list)
{
if ((product.getCount() > 0) || !product.hasLimitedStock())
{
writeItem(packet, product);
if ((product.getItemId() >= 3960) && (product.getItemId() <= 4026))
{
packet.writeQ((long) (product.getPrice() * Config.RATE_SIEGE_GUARDS_PRICE * (1 + _taxRate)));
}
else
{
packet.writeQ((long) (product.getPrice() * (1 + _taxRate)));
}
packet.writeQ((long) (product.getPrice() * (1.0 + _castleTaxRate + product.getBaseTaxRate())));
}
}
return true;

View File

@@ -21,6 +21,7 @@ import java.util.Set;
import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.actor.instance.L2DecoyInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.ceremonyofchaos.CeremonyOfChaosEvent;
@@ -133,7 +134,9 @@ public class CharInfo implements IClientOutgoingPacket
for (int slot : getPaperdollOrderAugument())
{
packet.writeQ(_activeChar.getInventory().getPaperdollAugmentationId(slot)); // Confirmed
final Augmentation augment = _activeChar.getInventory().getPaperdollAugmentation(slot);
packet.writeD(augment != null ? augment.getOptionId(0) : 0); // Confirmed
packet.writeD(augment != null ? augment.getOptionId(1) : 0); // Confirmed
}
packet.writeC(_armorEnchant);

View File

@@ -29,6 +29,7 @@ import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.data.sql.impl.ClanTable;
import com.l2jmobius.gameserver.data.xml.impl.ExperienceData;
import com.l2jmobius.gameserver.datatables.AugmentationData;
import com.l2jmobius.gameserver.model.CharSelectInfoPackage;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.entity.Hero;
@@ -190,7 +191,8 @@ public class CharSelectionInfo implements IClientOutgoingPacket
packet.writeD(i == _activeId ? 1 : 0);
packet.writeC(charInfoPackage.getEnchantEffect() > 127 ? 127 : charInfoPackage.getEnchantEffect());
packet.writeQ(charInfoPackage.getAugmentationId());
packet.writeD(charInfoPackage.getAugmentation() != null ? charInfoPackage.getAugmentation().getOptionId(0) : 0);
packet.writeD(charInfoPackage.getAugmentation() != null ? charInfoPackage.getAugmentation().getOptionId(1) : 0);
// packet.writeD(charInfoPackage.getTransformId()); // Used to display Transformations
packet.writeD(0x00); // Currently on retail when you are on character select you don't see your transformation.
@@ -364,7 +366,10 @@ public class CharSelectionInfo implements IClientOutgoingPacket
if (result.next())
{
final int augment = result.getInt("augAttributes");
charInfopackage.setAugmentationId(augment == -1 ? 0 : augment);
if (augment > 0)
{
charInfopackage.setAugmentation(AugmentationData.getInstance().getAugmentation(augment));
}
}
}
}

View File

@@ -19,6 +19,7 @@ package com.l2jmobius.gameserver.network.serverpackets;
import java.util.Collection;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.actor.L2Summon;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.OutgoingPackets;
@@ -28,14 +29,17 @@ import com.l2jmobius.gameserver.network.OutgoingPackets;
*/
public class ExBuySellList extends AbstractItemPacket
{
private Collection<L2ItemInstance> _sellList = null;
private Collection<L2ItemInstance> _sellList;
private Collection<L2ItemInstance> _refundList = null;
private final boolean _done;
private double _taxRate = 1;
private final int _inventorySlots;
private double _castleTaxRate = 1;
public ExBuySellList(L2PcInstance player, boolean done)
{
_sellList = player.getInventory().getAvailableItems(false, false, false);
final L2Summon pet = player.getPet();
_sellList = player.getInventory().getItems(item -> !item.isEquipped() && item.isSellable() && ((pet == null) || (item.getObjectId() != pet.getControlObjectId())));
_inventorySlots = player.getInventory().getItems((item) -> !item.isQuestItem()).size();
if (player.hasRefund())
{
_refundList = player.getRefund().getItems();
@@ -43,10 +47,10 @@ public class ExBuySellList extends AbstractItemPacket
_done = done;
}
public ExBuySellList(L2PcInstance player, boolean done, double taxRate)
public ExBuySellList(L2PcInstance player, boolean done, double castleTaxRate)
{
this(player, done);
_taxRate = 1 - taxRate;
_castleTaxRate = 1 - castleTaxRate;
}
@Override
@@ -55,7 +59,7 @@ public class ExBuySellList extends AbstractItemPacket
OutgoingPackets.EX_BUY_SELL_LIST.writeId(packet);
packet.writeD(0x01); // Type SELL
packet.writeD(0x00); // TODO: inventory count
packet.writeD(_inventorySlots);
if ((_sellList != null))
{
@@ -63,15 +67,15 @@ public class ExBuySellList extends AbstractItemPacket
for (L2ItemInstance item : _sellList)
{
writeItem(packet, item);
packet.writeQ((long) ((item.getItem().getReferencePrice() / 2) * _taxRate));
packet.writeQ((long) ((item.getItem().getReferencePrice() / 2) * _castleTaxRate));
}
}
}
else
{
packet.writeH(0x00);
}
if ((_refundList != null) && !_refundList.isEmpty())
if ((_refundList != null) && !_refundList.isEmpty())
{
packet.writeH(_refundList.size());
int i = 0;
@@ -79,7 +83,7 @@ public class ExBuySellList extends AbstractItemPacket
{
writeItem(packet, item);
packet.writeD(i++);
packet.writeQ((long) ((item.getItem().getReferencePrice() / 2) * _taxRate));
packet.writeQ((item.getItem().getReferencePrice() / 2) * item.getCount());
}
}
else

View File

@@ -26,15 +26,15 @@ public class ExPutItemResultForVariationCancel implements IClientOutgoingPacket
private final int _itemId;
private final int _itemAug1;
private final int _itemAug2;
private final int _price;
private final long _price;
public ExPutItemResultForVariationCancel(L2ItemInstance item, int price)
public ExPutItemResultForVariationCancel(L2ItemInstance item, long price)
{
_itemObjId = item.getObjectId();
_itemId = item.getDisplayId();
_price = price;
_itemAug1 = ((short) item.getAugmentation().getId());
_itemAug2 = item.getAugmentation().getId() >> 16;
_itemAug1 = item.getAugmentation().getOptionId(0);
_itemAug2 = item.getAugmentation().getOptionId(1);
}
@Override

View File

@@ -18,6 +18,7 @@ package com.l2jmobius.gameserver.network.serverpackets;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.enums.InventorySlot;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.itemcontainer.PcInventory;
import com.l2jmobius.gameserver.network.OutgoingPackets;
@@ -73,10 +74,12 @@ public class ExUserInfoEquipSlot extends AbstractMaskPacket<InventorySlot>
{
if (containsMask(slot))
{
final Augmentation augment = inventory.getPaperdollAugmentation(slot.getSlot());
packet.writeH(22); // 10 + 4 * 3
packet.writeD(inventory.getPaperdollObjectId(slot.getSlot()));
packet.writeD(inventory.getPaperdollItemId(slot.getSlot()));
packet.writeQ(inventory.getPaperdollAugmentationId(slot.getSlot()));
packet.writeD(augment != null ? augment.getOptionId(0) : 0);
packet.writeD(augment != null ? augment.getOptionId(1) : 0);
packet.writeD(inventory.getPaperdollItemVisualId(slot.getSlot()));
}
}

View File

@@ -101,7 +101,8 @@ public class FakePlayerInfo implements IClientOutgoingPacket
for (@SuppressWarnings("unused")
int slot : getPaperdollOrderAugument())
{
packet.writeQ(0x00);
packet.writeD(0x00);
packet.writeD(0x00);
}
packet.writeC(_fpcHolder.getArmorEnchantLevel());

View File

@@ -19,6 +19,7 @@ package com.l2jmobius.gameserver.network.serverpackets;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.data.xml.impl.ExperienceData;
import com.l2jmobius.gameserver.enums.AttributeType;
import com.l2jmobius.gameserver.model.Augmentation;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.OutgoingPackets;
@@ -88,7 +89,9 @@ public class GMViewCharacterInfo implements IClientOutgoingPacket
for (int slot : getPaperdollOrder())
{
packet.writeQ(_activeChar.getInventory().getPaperdollAugmentationId(slot));
final Augmentation augment = _activeChar.getInventory().getPaperdollAugmentation(slot);
packet.writeD(augment != null ? augment.getOptionId(0) : 0); // Confirmed
packet.writeD(augment != null ? augment.getOptionId(1) : 0); // Confirmed
}
packet.writeC(_activeChar.getInventory().getTalismanSlots()); // CT2.3

View File

@@ -48,7 +48,7 @@ public class GMViewSkillInfo implements IClientOutgoingPacket
{
packet.writeD(skill.isPassive() ? 1 : 0);
packet.writeH(skill.getDisplayLevel());
packet.writeH(0x00); // Sub level
packet.writeH(skill.getSubLevel());
packet.writeD(skill.getDisplayId());
packet.writeD(0x00);
packet.writeC(isDisabled && skill.isClanSkill() ? 1 : 0);

View File

@@ -19,21 +19,22 @@ package com.l2jmobius.gameserver.network.serverpackets;
import static com.l2jmobius.gameserver.data.xml.impl.MultisellData.PAGE_SIZE;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.ensoul.EnsoulOption;
import com.l2jmobius.gameserver.model.items.enchant.attribute.AttributeHolder;
import com.l2jmobius.gameserver.model.multisell.Entry;
import com.l2jmobius.gameserver.model.multisell.Ingredient;
import com.l2jmobius.gameserver.model.multisell.ItemInfo;
import com.l2jmobius.gameserver.model.multisell.ListContainer;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.ItemInfo;
import com.l2jmobius.gameserver.model.holders.ItemChanceHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MultisellEntryHolder;
import com.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.network.OutgoingPackets;
public final class MultiSellList implements IClientOutgoingPacket
public final class MultiSellList extends AbstractItemPacket
{
private int _size, _index;
private final ListContainer _list;
private final PreparedMultisellListHolder _list;
private final boolean _finished;
public MultiSellList(ListContainer list, int index)
public MultiSellList(PreparedMultisellListHolder list, int index)
{
_list = list;
_index = index;
@@ -54,7 +55,7 @@ public final class MultiSellList implements IClientOutgoingPacket
{
OutgoingPackets.MULTI_SELL_LIST.writeId(packet);
packet.writeD(_list.getListId()); // list id
packet.writeD(_list.getId()); // list id
packet.writeC(0x00); // GOD Unknown
packet.writeD(1 + (_index / PAGE_SIZE)); // page started from 1
packet.writeD(_finished ? 0x01 : 0x00); // finished
@@ -62,165 +63,61 @@ public final class MultiSellList implements IClientOutgoingPacket
packet.writeD(_size); // list length
packet.writeC(_list.isChanceMultisell() ? 0x01 : 0x00); // new multisell window
Entry ent;
while (_size-- > 0)
{
ent = _list.getEntries().get(_index++);
packet.writeD(ent.getEntryId());
packet.writeC(ent.isStackable() ? 1 : 0);
packet.writeH(0x00);
packet.writeD(0x00);
packet.writeD(0x00);
packet.writeH(0x00);
packet.writeH(0x00);
packet.writeH(0x00);
packet.writeH(0x00);
packet.writeH(0x00);
packet.writeH(0x00);
packet.writeH(0x00);
packet.writeH(0x00);
packet.writeC(0); // Size of regular soul crystal options.
// for (EnsoulOption option : item.getSoulCrystalOptions())
// {
// packet.writeD(option.getId()); // Regular Soul Crystal Ability ID.
// }
final ItemInfo itemEnchantment = _list.getItemEnchantment(_index);
final MultisellEntryHolder entry = _list.getEntries().get(_index++);
packet.writeC(0); // Size of special soul crystal options.
// for (EnsoulOption option : item.getSoulCrystalSpecialOptions())
// {
// packet.writeD(option.getId()); // Special Soul Crystal Ability ID.
// }
packet.writeD(_index); // Entry ID. Start from 1.
packet.writeC(entry.isStackable() ? 1 : 0);
packet.writeH(ent.getProducts().size());
packet.writeH(ent.getIngredients().size());
// Those values will be passed down to MultiSellChoose packet.
packet.writeH(itemEnchantment != null ? itemEnchantment.getEnchantLevel() : 0); // enchant level
writeItemAugment(packet, itemEnchantment);
writeItemElemental(packet, itemEnchantment);
writeItemEnsoulOptions(packet, itemEnchantment);
for (Ingredient ing : ent.getProducts())
packet.writeH(entry.getProducts().size());
packet.writeH(entry.getIngredients().size());
for (ItemChanceHolder product : entry.getProducts())
{
packet.writeD(ing.getItemId());
if (ing.getTemplate() != null)
final L2Item template = ItemTable.getInstance().getTemplate(product.getId());
final ItemInfo displayItemEnchantment = (_list.isMaintainEnchantment() && (itemEnchantment != null) && (template != null) && template.getClass().equals(itemEnchantment.getItem().getClass())) ? itemEnchantment : null;
packet.writeD(product.getId());
if (template != null)
{
packet.writeQ(ing.getTemplate().getBodyPart());
packet.writeH(ing.getTemplate().getType2());
packet.writeQ(template.getBodyPart());
packet.writeH(template.getType2());
}
else
{
packet.writeQ(0);
packet.writeH(65535);
}
packet.writeQ(ing.getItemCount());
if (ing.getItemInfo() != null)
{
final ItemInfo item = ing.getItemInfo();
packet.writeH(item.getEnchantLevel()); // enchant level
packet.writeD((int) (_list.isChanceMultisell() ? ing.getChance() : item.getAugmentId())); // augment id
packet.writeD(0x00); // mana
packet.writeD(0x00); // time ?
packet.writeH(item.getElementId()); // attack element
packet.writeH(item.getElementPower()); // element power
for (int i = 0; i < 6; i++)
{
final AttributeHolder holder = item.getElementals()[i];
packet.writeH(holder != null ? holder.getValue() : 0);
}
packet.writeC(item.getSpecialAbilities().size()); // Size of regular soul crystal options.
for (EnsoulOption option : item.getSpecialAbilities())
{
packet.writeD(option.getId()); // Regular Soul Crystal Ability ID.
}
packet.writeC(item.getAdditionalSpecialAbilities().size()); // Size of special soul crystal options.
for (EnsoulOption option : item.getAdditionalSpecialAbilities())
{
packet.writeD(option.getId()); // Special Soul Crystal Ability ID.
}
}
else
{
packet.writeH(ing.getEnchantLevel()); // enchant level
packet.writeD((int) ing.getChance()); // augment id
packet.writeD(0x00); // mana
packet.writeD(0x00); // time ?
packet.writeH(0x00); // attack element
packet.writeH(0x00); // element power
packet.writeH(0x00); // fire
packet.writeH(0x00); // water
packet.writeH(0x00); // wind
packet.writeH(0x00); // earth
packet.writeH(0x00); // holy
packet.writeH(0x00); // dark
packet.writeC(0); // Size of regular soul crystal options.
// for (EnsoulOption option : item.getSoulCrystalOptions())
// {
// packet.writeD(option.getId()); // Regular Soul Crystal Ability ID.
// }
packet.writeC(0); // Size of special soul crystal options.
// for (EnsoulOption option : item.getSoulCrystalSpecialOptions())
// {
// packet.writeD(option.getId()); // Special Soul Crystal Ability ID.
// }
}
packet.writeQ(_list.getProductCount(product));
packet.writeH(displayItemEnchantment != null ? displayItemEnchantment.getEnchantLevel() : 0); // enchant level
packet.writeD((int) Math.ceil(product.getChance())); // chance
writeItemAugment(packet, displayItemEnchantment);
writeItemElemental(packet, displayItemEnchantment);
writeItemEnsoulOptions(packet, displayItemEnchantment);
}
for (Ingredient ing : ent.getIngredients())
for (ItemHolder ingredient : entry.getIngredients())
{
packet.writeD(ing.getItemId());
packet.writeH(ing.getTemplate() != null ? ing.getTemplate().getType2() : 65535);
packet.writeQ(ing.getItemCount());
if (ing.getItemInfo() != null)
{
final ItemInfo item = ing.getItemInfo();
packet.writeH(item.getEnchantLevel()); // enchant level
packet.writeD((int) (_list.isChanceMultisell() ? ing.getChance() : item.getAugmentId())); // augment id
packet.writeD(0x00); // mana
packet.writeH(item.getElementId()); // attack element
packet.writeH(item.getElementPower()); // element power
for (int i = 0; i < 6; i++)
{
final AttributeHolder holder = item.getElementals()[i];
packet.writeH(holder != null ? holder.getValue() : 0);
}
packet.writeC(item.getSpecialAbilities().size()); // Size of regular soul crystal options.
for (EnsoulOption option : item.getSpecialAbilities())
{
packet.writeD(option.getId()); // Regular Soul Crystal Ability ID.
}
packet.writeC(item.getAdditionalSpecialAbilities().size()); // Size of special soul crystal options.
for (EnsoulOption option : item.getAdditionalSpecialAbilities())
{
packet.writeD(option.getId()); // Special Soul Crystal Ability ID.
}
}
else
{
packet.writeH(ing.getEnchantLevel()); // enchant level
packet.writeD((int) ing.getChance()); // augment id
packet.writeD(0x00); // mana
packet.writeH(0x00); // attack element
packet.writeH(0x00); // element power
packet.writeH(0x00); // fire
packet.writeH(0x00); // water
packet.writeH(0x00); // wind
packet.writeH(0x00); // earth
packet.writeH(0x00); // holy
packet.writeH(0x00); // dark
packet.writeC(0); // Size of regular soul crystal options.
// for (EnsoulOption option : item.getSoulCrystalOptions())
// {
// packet.writeD(option.getId()); // Regular Soul Crystal Ability ID.
// }
packet.writeC(0); // Size of special soul crystal options.
// for (EnsoulOption option : item.getSoulCrystalSpecialOptions())
// {
// packet.writeD(option.getId()); // Special Soul Crystal Ability ID.
// }
}
final L2Item template = ItemTable.getInstance().getTemplate(ingredient.getId());
final ItemInfo displayItemEnchantment = ((itemEnchantment != null) && (itemEnchantment.getItem().getId() == ingredient.getId())) ? itemEnchantment : null;
packet.writeD(ingredient.getId());
packet.writeH(template != null ? template.getType2() : 65535);
packet.writeQ(_list.getIngredientCount(ingredient));
packet.writeH(displayItemEnchantment != null ? displayItemEnchantment.getEnchantLevel() : 0); // enchant level
writeItemAugment(packet, displayItemEnchantment);
writeItemElemental(packet, displayItemEnchantment);
writeItemEnsoulOptions(packet, displayItemEnchantment);
}
}
return true;
}
}
}

View File

@@ -1,111 +0,0 @@
/*
* 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 com.l2jmobius.gameserver.network.serverpackets;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.enums.AttributeType;
import com.l2jmobius.gameserver.enums.TaxType;
import com.l2jmobius.gameserver.model.actor.L2Summon;
import com.l2jmobius.gameserver.model.actor.instance.L2MerchantInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.OutgoingPackets;
public class SellList implements IClientOutgoingPacket
{
private final L2PcInstance _activeChar;
private final L2MerchantInstance _merchant;
private final long _money;
private final List<L2ItemInstance> _sellList;
public SellList(L2PcInstance player)
{
this(player, null);
}
public SellList(L2PcInstance player, L2MerchantInstance lease)
{
_activeChar = player;
_merchant = lease;
_money = _activeChar.getAdena();
if (_merchant == null)
{
_sellList = new LinkedList<>();
final L2Summon pet = _activeChar.getPet();
for (L2ItemInstance item : _activeChar.getInventory().getItems())
{
if (!item.isEquipped() && item.isSellable() && ((pet == null) || (item.getObjectId() != pet.getControlObjectId()))) // Pet is summoned and not the item that summoned the pet
{
_sellList.add(item);
}
}
}
else
{
_sellList = Collections.emptyList();
}
}
@Override
public boolean write(PacketWriter packet)
{
OutgoingPackets.SELL_LIST.writeId(packet);
packet.writeQ(_money);
packet.writeD(_merchant == null ? 0x00 : 1000000 + _merchant.getTemplate().getId());
packet.writeH(_sellList.size());
for (L2ItemInstance item : _sellList)
{
int price = item.getItem().getReferencePrice() / 2;
if (_merchant != null)
{
price -= (price * _merchant.getTotalTaxRate(TaxType.SELL));
}
packet.writeH(item.getItem().getType1());
packet.writeD(item.getObjectId());
packet.writeD(item.getDisplayId());
packet.writeQ(item.getCount());
packet.writeH(item.getItem().getType2());
packet.writeH(item.isEquipped() ? 0x01 : 0x00);
packet.writeD(item.getItem().getBodyPart());
packet.writeH(item.getEnchantLevel());
packet.writeH(0x00); // TODO: Verify me
packet.writeH(item.getCustomType2());
packet.writeQ(price);
// T1
packet.writeH(item.getAttackAttributeType().getClientId());
packet.writeH(item.getAttackAttributePower());
for (AttributeType type : AttributeType.ATTRIBUTE_TYPES)
{
packet.writeH(item.getDefenceAttribute(type));
}
// Enchant Effects
for (int op : item.getEnchantOptions())
{
packet.writeH(op);
}
}
return true;
}
}

View File

@@ -20,8 +20,8 @@ import java.util.Collection;
import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.buylist.L2BuyList;
import com.l2jmobius.gameserver.model.buylist.Product;
import com.l2jmobius.gameserver.model.buylist.ProductList;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.network.OutgoingPackets;
@@ -32,7 +32,7 @@ public class ShopPreviewList implements IClientOutgoingPacket
private final long _money;
private int _expertise;
public ShopPreviewList(L2BuyList list, long currentMoney, int expertiseIndex)
public ShopPreviewList(ProductList list, long currentMoney, int expertiseIndex)
{
_listId = list.getListId();
_list = list.getProducts();

View File

@@ -37,7 +37,7 @@ public final class TradeOtherAdd extends AbstractItemPacket
{
OutgoingPackets.TRADE_OTHER_ADD.writeId(packet);
packet.writeH(1); // item count
writeTradeItem(packet, _item);
writeItem(packet, _item);
return true;
}
}

View File

@@ -37,7 +37,7 @@ public final class TradeOwnAdd extends AbstractItemPacket
{
OutgoingPackets.TRADE_OWN_ADD.writeId(packet);
packet.writeH(1); // items added count
writeTradeItem(packet, _item);
writeItem(packet, _item);
return true;
}
}

View File

@@ -42,7 +42,7 @@ public class TradeUpdate extends AbstractItemPacket
packet.writeH(1);
packet.writeH((_newCount > 0) && _item.getItem().isStackable() ? 3 : 2);
writeTradeItem(packet, _item);
writeItem(packet, _item);
return true;
}
}

View File

@@ -45,7 +45,7 @@ public class ExResponseCommissionBuyItem implements IClientOutgoingPacket
if (_commissionItem != null)
{
final ItemInfo itemInfo = _commissionItem.getItemInfo();
packet.writeD(itemInfo.getEnchant());
packet.writeD(itemInfo.getEnchantLevel());
packet.writeD(itemInfo.getItem().getId());
packet.writeQ(itemInfo.getCount());
}