12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022 |
- /*
- * 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.l2jserver.gameserver;
- import java.io.File;
- import java.io.IOException;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Map;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- import javax.xml.parsers.DocumentBuilderFactory;
- import javax.xml.parsers.ParserConfigurationException;
- import javolution.util.FastList;
- import javolution.util.FastMap;
- import org.w3c.dom.Document;
- import org.w3c.dom.NamedNodeMap;
- import org.w3c.dom.Node;
- import org.xml.sax.SAXException;
- import com.l2jserver.Config;
- import com.l2jserver.gameserver.datatables.ItemTable;
- import com.l2jserver.gameserver.model.L2ManufactureItem;
- import com.l2jserver.gameserver.model.L2RecipeInstance;
- import com.l2jserver.gameserver.model.L2RecipeList;
- import com.l2jserver.gameserver.model.L2RecipeStatInstance;
- import com.l2jserver.gameserver.model.StatsSet;
- import com.l2jserver.gameserver.model.TempItem;
- import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
- import com.l2jserver.gameserver.model.itemcontainer.Inventory;
- import com.l2jserver.gameserver.model.items.L2Item;
- import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
- import com.l2jserver.gameserver.model.skills.L2Skill;
- import com.l2jserver.gameserver.model.stats.Stats;
- import com.l2jserver.gameserver.network.SystemMessageId;
- import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
- import com.l2jserver.gameserver.network.serverpackets.ItemList;
- import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
- import com.l2jserver.gameserver.network.serverpackets.RecipeBookItemList;
- import com.l2jserver.gameserver.network.serverpackets.RecipeItemMakeInfo;
- import com.l2jserver.gameserver.network.serverpackets.RecipeShopItemInfo;
- import com.l2jserver.gameserver.network.serverpackets.SetupGauge;
- import com.l2jserver.gameserver.network.serverpackets.StatusUpdate;
- import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
- import com.l2jserver.gameserver.taskmanager.AttackStanceTaskManager;
- import com.l2jserver.gameserver.util.Util;
- import com.l2jserver.util.Rnd;
- public class RecipeController
- {
- protected static final Logger _log = Logger.getLogger(RecipeController.class.getName());
-
- private static final Map<Integer, L2RecipeList> _lists = new FastMap<Integer, L2RecipeList>();
- protected static final Map<Integer, RecipeItemMaker> _activeMakers = new FastMap<Integer, RecipeItemMaker>().shared();
- private static final String RECIPES_FILE = "recipes.xml";
-
- public static RecipeController getInstance()
- {
- return SingletonHolder._instance;
- }
-
- protected RecipeController()
- {
- try
- {
- loadFromXML();
- _log.info("RecipeController: Loaded " + _lists.size() + " recipes.");
- }
- catch (Exception e)
- {
- _log.log(Level.SEVERE, "Failed loading recipe list", e);
- }
- }
-
- public int getRecipesCount()
- {
- return _lists.size();
- }
-
- public L2RecipeList getRecipeList(int listId)
- {
- return _lists.get(listId);
- }
-
- public L2RecipeList getRecipeByItemId(int itemId)
- {
- for (L2RecipeList find : _lists.values())
- {
- if (find.getRecipeId() == itemId)
- {
- return find;
- }
- }
- return null;
- }
-
- public int[] getAllItemIds()
- {
- int[] idList = new int[_lists.size()];
- int i = 0;
- for (L2RecipeList rec : _lists.values())
- {
- idList[i++] = rec.getRecipeId();
- }
- return idList;
- }
-
- public synchronized void requestBookOpen(L2PcInstance player, boolean isDwarvenCraft)
- {
- RecipeItemMaker maker = null;
- if (Config.ALT_GAME_CREATION)
- {
- maker = _activeMakers.get(player.getObjectId());
- }
-
- if (maker == null)
- {
- RecipeBookItemList response = new RecipeBookItemList(isDwarvenCraft, player.getMaxMp());
- response.addRecipes(isDwarvenCraft ? player.getDwarvenRecipeBook() : player.getCommonRecipeBook());
- player.sendPacket(response);
- return;
- }
-
- player.sendPacket(SystemMessageId.CANT_ALTER_RECIPEBOOK_WHILE_CRAFTING);
- }
-
- public synchronized void requestMakeItemAbort(L2PcInstance player)
- {
- _activeMakers.remove(player.getObjectId()); // TODO: anything else here?
- }
-
- public synchronized void requestManufactureItem(L2PcInstance manufacturer, int recipeListId, L2PcInstance player)
- {
- L2RecipeList recipeList = getValidRecipeList(player, recipeListId);
-
- if (recipeList == null)
- {
- return;
- }
-
- List<L2RecipeList> dwarfRecipes = Arrays.asList(manufacturer.getDwarvenRecipeBook());
- List<L2RecipeList> commonRecipes = Arrays.asList(manufacturer.getCommonRecipeBook());
-
- if (!dwarfRecipes.contains(recipeList) && !commonRecipes.contains(recipeList))
- {
- Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false recipe id.", Config.DEFAULT_PUNISH);
- return;
- }
-
- RecipeItemMaker maker;
-
- if (Config.ALT_GAME_CREATION && ((maker = _activeMakers.get(manufacturer.getObjectId())) != null)) // check if busy
- {
- player.sendMessage("Manufacturer is busy, please try later.");
- return;
- }
-
- maker = new RecipeItemMaker(manufacturer, recipeList, player);
- if (maker._isValid)
- {
- if (Config.ALT_GAME_CREATION)
- {
- _activeMakers.put(manufacturer.getObjectId(), maker);
- ThreadPoolManager.getInstance().scheduleGeneral(maker, 100);
- }
- else
- {
- maker.run();
- }
- }
- }
-
- public synchronized void requestMakeItem(L2PcInstance player, int recipeListId)
- {
- if (AttackStanceTaskManager.getInstance().getAttackStanceTask(player) || player.isInDuel())
- {
- player.sendPacket(SystemMessageId.CANT_OPERATE_PRIVATE_STORE_DURING_COMBAT);
- return;
- }
-
- L2RecipeList recipeList = getValidRecipeList(player, recipeListId);
-
- if (recipeList == null)
- {
- return;
- }
-
- List<L2RecipeList> dwarfRecipes = Arrays.asList(player.getDwarvenRecipeBook());
- List<L2RecipeList> commonRecipes = Arrays.asList(player.getCommonRecipeBook());
-
- if (!dwarfRecipes.contains(recipeList) && !commonRecipes.contains(recipeList))
- {
- Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false recipe id.", Config.DEFAULT_PUNISH);
- return;
- }
-
- RecipeItemMaker maker;
-
- // check if already busy (possible in alt mode only)
- if (Config.ALT_GAME_CREATION && ((maker = _activeMakers.get(player.getObjectId())) != null))
- {
- SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S2_S1);
- sm.addItemName(recipeList.getItemId());
- sm.addString("You are busy creating");
- player.sendPacket(sm);
- return;
- }
-
- maker = new RecipeItemMaker(player, recipeList, player);
- if (maker._isValid)
- {
- if (Config.ALT_GAME_CREATION)
- {
- _activeMakers.put(player.getObjectId(), maker);
- ThreadPoolManager.getInstance().scheduleGeneral(maker, 100);
- }
- else
- {
- maker.run();
- }
- }
- }
-
- private void loadFromXML() throws SAXException, IOException, ParserConfigurationException
- {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setValidating(false);
- factory.setIgnoringComments(true);
- File file = new File(Config.DATAPACK_ROOT + "/data/" + RECIPES_FILE);
- if (file.exists())
- {
- Document doc = factory.newDocumentBuilder().parse(file);
- List<L2RecipeInstance> recipePartList = new FastList<L2RecipeInstance>();
- List<L2RecipeStatInstance> recipeStatUseList = new FastList<L2RecipeStatInstance>();
- List<L2RecipeStatInstance> recipeAltStatChangeList = new FastList<L2RecipeStatInstance>();
-
- for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
- {
- if ("list".equalsIgnoreCase(n.getNodeName()))
- {
- recipesFile: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
- {
- if ("item".equalsIgnoreCase(d.getNodeName()))
- {
- recipePartList.clear();
- recipeStatUseList.clear();
- recipeAltStatChangeList.clear();
- NamedNodeMap attrs = d.getAttributes();
- Node att;
- int id = -1;
- boolean haveRare = false;
- StatsSet set = new StatsSet();
-
- att = attrs.getNamedItem("id");
- if (att == null)
- {
- _log.severe("Missing id for recipe item, skipping");
- continue;
- }
- id = Integer.parseInt(att.getNodeValue());
- set.set("id", id);
-
- att = attrs.getNamedItem("recipeId");
- if (att == null)
- {
- _log.severe("Missing recipeId for recipe item id: " + id + ", skipping");
- continue;
- }
- set.set("recipeId", Integer.parseInt(att.getNodeValue()));
-
- att = attrs.getNamedItem("name");
- if (att == null)
- {
- _log.severe("Missing name for recipe item id: " + id + ", skipping");
- continue;
- }
- set.set("recipeName", att.getNodeValue());
-
- att = attrs.getNamedItem("craftLevel");
- if (att == null)
- {
- _log.severe("Missing level for recipe item id: " + id + ", skipping");
- continue;
- }
- set.set("craftLevel", Integer.parseInt(att.getNodeValue()));
-
- att = attrs.getNamedItem("type");
- if (att == null)
- {
- _log.severe("Missing type for recipe item id: " + id + ", skipping");
- continue;
- }
- set.set("isDwarvenRecipe", att.getNodeValue().equalsIgnoreCase("dwarven"));
-
- att = attrs.getNamedItem("successRate");
- if (att == null)
- {
- _log.severe("Missing successRate for recipe item id: " + id + ", skipping");
- continue;
- }
- set.set("successRate", Integer.parseInt(att.getNodeValue()));
-
- for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
- {
- if ("statUse".equalsIgnoreCase(c.getNodeName()))
- {
- String statName = c.getAttributes().getNamedItem("name").getNodeValue();
- int value = Integer.parseInt(c.getAttributes().getNamedItem("value").getNodeValue());
- try
- {
- recipeStatUseList.add(new L2RecipeStatInstance(statName, value));
- }
- catch (Exception e)
- {
- _log.severe("Error in StatUse parameter for recipe item id: " + id + ", skipping");
- continue recipesFile;
- }
- }
- else if ("altStatChange".equalsIgnoreCase(c.getNodeName()))
- {
- String statName = c.getAttributes().getNamedItem("name").getNodeValue();
- int value = Integer.parseInt(c.getAttributes().getNamedItem("value").getNodeValue());
- try
- {
- recipeAltStatChangeList.add(new L2RecipeStatInstance(statName, value));
- }
- catch (Exception e)
- {
- _log.severe("Error in AltStatChange parameter for recipe item id: " + id + ", skipping");
- continue recipesFile;
- }
- }
- else if ("ingredient".equalsIgnoreCase(c.getNodeName()))
- {
- int ingId = Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue());
- int ingCount = Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue());
- recipePartList.add(new L2RecipeInstance(ingId, ingCount));
- }
- else if ("production".equalsIgnoreCase(c.getNodeName()))
- {
- set.set("itemId", Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue()));
- set.set("count", Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue()));
- }
- else if ("productionRare".equalsIgnoreCase(c.getNodeName()))
- {
- set.set("rareItemId", Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue()));
- set.set("rareCount", Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue()));
- set.set("rarity", Integer.parseInt(c.getAttributes().getNamedItem("rarity").getNodeValue()));
- haveRare = true;
- }
- }
-
- L2RecipeList recipeList = new L2RecipeList(set, haveRare);
- for (L2RecipeInstance recipePart : recipePartList)
- {
- recipeList.addRecipe(recipePart);
- }
- for (L2RecipeStatInstance recipeStatUse : recipeStatUseList)
- {
- recipeList.addStatUse(recipeStatUse);
- }
- for (L2RecipeStatInstance recipeAltStatChange : recipeAltStatChangeList)
- {
- recipeList.addAltStatChange(recipeAltStatChange);
- }
-
- _lists.put(id, recipeList);
- }
- }
- }
- }
- }
- else
- {
- _log.severe("Recipes file (" + file.getAbsolutePath() + ") doesnt exists.");
- }
- }
-
- private static class RecipeItemMaker implements Runnable
- {
- protected boolean _isValid;
- protected List<TempItem> _items = null;
- protected final L2RecipeList _recipeList;
- protected final L2PcInstance _player; // "crafter"
- protected final L2PcInstance _target; // "customer"
- protected final L2Skill _skill;
- protected final int _skillId;
- protected final int _skillLevel;
- protected int _creationPasses = 1;
- protected int _itemGrab;
- protected int _exp = -1;
- protected int _sp = -1;
- protected long _price;
- protected int _totalItems;
- protected int _delay;
-
- public RecipeItemMaker(L2PcInstance pPlayer, L2RecipeList pRecipeList, L2PcInstance pTarget)
- {
- _player = pPlayer;
- _target = pTarget;
- _recipeList = pRecipeList;
-
- _isValid = false;
- _skillId = _recipeList.isDwarvenRecipe() ? L2Skill.SKILL_CREATE_DWARVEN : L2Skill.SKILL_CREATE_COMMON;
- _skillLevel = _player.getSkillLevel(_skillId);
- _skill = _player.getKnownSkill(_skillId);
-
- _player.isInCraftMode(true);
-
- if (_player.isAlikeDead())
- {
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- abort();
- return;
- }
-
- if (_target.isAlikeDead())
- {
- _target.sendPacket(ActionFailed.STATIC_PACKET);
- abort();
- return;
- }
-
- if (_target.isProcessingTransaction())
- {
- _target.sendPacket(ActionFailed.STATIC_PACKET);
- abort();
- return;
- }
-
- if (_player.isProcessingTransaction())
- {
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- abort();
- return;
- }
-
- // validate recipe list
- if (_recipeList.getRecipes().length == 0)
- {
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- abort();
- return;
- }
-
- // validate skill level
- if (_recipeList.getLevel() > _skillLevel)
- {
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- abort();
- return;
- }
-
- // check that customer can afford to pay for creation services
- if (_player != _target)
- {
- for (L2ManufactureItem temp : _player.getCreateList().getList())
- {
- if (temp.getRecipeId() == _recipeList.getId()) // find recipe for item we want manufactured
- {
- _price = temp.getCost();
- if (_target.getAdena() < _price) // check price
- {
- _target.sendPacket(SystemMessageId.YOU_NOT_ENOUGH_ADENA);
- abort();
- return;
- }
- break;
- }
- }
- }
-
- // make temporary items
- if ((_items = listItems(false)) == null)
- {
- abort();
- return;
- }
-
- for (TempItem i : _items)
- {
- _totalItems += i.getQuantity();
- }
-
- // initial statUse checks
- if (!calculateStatUse(false, false))
- {
- abort();
- return;
- }
-
- // initial AltStatChange checks
- if (Config.ALT_GAME_CREATION)
- {
- calculateAltStatChange();
- }
-
- updateMakeInfo(true);
- updateCurMp();
- updateCurLoad();
-
- _player.isInCraftMode(false);
- _isValid = true;
- }
-
- @Override
- public void run()
- {
- if (!Config.IS_CRAFTING_ENABLED)
- {
- _target.sendMessage("Item creation is currently disabled.");
- abort();
- return;
- }
-
- if ((_player == null) || (_target == null))
- {
- _log.warning("player or target == null (disconnected?), aborting" + _target + _player);
- abort();
- return;
- }
-
- if (!_player.isOnline() || !_target.isOnline())
- {
- _log.warning("player or target is not online, aborting " + _target + _player);
- abort();
- return;
- }
-
- if (Config.ALT_GAME_CREATION && (_activeMakers.get(_player.getObjectId()) == null))
- {
- if (_target != _player)
- {
- _target.sendMessage("Manufacture aborted");
- _player.sendMessage("Manufacture aborted");
- }
- else
- {
- _player.sendMessage("Item creation aborted");
- }
-
- abort();
- return;
- }
-
- if (Config.ALT_GAME_CREATION && !_items.isEmpty())
- {
-
- if (!calculateStatUse(true, true))
- {
- return; // check stat use
- }
- updateCurMp(); // update craft window mp bar
-
- grabSomeItems(); // grab (equip) some more items with a nice msg to player
-
- // if still not empty, schedule another pass
- if (!_items.isEmpty())
- {
- // divided by RATE_CONSUMABLES_COST to remove craft time increase on higher consumables rates
- _delay = (int) ((Config.ALT_GAME_CREATION_SPEED * _player.getMReuseRate(_skill) * GameTimeController.TICKS_PER_SECOND) / Config.RATE_CONSUMABLE_COST) * GameTimeController.MILLIS_IN_TICK;
-
- // FIXME: please fix this packet to show crafting animation (somebody)
- MagicSkillUse msk = new MagicSkillUse(_player, _skillId, _skillLevel, _delay, 0);
- _player.broadcastPacket(msk);
-
- _player.sendPacket(new SetupGauge(0, _delay));
- ThreadPoolManager.getInstance().scheduleGeneral(this, 100 + _delay);
- }
- else
- {
- // for alt mode, sleep delay msec before finishing
- _player.sendPacket(new SetupGauge(0, _delay));
-
- try
- {
- Thread.sleep(_delay);
- }
- catch (InterruptedException e)
- {
- }
- finally
- {
- finishCrafting();
- }
- }
- } // for old craft mode just finish
- else
- {
- finishCrafting();
- }
- }
-
- private void finishCrafting()
- {
- if (!Config.ALT_GAME_CREATION)
- {
- calculateStatUse(false, true);
- }
-
- // first take adena for manufacture
- if ((_target != _player) && (_price > 0)) // customer must pay for services
- {
- // attempt to pay for item
- L2ItemInstance adenatransfer = _target.transferItem("PayManufacture", _target.getInventory().getAdenaInstance().getObjectId(), _price, _player.getInventory(), _player);
-
- if (adenatransfer == null)
- {
- _target.sendPacket(SystemMessageId.YOU_NOT_ENOUGH_ADENA);
- abort();
- return;
- }
- }
-
- if ((_items = listItems(true)) == null) // this line actually takes materials from inventory
- { // handle possible cheaters here
- // (they click craft then try to get rid of items in order to get free craft)
- }
- else if (Rnd.get(100) < _recipeList.getSuccessRate())
- {
- rewardPlayer(); // and immediately puts created item in its place
- updateMakeInfo(true);
- }
- else
- {
- if (_target != _player)
- {
- SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.CREATION_OF_S2_FOR_C1_AT_S3_ADENA_FAILED);
- msg.addString(_target.getName());
- msg.addItemName(_recipeList.getItemId());
- msg.addItemNumber(_price);
- _player.sendPacket(msg);
-
- msg = SystemMessage.getSystemMessage(SystemMessageId.C1_FAILED_TO_CREATE_S2_FOR_S3_ADENA);
- msg.addString(_player.getName());
- msg.addItemName(_recipeList.getItemId());
- msg.addItemNumber(_price);
- _target.sendPacket(msg);
- }
- else
- {
- _target.sendPacket(SystemMessageId.ITEM_MIXING_FAILED);
- }
- updateMakeInfo(false);
- }
- // update load and mana bar of craft window
- updateCurMp();
- updateCurLoad();
- _activeMakers.remove(_player.getObjectId());
- _player.isInCraftMode(false);
- _target.sendPacket(new ItemList(_target, false));
- }
-
- private void updateMakeInfo(boolean success)
- {
- if (_target == _player)
- {
- _target.sendPacket(new RecipeItemMakeInfo(_recipeList.getId(), _target, success));
- }
- else
- {
- _target.sendPacket(new RecipeShopItemInfo(_player, _recipeList.getId()));
- }
- }
-
- private void updateCurLoad()
- {
- StatusUpdate su = new StatusUpdate(_target);
- su.addAttribute(StatusUpdate.CUR_LOAD, _target.getCurrentLoad());
- _target.sendPacket(su);
- }
-
- private void updateCurMp()
- {
- StatusUpdate su = new StatusUpdate(_target);
- su.addAttribute(StatusUpdate.CUR_MP, (int) _target.getCurrentMp());
- _target.sendPacket(su);
- }
-
- private void grabSomeItems()
- {
- int grabItems = _itemGrab;
- while ((grabItems > 0) && !_items.isEmpty())
- {
- TempItem item = _items.get(0);
-
- int count = item.getQuantity();
- if (count >= grabItems)
- {
- count = grabItems;
- }
-
- item.setQuantity(item.getQuantity() - count);
- if (item.getQuantity() <= 0)
- {
- _items.remove(0);
- }
- else
- {
- _items.set(0, item);
- }
-
- grabItems -= count;
-
- if (_target == _player)
- {
- SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S1_S2_EQUIPPED); // you equipped ...
- sm.addItemNumber(count);
- sm.addItemName(item.getItemId());
- _player.sendPacket(sm);
- }
- else
- {
- _target.sendMessage("Manufacturer " + _player.getName() + " used " + count + " " + item.getItemName());
- }
- }
- }
-
- // AltStatChange parameters make their effect here
- private void calculateAltStatChange()
- {
- _itemGrab = _skillLevel;
-
- for (L2RecipeStatInstance altStatChange : _recipeList.getAltStatChange())
- {
- if (altStatChange.getType() == L2RecipeStatInstance.StatType.XP)
- {
- _exp = altStatChange.getValue();
- }
- else if (altStatChange.getType() == L2RecipeStatInstance.StatType.SP)
- {
- _sp = altStatChange.getValue();
- }
- else if (altStatChange.getType() == L2RecipeStatInstance.StatType.GIM)
- {
- _itemGrab *= altStatChange.getValue();
- }
- }
- // determine number of creation passes needed
- _creationPasses = (_totalItems / _itemGrab) + ((_totalItems % _itemGrab) != 0 ? 1 : 0);
- if (_creationPasses < 1)
- {
- _creationPasses = 1;
- }
- }
-
- // StatUse
- private boolean calculateStatUse(boolean isWait, boolean isReduce)
- {
- boolean ret = true;
- for (L2RecipeStatInstance statUse : _recipeList.getStatUse())
- {
- double modifiedValue = statUse.getValue() / _creationPasses;
- if (statUse.getType() == L2RecipeStatInstance.StatType.HP)
- {
- // we do not want to kill the player, so its CurrentHP must be greater than the reduce value
- if (_player.getCurrentHp() <= modifiedValue)
- {
- // rest (wait for HP)
- if (Config.ALT_GAME_CREATION && isWait)
- {
- _player.sendPacket(new SetupGauge(0, _delay));
- ThreadPoolManager.getInstance().scheduleGeneral(this, 100 + _delay);
- }
- else
- {
- _target.sendPacket(SystemMessageId.NOT_ENOUGH_HP);
- abort();
- }
- ret = false;
- }
- else if (isReduce)
- {
- _player.reduceCurrentHp(modifiedValue, _player, _skill);
- }
- }
- else if (statUse.getType() == L2RecipeStatInstance.StatType.MP)
- {
- if (_player.getCurrentMp() < modifiedValue)
- {
- // rest (wait for MP)
- if (Config.ALT_GAME_CREATION && isWait)
- {
- _player.sendPacket(new SetupGauge(0, _delay));
- ThreadPoolManager.getInstance().scheduleGeneral(this, 100 + _delay);
- }
- else
- {
- _target.sendPacket(SystemMessageId.NOT_ENOUGH_MP);
- abort();
- }
- ret = false;
- }
- else if (isReduce)
- {
- _player.reduceCurrentMp(modifiedValue);
- }
- }
- else
- {
- // there is an unknown StatUse value
- _target.sendMessage("Recipe error!!!, please tell this to your GM.");
- ret = false;
- abort();
- }
- }
- return ret;
- }
-
- private List<TempItem> listItems(boolean remove)
- {
- L2RecipeInstance[] recipes = _recipeList.getRecipes();
- Inventory inv = _target.getInventory();
- List<TempItem> materials = new FastList<TempItem>();
- SystemMessage sm;
-
- for (L2RecipeInstance recipe : recipes)
- {
- int quantity = _recipeList.isConsumable() ? (int) (recipe.getQuantity() * Config.RATE_CONSUMABLE_COST) : recipe.getQuantity();
-
- if (quantity > 0)
- {
- L2ItemInstance item = inv.getItemByItemId(recipe.getItemId());
- long itemQuantityAmount = item == null ? 0 : item.getCount();
-
- // check materials
- if (itemQuantityAmount < quantity)
- {
- sm = SystemMessage.getSystemMessage(SystemMessageId.MISSING_S2_S1_TO_CREATE);
- sm.addItemName(recipe.getItemId());
- sm.addItemNumber(quantity - itemQuantityAmount);
- _target.sendPacket(sm);
-
- abort();
- return null;
- }
-
- // make new temporary object, just for counting purposes
-
- TempItem temp = new TempItem(item, quantity);
- materials.add(temp);
- }
- }
-
- if (remove)
- {
- for (TempItem tmp : materials)
- {
- inv.destroyItemByItemId("Manufacture", tmp.getItemId(), tmp.getQuantity(), _target, _player);
-
- if (tmp.getQuantity() > 1)
- {
- sm = SystemMessage.getSystemMessage(SystemMessageId.S2_S1_DISAPPEARED);
- sm.addItemName(tmp.getItemId());
- sm.addItemNumber(tmp.getQuantity());
- _target.sendPacket(sm);
- }
- else
- {
- sm = SystemMessage.getSystemMessage(SystemMessageId.S1_DISAPPEARED);
- sm.addItemName(tmp.getItemId());
- _target.sendPacket(sm);
- }
- }
- }
- return materials;
- }
-
- private void abort()
- {
- updateMakeInfo(false);
- _player.isInCraftMode(false);
- _activeMakers.remove(_player.getObjectId());
- }
-
- private void rewardPlayer()
- {
- int rareProdId = _recipeList.getRareItemId();
- int itemId = _recipeList.getItemId();
- int itemCount = _recipeList.getCount();
- L2Item template = ItemTable.getInstance().getTemplate(itemId);
-
- // check that the current recipe has a rare production or not
- if ((rareProdId != -1) && ((rareProdId == itemId) || Config.CRAFT_MASTERWORK))
- {
- if (Rnd.get(100) < _recipeList.getRarity())
- {
- itemId = rareProdId;
- itemCount = _recipeList.getRareCount();
- }
- }
-
- _target.getInventory().addItem("Manufacture", itemId, itemCount, _target, _player);
-
- // inform customer of earned item
- SystemMessage sm = null;
- if (_target != _player)
- {
- // inform manufacturer of earned profit
- if (itemCount == 1)
- {
- sm = SystemMessage.getSystemMessage(SystemMessageId.S2_CREATED_FOR_C1_FOR_S3_ADENA);
- sm.addString(_target.getName());
- sm.addItemName(itemId);
- sm.addItemNumber(_price);
- _player.sendPacket(sm);
-
- sm = SystemMessage.getSystemMessage(SystemMessageId.C1_CREATED_S2_FOR_S3_ADENA);
- sm.addString(_player.getName());
- sm.addItemName(itemId);
- sm.addItemNumber(_price);
- _target.sendPacket(sm);
- }
- else
- {
- sm = SystemMessage.getSystemMessage(SystemMessageId.S2_S3_S_CREATED_FOR_C1_FOR_S4_ADENA);
- sm.addString(_target.getName());
- sm.addNumber(itemCount);
- sm.addItemName(itemId);
- sm.addItemNumber(_price);
- _player.sendPacket(sm);
-
- sm = SystemMessage.getSystemMessage(SystemMessageId.C1_CREATED_S2_S3_S_FOR_S4_ADENA);
- sm.addString(_player.getName());
- sm.addNumber(itemCount);
- sm.addItemName(itemId);
- sm.addItemNumber(_price);
- _target.sendPacket(sm);
- }
- }
-
- if (itemCount > 1)
- {
- sm = SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S);
- sm.addItemName(itemId);
- sm.addItemNumber(itemCount);
- _target.sendPacket(sm);
- }
- else
- {
- sm = SystemMessage.getSystemMessage(SystemMessageId.EARNED_ITEM_S1);
- sm.addItemName(itemId);
- _target.sendPacket(sm);
- }
-
- if (Config.ALT_GAME_CREATION)
- {
- int recipeLevel = _recipeList.getLevel();
- if (_exp < 0)
- {
- _exp = template.getReferencePrice() * itemCount;
- _exp /= recipeLevel;
- }
- if (_sp < 0)
- {
- _sp = _exp / 10;
- }
- if (itemId == rareProdId)
- {
- _exp *= Config.ALT_GAME_CREATION_RARE_XPSP_RATE;
- _sp *= Config.ALT_GAME_CREATION_RARE_XPSP_RATE;
- }
-
- if (_exp < 0)
- {
- _exp = 0;
- }
- if (_sp < 0)
- {
- _sp = 0;
- }
-
- for (int i = _skillLevel; i > recipeLevel; i--)
- {
- _exp /= 4;
- _sp /= 4;
- }
-
- // Added multiplication of Creation speed with XP/SP gain
- // slower crafting -> more XP, faster crafting -> less XP
- // you can use ALT_GAME_CREATION_XP_RATE/SP to
- // modify XP/SP gained (default = 1)
-
- _player.addExpAndSp((int) _player.calcStat(Stats.EXPSP_RATE, _exp * Config.ALT_GAME_CREATION_XP_RATE * Config.ALT_GAME_CREATION_SPEED, null, null), (int) _player.calcStat(Stats.EXPSP_RATE, _sp * Config.ALT_GAME_CREATION_SP_RATE * Config.ALT_GAME_CREATION_SPEED, null, null));
- }
- updateMakeInfo(true); // success
- }
- }
-
- private L2RecipeList getValidRecipeList(L2PcInstance player, int id)
- {
- L2RecipeList recipeList = getRecipeList(id);
-
- if ((recipeList == null) || (recipeList.getRecipes().length == 0))
- {
- player.sendMessage("No recipe for: " + id);
- player.isInCraftMode(false);
- return null;
- }
- return recipeList;
- }
-
- private static class SingletonHolder
- {
- protected static final RecipeController _instance = new RecipeController();
- }
- }
|