Multisell, augment and tax zone rework.
Adapted from: L2jUnity free files.
This commit is contained in:
@@ -237,7 +237,6 @@ public final class Config
|
||||
public static double ALT_GAME_CREATION_XP_RATE;
|
||||
public static double ALT_GAME_CREATION_RARE_XPSP_RATE;
|
||||
public static double ALT_GAME_CREATION_SP_RATE;
|
||||
public static boolean ALT_BLACKSMITH_USE_RECIPES;
|
||||
public static boolean ALT_CLAN_LEADER_INSTANT_ACTIVATION;
|
||||
public static int ALT_CLAN_JOIN_DAYS;
|
||||
public static int ALT_CLAN_CREATE_DAYS;
|
||||
@@ -1659,7 +1658,6 @@ public final class Config
|
||||
ALT_GAME_CREATION_XP_RATE = Character.getDouble("AltGameCreationXpRate", 1);
|
||||
ALT_GAME_CREATION_SP_RATE = Character.getDouble("AltGameCreationSpRate", 1);
|
||||
ALT_GAME_CREATION_RARE_XPSP_RATE = Character.getDouble("AltGameCreationRareXpSpRate", 2);
|
||||
ALT_BLACKSMITH_USE_RECIPES = Character.getBoolean("AltBlacksmithUseRecipes", true);
|
||||
ALT_CLAN_LEADER_INSTANT_ACTIVATION = Character.getBoolean("AltClanLeaderInstantActivation", false);
|
||||
ALT_CLAN_JOIN_DAYS = Character.getInt("DaysBeforeJoinAClan", 1);
|
||||
ALT_CLAN_CREATE_DAYS = Character.getInt("DaysBeforeCreateAClan", 10);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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()
|
||||
|
@@ -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":
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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)
|
||||
|
@@ -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()
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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()
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
|
@@ -162,7 +162,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;
|
||||
@@ -212,6 +211,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;
|
||||
@@ -235,7 +235,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;
|
||||
@@ -290,7 +289,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;
|
||||
@@ -561,7 +559,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;
|
||||
@@ -4336,6 +4334,8 @@ public final class L2PcInstance extends L2Playable
|
||||
return getClan().getAllyCrestId();
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
/*
|
||||
public void queryGameGuard()
|
||||
{
|
||||
if (getClient() != null)
|
||||
@@ -4345,9 +4345,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.
|
||||
@@ -4712,12 +4713,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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
//}
|
||||
}
|
@@ -49,4 +49,10 @@ public class EnsoulOption extends SkillHolder
|
||||
{
|
||||
return _desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Ensoul Id: " + _id + " Name: " + _name + " Desc: " + _desc;
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -2701,7 +2701,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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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()
|
||||
{
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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());
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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())
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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())
|
||||
{
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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()
|
||||
{
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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));
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
@@ -75,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))
|
||||
{
|
||||
@@ -99,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)
|
||||
{
|
||||
@@ -162,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);
|
||||
@@ -170,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,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())
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
@@ -191,7 +192,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.
|
||||
@@ -365,7 +367,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
@@ -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());
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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,175 +55,71 @@ public final class MultiSellList implements IClientOutgoingPacket
|
||||
{
|
||||
OutgoingPackets.MULTI_SELL_LIST.writeId(packet);
|
||||
|
||||
packet.writeC(0x00);
|
||||
packet.writeD(_list.getListId()); // list id
|
||||
packet.writeC(0x00); // Helios
|
||||
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
|
||||
packet.writeD(PAGE_SIZE); // size of pages
|
||||
packet.writeD(_size); // list length
|
||||
packet.writeC(_list.isChanceMultisell() ? 0x01 : 0x00); // new multisell window
|
||||
packet.writeD(0x20); // Always 32 oO
|
||||
packet.writeD(0x20); // Helios - Always 32
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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();
|
||||
|
@@ -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());
|
||||
}
|
||||
|
Reference in New Issue
Block a user