/**
* License
* THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS
* CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE").
* THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.
* ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR
* COPYRIGHT LAW IS PROHIBITED.
*
* BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND
* AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE
* MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED
* HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
*
*/
package l1j.server.server.model.npc.action;
import java.util.List;
import l1j.server.server.datatables.ItemTable;
import l1j.server.server.model.L1Object;
import l1j.server.server.model.L1ObjectAmount;
import l1j.server.server.model.L1PcInventory;
import l1j.server.server.model.Instance.L1ItemInstance;
import l1j.server.server.model.Instance.L1NpcInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.npc.L1NpcHtml;
import l1j.server.server.serverpackets.S_HowManyMake;
import l1j.server.server.serverpackets.S_ServerMessage;
import l1j.server.server.templates.L1Item;
import l1j.server.server.utils.IterableElementList;
import l1j.server.server.utils.collections.Lists;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class L1NpcMakeItemAction extends L1NpcXmlAction {
private final List<L1ObjectAmount<Integer>> _materials = Lists.newList();
private final List<L1ObjectAmount<Integer>> _items = Lists.newList();
private final boolean _isAmountInputable;
private final L1NpcAction _actionOnSucceed;
private final L1NpcAction _actionOnFail;
public L1NpcMakeItemAction(Element element) {
super(element);
_isAmountInputable = L1NpcXmlParser.getBoolAttribute(element, "AmountInputable", true);
NodeList list = element.getChildNodes();
for (Element elem : new IterableElementList(list)) {
if (elem.getNodeName().equalsIgnoreCase("Material")) {
int id = Integer.valueOf(elem.getAttribute("ItemId"));
int amount = Integer.valueOf(elem.getAttribute("Amount"));
_materials.add(new L1ObjectAmount<Integer>(id, amount));
continue;
}
if (elem.getNodeName().equalsIgnoreCase("Item")) {
int id = Integer.valueOf(elem.getAttribute("ItemId"));
int amount = Integer.valueOf(elem.getAttribute("Amount"));
_items.add(new L1ObjectAmount<Integer>(id, amount));
continue;
}
}
if (_items.isEmpty() || _materials.isEmpty()) {
throw new IllegalArgumentException();
}
Element elem = L1NpcXmlParser.getFirstChildElementByTagName(element, "Succeed");
_actionOnSucceed = elem == null ? null : new L1NpcListedAction(elem);
elem = L1NpcXmlParser.getFirstChildElementByTagName(element, "Fail");
_actionOnFail = elem == null ? null : new L1NpcListedAction(elem);
}
private boolean makeItems(L1PcInstance pc, String npcName, int amount) {
if (amount <= 0) {
return false;
}
boolean isEnoughMaterials = true;
for (L1ObjectAmount<Integer> material : _materials) {
if (!pc.getInventory().checkItemNotEquipped(material.getObject(), material.getAmount() * amount)) {
L1Item temp = ItemTable.getInstance().getTemplate(material.getObject());
pc.sendPackets(new S_ServerMessage(337, temp.getName() + "("
+ ((material.getAmount() * amount) - pc.getInventory().countItems(temp.getItemId())) + ")")); // \f1%0が不足しています。
isEnoughMaterials = false;
}
}
if (!isEnoughMaterials) {
return false;
}
// 容量と重量の計算
int countToCreate = 0; // アイテムの個数(纏まる物は1個)
int weight = 0;
for (L1ObjectAmount<Integer> makingItem : _items) {
L1Item temp = ItemTable.getInstance().getTemplate(makingItem.getObject());
if (temp.isStackable()) {
if (!pc.getInventory().checkItem(makingItem.getObject())) {
countToCreate += 1;
}
}
else {
countToCreate += makingItem.getAmount() * amount;
}
weight += temp.getWeight() * (makingItem.getAmount() * amount) / 1000;
}
// 容量確認
if (pc.getInventory().getSize() + countToCreate > 180) {
pc.sendPackets(new S_ServerMessage(263)); // \f1一人のキャラクターが持って歩けるアイテムは最大180個までです。
return false;
}
// 重量確認
if (pc.getMaxWeight() < pc.getInventory().getWeight() + weight) {
pc.sendPackets(new S_ServerMessage(82)); // アイテムが重すぎて、これ以上持てません。
return false;
}
for (L1ObjectAmount<Integer> material : _materials) {
// 材料消費
pc.getInventory().consumeItem(material.getObject(), material.getAmount() * amount);
}
for (L1ObjectAmount<Integer> makingItem : _items) {
L1ItemInstance item = pc.getInventory().storeItem(makingItem.getObject(), makingItem.getAmount() * amount);
if (item != null) {
String itemName = ItemTable.getInstance().getTemplate(makingItem.getObject()).getName();
if (makingItem.getAmount() * amount > 1) {
itemName = itemName + " (" + makingItem.getAmount() * amount + ")";
}
pc.sendPackets(new S_ServerMessage(143, npcName, itemName)); // \f1%0が%1をくれました。
}
}
return true;
}
/**
* 指定されたインベントリ内に、素材が何セットあるか数える
*/
private int countNumOfMaterials(L1PcInventory inv) {
int count = Integer.MAX_VALUE;
for (L1ObjectAmount<Integer> material : _materials) {
int numOfSet = inv.countItems(material.getObject()) / material.getAmount();
count = Math.min(count, numOfSet);
}
return count;
}
@Override
public L1NpcHtml execute(String actionName, L1PcInstance pc, L1Object obj, byte[] args) {
int numOfMaterials = countNumOfMaterials(pc.getInventory());
if ((1 < numOfMaterials) && _isAmountInputable) {
pc.sendPackets(new S_HowManyMake(obj.getId(), numOfMaterials, actionName));
return null;
}
return executeWithAmount(actionName, pc, obj, 1);
}
@Override
public L1NpcHtml executeWithAmount(String actionName, L1PcInstance pc, L1Object obj, int amount) {
L1NpcInstance npc = (L1NpcInstance) obj;
L1NpcHtml result = null;
if (makeItems(pc, npc.getNpcTemplate().get_name(), amount)) {
if (_actionOnSucceed != null) {
result = _actionOnSucceed.execute(actionName, pc, obj, new byte[0]);
}
}
else {
if (_actionOnFail != null) {
result = _actionOnFail.execute(actionName, pc, obj, new byte[0]);
}
}
return result == null ? L1NpcHtml.HTML_CLOSE : result;
}
}