rendered paste bodyIndex: config/altsettings.properties
===================================================================
--- config/altsettings.properties (revision 1682)
+++ config/altsettings.properties (working copy)
@@ -23,9 +23,13 @@
# - players get EXP/SP for crafting
AltGameCreation = False
-# time multiplyer - bigger number = slower crafting, default was 15 now is 10
-AltGameCreationSpeed = 10
+# time multiplier - bigger number ===> slower crafting but more XP/SP
+AltGameCreationSpeed = 1
+# Additional XP/SP rate multiplier (for increased XP/SP) default = 1
+AltGameCreationRateXp = 1
+AltGameCreationRateSp = 1
+
# Alternative skill learn rules:
# - all classes can learn all skills
# - skills of another class costs x2 SP
Index: net/sf/l2j/Config.java
===================================================================
--- net/sf/l2j/Config.java (revision 1682)
+++ net/sf/l2j/Config.java (working copy)
@@ -80,15 +80,21 @@
/** Character name template */
public static String CNAME_TEMPLATE;
-
+
/** Global chat state */
public static String DEFAULT_GLOBAL_CHAT;
/** For test servers - evrybody has admin rights */
public static boolean EVERYBODY_HAS_ADMIN_RIGHTS;
/** Alternative game crafting */
public static boolean ALT_GAME_CREATION;
- /** Alternative game crafting speed mutiplyer - default 10, bigger number -> slower */
- public static int ALT_GAME_CREATION_SPEED;
+ /** Alternative game crafting speed mutiplier - default 0 (fastest but still not instant) */
+ public static double ALT_GAME_CREATION_SPEED;
+ /** Alternative game crafting XP rate multiplier - default 1*/
+ public static double ALT_GAME_CREATION_XP_RATE;
+ /** Alternative game crafting SP rate multiplier - default 1*/
+ public static double ALT_GAME_CREATION_SP_RATE;
+
+
/** Alternative game skill learning */
public static boolean ALT_GAME_SKILL_LEARN;
/** Cancel ATTACK/cast by hit */
@@ -234,7 +240,7 @@
public static int PLAYER_RATE_DROP_ITEM;
public static int PLAYER_RATE_DROP_EQUIP;
public static int PLAYER_RATE_DROP_EQUIP_WEAPON;
-
+
/** Pet Rates (Multipliers) */
public static float PET_XP_RATE;
public static int PET_FOOD_RATE;
@@ -322,7 +328,7 @@
public static final String HEXID_FILE = "./config/hexid.txt";
public static final String COMMAND_PRIVILEGES_FILE = "./config/command-privileges.properties";
public static final String AI_FILE = "./config/ai.properties";
-
+
public static boolean CHECK_KNOWN;
public static int GAME_SERVER_LOGIN_PORT;
@@ -577,7 +583,7 @@
PLAYER_RATE_DROP_ITEM = Integer.parseInt(serverSettings.getProperty("PlayerRateDropItem", "70"));
PLAYER_RATE_DROP_EQUIP = Integer.parseInt(serverSettings.getProperty("PlayerRateDropEquip", "25"));
PLAYER_RATE_DROP_EQUIP_WEAPON = Integer.parseInt(serverSettings.getProperty("PlayerRateDropEquipWeapon", "5"));
-
+
PET_XP_RATE = Float.parseFloat(serverSettings.getProperty("PetXpRate", "1."));
PET_FOOD_RATE = Integer.parseInt(serverSettings.getProperty("PetFoodRate", "1"));
@@ -834,6 +840,7 @@
GM_NAME_COLOUR = Integer.decode("0x" + otherSettings.getProperty("GMNameColour", "00FF00"));
GM_STARTUP_INVISIBLE = Boolean.parseBoolean(otherSettings.getProperty("GMStartupInvisible", "True"));
GM_STARTUP_SILENCE = Boolean.parseBoolean(otherSettings.getProperty("GMStartupSilence", "True"));
+
}
catch (Exception e)
{
@@ -873,13 +880,15 @@
ALT_GAME_TIREDNESS = Boolean.parseBoolean(altSettings.getProperty("AltGameTiredness", "false"));
ALT_GAME_CREATION = Boolean.parseBoolean(altSettings.getProperty("AltGameCreation", "false"));
- ALT_GAME_CREATION_SPEED = Integer.parseInt(altSettings.getProperty("AltGameCreationSpeed", "10"));
+ ALT_GAME_CREATION_SPEED = Double.parseDouble(altSettings.getProperty("AltGameCreationSpeed", "1"));
+ ALT_GAME_CREATION_XP_RATE=Double.parseDouble(altSettings.getProperty("AltGameCreationXpRate", "1"));
+ ALT_GAME_CREATION_SP_RATE=Double.parseDouble(altSettings.getProperty("AltGameCreationSpRate", "1"));
ALT_GAME_SKILL_LEARN = Boolean.parseBoolean(altSettings.getProperty("AltGameSkillLearn", "false"));
ALT_GAME_CANCEL_BOW = altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("bow") || altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");
ALT_GAME_CANCEL_CAST = altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("cast") || altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");
ALT_GAME_SHIELD_BLOCKS = Boolean.parseBoolean(altSettings.getProperty("AltShieldBlocks", "false"));
ALT_GAME_DELEVEL = Boolean.parseBoolean(altSettings.getProperty("Delevel", "true"));
- ALT_GAME_MAGICFAILURES = Boolean.parseBoolean(altSettings.getProperty("MagicFailures", "false"));
+ ALT_GAME_MAGICFAILURES = Boolean.parseBoolean(altSettings.getProperty("MagicFailures", "false"));
ALT_GAME_MOB_ATTACK_AI = Boolean.parseBoolean(altSettings.getProperty("AltGameMobAttackAI", "false"));
ALT_GAME_SKILL_FORMULAS = altSettings.getProperty("AltGameSkillFormulas", "none");
ALT_GAME_EXPONENT_XP = Float.parseFloat(altSettings.getProperty("AltGameExponentXp", "0."));
@@ -1232,7 +1241,9 @@
// Alternative settings
else if (pName.equalsIgnoreCase("AltGameTiredness")) ALT_GAME_TIREDNESS = Boolean.valueOf(pValue);
else if (pName.equalsIgnoreCase("AltGameCreation")) ALT_GAME_CREATION = Boolean.valueOf(pValue);
- else if (pName.equalsIgnoreCase("AltGameCreationSpeed")) ALT_GAME_CREATION_SPEED = Integer.parseInt(pValue);
+ else if (pName.equalsIgnoreCase("AltGameCreationSpeed")) ALT_GAME_CREATION_SPEED = Double.parseDouble(pValue);
+ else if (pName.equalsIgnoreCase("AltGameCreationXpRate")) ALT_GAME_CREATION_XP_RATE = Double.parseDouble(pValue);
+ else if (pName.equalsIgnoreCase("AltGameCreationSpRate")) ALT_GAME_CREATION_SP_RATE = Double.parseDouble(pValue);
else if (pName.equalsIgnoreCase("AltGameSkillLearn")) ALT_GAME_SKILL_LEARN = Boolean.valueOf(pValue);
else if (pName.equalsIgnoreCase("AltGameCancelByHit"))
Index: net/sf/l2j/gameserver/RecipeController.java
===================================================================
--- net/sf/l2j/gameserver/RecipeController.java (revision 1682)
+++ net/sf/l2j/gameserver/RecipeController.java (working copy)
@@ -33,8 +33,6 @@
import javolution.util.FastList;
import javolution.util.FastMap;
import net.sf.l2j.Config;
-import net.sf.l2j.gameserver.ClientScheduler;
-import net.sf.l2j.gameserver.GameTimeController;
import net.sf.l2j.gameserver.lib.Rnd;
import net.sf.l2j.gameserver.model.Inventory;
import net.sf.l2j.gameserver.model.L2ItemInstance;
@@ -57,51 +55,49 @@
public class RecipeController
{
protected static Logger _log = Logger.getLogger(RecipeController.class.getName());
-
+
private static RecipeController _instance;
private Map<Integer, L2RecipeList> _lists;
protected static Map<L2PcInstance, RecipeItemMaker> activeMakers = Collections.synchronizedMap(new WeakHashMap<L2PcInstance, RecipeItemMaker>());
protected static final Random _rnd = new Random();
-
+
public static RecipeController getInstance()
{
return _instance == null ? _instance = new RecipeController() : _instance;
}
-
+
public RecipeController()
{
_lists = new FastMap<Integer, L2RecipeList>();
String line = null;
LineNumberReader lnr = null;
-
+
try
{
File recipesData = new File(Config.DATAPACK_ROOT, "data/recipes.csv");
lnr = new LineNumberReader(new BufferedReader(new FileReader(recipesData)));
-
+
while ((line = lnr.readLine()) != null)
{
if (line.trim().length() == 0 || line.startsWith("#"))
- {
continue;
- }
-
+
parseList(line);
-
+
}
_log.config("RecipeController: Loaded " + _lists.size() + " Recipes.");
}
catch (Exception e)
{
if (lnr != null)
- {
+
_log.log(Level.WARNING, "error while creating recipe controller in linenr: "
- + lnr.getLineNumber(), e);
- }
+ + lnr.getLineNumber(), e);
+
else
- {
+
_log.warning("No recipes were found in data folder");
- }
+
}
finally
{
@@ -114,17 +110,17 @@
}
}
}
-
+
public int getRecipesCount()
{
return _lists.size();
}
-
+
public L2RecipeList getRecipeList(int listId)
{
return _lists.get(listId);
}
-
+
public L2RecipeList getRecipeByItemId(int itemId)
{
for (int i = 0; i < _lists.size(); i++)
@@ -137,112 +133,118 @@
}
return null;
}
-
+
public synchronized void requestBookOpen(L2PcInstance player, boolean isDwarvenCraft)
{
RecipeItemMaker maker = null;
if (Config.ALT_GAME_CREATION) maker = activeMakers.get(player);
-
+
if (maker == null)
{
RecipeBookItemList response = new RecipeBookItemList(isDwarvenCraft, player.getMaxMp());
response.addRecipes(isDwarvenCraft ? player.getDwarvenRecipeBook()
- : player.getCommonRecipeBook());
+ : player.getCommonRecipeBook());
player.sendPacket(response);
return;
}
-
+
SystemMessage sm = new SystemMessage(SystemMessage.CANT_ALTER_RECIPEBOOK_WHILE_CRAFTING);
player.sendPacket(sm);
return;
}
-
+
public synchronized void requestMakeItemAbort(L2PcInstance player)
{
- activeMakers.remove(player);
+ if (activeMakers != null) activeMakers.remove(player);
}
-
+
public synchronized void requestManufactureItem(L2PcInstance manufacturer, int recipeListId,
- L2PcInstance player)
+ L2PcInstance player)
{
L2RecipeList recipeList = getValidRecipeList(player, recipeListId);
-
+
if (recipeList == null) return;
- manufacturer.isInCraftMode(true);
-
- if (!Config.ALT_GAME_CREATION)
+
+ RecipeItemMaker maker;
+
+ if (Config.ALT_GAME_CREATION && (maker = activeMakers.get(manufacturer)) != null) // check if busy
{
- new RecipeItemMaker(manufacturer, recipeList, player);
+ player.sendMessage("Manufacturer is busy, please try later.");
+ return;
}
- else
+
+ maker = new RecipeItemMaker(manufacturer, recipeList, player);
+ if (maker.isValid)
{
- RecipeItemMaker maker = activeMakers.get(manufacturer);
- if (maker != null)
+ if (Config.ALT_GAME_CREATION)
{
- player.sendMessage("Manufacturer is busy creating.");
- manufacturer.isInCraftMode(false);
- return;
+ activeMakers.put(manufacturer, maker);
+ ClientScheduler.scheduleEvent(maker, 100);
}
- maker = new RecipeItemMaker(manufacturer, recipeList, player);
- if (maker.isValid) activeMakers.put(manufacturer, maker);
+ else maker.run();
}
}
-
+
public synchronized void requestMakeItem(L2PcInstance player, int recipeListId)
{
L2RecipeList recipeList = getValidRecipeList(player, recipeListId);
-
- if (recipeList == null) return;
-
- player.isInCraftMode(true);
-
- if (!Config.ALT_GAME_CREATION)
+
+ if (recipeList == null)
{
- new RecipeItemMaker(player, recipeList, player);
+ _log.warning("recipelist == null");
+ return;
}
- else
+
+ RecipeItemMaker maker;
+
+ // check if already busy (possible in alt mode only)
+ if (Config.ALT_GAME_CREATION && ((maker = activeMakers.get(player)) != null))
{
- RecipeItemMaker maker = activeMakers.get(player);
- if (maker != null)
+ SystemMessage sm = new SystemMessage(614);
+ sm.addString("You are busy creating ");
+ sm.addItemName(recipeList.getItemId());
+ player.sendPacket(sm);
+ return;
+ }
+
+ maker = new RecipeItemMaker(player, recipeList, player);
+ if (maker.isValid)
+ {
+ if (Config.ALT_GAME_CREATION)
{
- SystemMessage sm = new SystemMessage(614);
- sm.addString("You are busy creating ");
- sm.addItemName(recipeList.getItemId());
- player.sendPacket(sm);
- player.isInCraftMode(false);
- return;
+ activeMakers.put(player, maker);
+ ClientScheduler.scheduleEvent(maker, 100);
}
- maker = new RecipeItemMaker(player, recipeList, player);
- if (maker.isValid) activeMakers.put(player, maker);
+ else maker.run();
}
}
-
+
private void parseList(String line)
{
try
{
StringTokenizer st = new StringTokenizer(line, ";");
List<L2RecipeInstance> recipePartList = new FastList<L2RecipeInstance>();
-
+
//we use common/dwarf for easy reading of the recipes.csv file
String recipeTypeString = st.nextToken();
-
- //now we parse the string into a boolean
+
+ // now parse the string into a boolean
boolean isDwarvenRecipe;
-
+
if (recipeTypeString.equalsIgnoreCase("dwarven")) isDwarvenRecipe = true;
else if (recipeTypeString.equalsIgnoreCase("common")) isDwarvenRecipe = false;
else
{ //prints a helpfull message
- _log.warning("Error parsing recipes.csv, unknow recipe type " + recipeTypeString);
+ _log.warning("Error parsing recipes.csv, unknown recipe type " + recipeTypeString);
return;
}
-
+
String recipeName = st.nextToken();
int id = Integer.parseInt(st.nextToken());
int recipeId = Integer.parseInt(st.nextToken());
int level = Integer.parseInt(st.nextToken());
-
+
//material
StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");
while (st2.hasMoreTokens())
@@ -253,18 +255,18 @@
L2RecipeInstance rp = new L2RecipeInstance(rpItemId, quantity);
recipePartList.add(rp);
}
-
+
int itemId = Integer.parseInt(st.nextToken());
int count = Integer.parseInt(st.nextToken());
-
+
//npc fee
/*String notdoneyet = */st.nextToken();
-
+
int mpCost = Integer.parseInt(st.nextToken());
int successRate = Integer.parseInt(st.nextToken());
-
+
L2RecipeList recipeList = new L2RecipeList(id, level, recipeId, recipeName, successRate,
- mpCost, itemId, count, isDwarvenRecipe);
+ mpCost, itemId, count, isDwarvenRecipe);
for (L2RecipeInstance recipePart : recipePartList)
{
recipeList.addRecipe(recipePart);
@@ -275,328 +277,490 @@
{
_log.severe("Exception in RecipeController.parseList() - " + e);
}
- ;
}
-
+
public class RecipeItemMaker implements Runnable
{
public boolean isValid;
- final List<L2ItemInstance> items;
- int materialsRefPrice;
- final L2PcInstance player;
+ List<TempItem> items = null;
+ final L2RecipeList recipeList;
+ final L2PcInstance player; // "crafter"
+ final L2PcInstance target; // "customer"
+ final L2Skill skill;
+ final int skillId;
+ final int skillLevel;
+ double creationPasses;
int price;
- final L2RecipeList recipeList;
- final L2PcInstance target;
- int timeReady;
int delay;
- int gameTicks;
int totalItems;
- int usedItems;
- int skillLevel;
+ int materialsRefPrice;
+ double manaRequired;
public RecipeItemMaker(L2PcInstance player, L2RecipeList recipeList, L2PcInstance target)
{
this.player = player;
this.target = target;
this.recipeList = recipeList;
- this.items = new FastList<L2ItemInstance>();
- this.isValid = false;
-
- skillLevel = recipeList.isDwarvenRecipe() ? player.getSkillLevel(L2Skill.SKILL_CREATE_DWARVEN)
- : player.getSkillLevel(L2Skill.SKILL_CREATE_COMMON);
-
- if (!validateSkillLevel()) return;
- if (!validateRecipeList()) return;
- if (!validateCustomerCanAfford(target,player)) return;
- if (!validateMaterials()) return;
- if (!validateMp()) return;
-
- isValid = true;
- updateTime();
- run();
- }
-
- private void finishCrafting()
- {
- player.reduceCurrentMp(recipeList.getMpCost());
-
- if (Rnd.get(100) < recipeList.getSuccessRate())
+
+ 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())
{
- if (target != player)
- {
- if (price > 0)
+ player.sendMessage("Dead persons can't craft.");
+ player.sendPacket(new ActionFailed());
+ abort();
+ return;
+ }
+
+ if (target.isAlikeDead())
+ {
+ target.sendMessage("Dead customers can't use manufacture.");
+ target.sendPacket(new ActionFailed());
+ abort();
+ return;
+ }
+
+ // validate recipe list
+ if ((recipeList == null) || (recipeList.getRecipes().length == 0))
+ {
+ player.sendMessage("No such recipe");
+ player.sendPacket(new ActionFailed());
+ abort();
+ return;
+ }
+
+ manaRequired = recipeList.getMpCost();
+
+ // validate skill level
+ if (recipeList.getLevel() > skillLevel)
+ {
+ player.sendMessage("Need skill level " + recipeList.getLevel());
+ player.sendPacket(new ActionFailed());
+ 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
{
- target.reduceAdena("Manufacture", price, player, false);
- player.addAdena("Manufacture", price, target, false);
+ price = temp.getCost();
+ if (target.getAdena() < price) // check price
+ {
+ target.sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA));
+ abort();
+ return;
+ }
+ break;
}
- updateCurLoad();
+ }
+
+ // make temporary items
+ if ((items = listItems(false)) == null)
+ {
+ abort();
+ return;
}
-
- RewardPlayer();
- updateMakeInfo(true); // success
+
+ // calculate reference price
+ for (TempItem i : items)
+ {
+ materialsRefPrice += i.getReferencePrice() * i.getQuantity();
+ totalItems += i.getQuantity();
}
- else
+ // initial mana check requires MP as written on recipe
+ if (player.getCurrentMp() < manaRequired)
{
- player.sendMessage("Item(s) failed to create");
- updateMakeInfo(false);
+ target.sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_MP));
+ abort();
+ return;
}
- activeMakers.remove(player);
+
+ // determine number of creation passes needed
+ // can "equip" skillLevel items each pass
+ creationPasses = (totalItems / skillLevel) + ((totalItems % skillLevel)!=0 ? 1 : 0);
+
+ if (Config.ALT_GAME_CREATION && creationPasses != 0) // update mana required to "per pass"
+ manaRequired /= creationPasses; // checks to validateMp() will only need portion of mp for one pass
+
+ updateMakeInfo(true); // attempt to update mana bar
+ updateCurMp();
+ updateCurLoad();
+
player.isInCraftMode(false);
-
- target.sendPacket(new ItemList(target, false));
+ isValid = true;
}
-
+
public void run()
{
- player.isInCraftMode(true);
- gameTicks = GameTimeController.getGameTicks();
- if (!validateCraftingEnabled() || !validateMp()) return;
+ if (!Config.IS_CRAFTING_ENABLED)
+ {
+ target.sendMessage("Crafting is currently disabled.");
+ abort();
+ return;
+ }
- updateTime();
+ if (player == null || target == null)
+ {
+ _log.warning("player or target == null (disconnected?), aborting");
+ abort();
+ return;
+ }
+ if (player.isOnline()==0 || target.isOnline()==0)
+ {
+ _log.warning("player or target is not online, aborting");
+ abort();
+ return;
+ }
+
+ if (Config.ALT_GAME_CREATION && activeMakers.get(player) == null)
+ {
+ player.sendMessage("Crafting aborted");
+ abort();
+ return;
+ }
+
+ // check mana
+ if (!validateMp()) return;
+
+ // divided by RATE_CONSUMABLES_COST to remove craft time increase on higher consumable rates
+ // to prevent slower crafting on higher consumable rates
+ delay = (int) (Config.ALT_GAME_CREATION_SPEED * player.getMReuseRate(skill)
+ * GameTimeController.TICKS_PER_SECOND / Config.RATE_CONSUMABLE_COST)
+ * GameTimeController.MILLIS_IN_TICK;
+
if (Config.ALT_GAME_CREATION && !items.isEmpty())
{
- player.reduceCurrentMp(recipeList.getMpCost()); // use some mp
+ player.reduceCurrentMp(manaRequired); // use some mp
grabSomeItems(); // grab (equip) some more items with a nice msg to player
-
- MagicSkillUser msk = new MagicSkillUser(
- player,
- recipeList.isDwarvenRecipe() ? L2Skill.SKILL_CREATE_DWARVEN
- : L2Skill.SKILL_CREATE_COMMON,
- skillLevel, delay, 0);
-
+
+ // FIXME: please fix this packet to show crafting animation (somebody)
+ MagicSkillUser msk = new MagicSkillUser(player, skillId, skillLevel, delay, 0);
player.broadcastPacket(msk);
-
+
player.sendPacket(new SetupGauge(0, delay));
+
+ ClientScheduler.scheduleEvent(this, 100 + delay);
+ _log.warning(".");
+ }
+ else
+ // finish crafting
+ {
+ _log.warning("finishcrafting entered");
+ if(!Config.ALT_GAME_CREATION) player.reduceCurrentMp(manaRequired);
+
+ // 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 || adenatransfer.getCount()!=price)
+ {
+ target.sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA));
+ abort();
+ return;
+ }
+ }
- ClientScheduler.getInstance().scheduleLow(this, 100 + delay);
+ _log.warning("calling listItems(true)");
+ if ((items = listItems(true)) == null) // this line actually takes materials from inventory
+ {
+ _log.warning("Could not take materials from inventory: " + target);
+ target.sendMessage("Could not take materials from inventory");
+ }
+ else if (Rnd.get(100) < recipeList.getSuccessRate())
+ {
+ RewardPlayer(); // and this one immediately puts created item in its place
+ updateMakeInfo(true);
+ }
+ else
+ {
+ player.sendMessage("Item(s) failed to create");
+ updateMakeInfo(false);
+ }
+ _log.warning("before updates and finish");
+ // update load and mana bar of craft window
+ updateCurMp();
+ updateCurLoad();
+ activeMakers.remove(player);
+ player.isInCraftMode(false);
+ target.sendPacket(new ItemList(target, false));
}
- else finishCrafting();
-
- // update load and mana bar of craft window
- updateMakeInfo(true);
- updateCurMp();
- updateCurLoad();
}
-
- private void updateTime()
- {
- // divided by RATE_CONSUMABLES_COST to remove craft time increase on higher consumable rates (more mats consumed -> more time)
- timeReady = gameTicks
- + (int) (Config.ALT_GAME_CREATION_SPEED
- * player.getMReuseRate(player.getKnownSkill(172))
- * GameTimeController.TICKS_PER_SECOND / Config.RATE_CONSUMABLE_COST);
-
- delay = (timeReady - gameTicks) * GameTimeController.MILLIS_IN_TICK;
- }
-
+
private void updateMakeInfo(boolean success)
{
- if (target == player) target.sendPacket(new RecipeItemMakeInfo(recipeList.getId(), target, success));
+ if (target == player) target.sendPacket(new RecipeItemMakeInfo(recipeList.getId(), target,
+ success));
else target.sendPacket(new RecipeShopItemInfo(player.getObjectId(), recipeList.getId()));
}
-
+
private void updateCurLoad()
{
StatusUpdate su = new StatusUpdate(target.getObjectId());
su.addAttribute(StatusUpdate.CUR_LOAD, target.getCurrentLoad());
target.sendPacket(su);
}
-
+
private void updateCurMp()
{
-
+
StatusUpdate su = new StatusUpdate(target.getObjectId());
su.addAttribute(StatusUpdate.CUR_MP, (int) target.getCurrentMp());
target.sendPacket(su);
}
-
+
private void grabSomeItems()
{
- int numItems = player.getSkillLevel(172);
+ int numItems = skillLevel;
+
while (numItems > 0 && !items.isEmpty())
{
- L2ItemInstance item = items.get(0);
-
- int count = item.getCount();
+ TempItem item = items.get(0);
+
+ int count = item.getQuantity();
if (count >= numItems) count = numItems;
-
- item.setCount(item.getCount() - count);
- if (item.getCount() <= 0) items.remove(0);
-
+
+ item.setQuantity(item.getQuantity() - count);
+ if (item.getQuantity() <= 0) items.remove(0);
+ else items.set(0, item);
+
numItems -= count;
- usedItems += count;
-
- SystemMessage sm = new SystemMessage(368); // you equipped ...
- sm.addNumber(count);
- sm.addItemName(item.getItemId());
- if (target == null) player.sendPacket(sm);
- else target.sendPacket(sm);
+
+ if (target == player)
+ {
+ SystemMessage sm = new SystemMessage(368); // you equipped ...
+ sm.addNumber(count);
+ sm.addItemName(item.getItemId());
+ player.sendPacket(sm);
+ }
+ else target.sendMessage("Manufacturer " + player.getName() + " used " + count + " "
+ + item.getItemName());
}
}
-
- private boolean validateCraftingEnabled()
+
+ private boolean validateMp()
{
- if (!Config.IS_CRAFTING_ENABLED)
+ if (player.getCurrentMp() < manaRequired)
{
- target.sendMessage("Crafting is currently disabled.");
- player.isInCraftMode(false);
- activeMakers.remove(player);
- updateMakeInfo(false);
- return false;
- }
- return true;
- }
-
- private boolean validateCustomerCanAfford(L2PcInstance customer, L2PcInstance manufacturer)
- {
- if(customer==manufacturer) return true;
- for (L2ManufactureItem temp : manufacturer.getCreateList().getList())
- if (temp.getRecipeId() == recipeList.getId()) // find recipe for item we want manufactured
+ // rest (wait for MP)
+ if (Config.ALT_GAME_CREATION)
{
- int price = temp.getCost();
- if (customer.getAdena() < price) // check price
- {
- customer.sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA));
- manufacturer.isInCraftMode(false);
- activeMakers.remove(manufacturer);
- return false;
- }
- break;
+ player.sendPacket(new SetupGauge(0, delay));
+ ClientScheduler.scheduleEvent(this, 100 + delay);
}
- return true;
- }
- private boolean validateMp()
- {
- if (player.getCurrentMp() < recipeList.getMpCost())
- {
- target.sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_MP));
- player.isInCraftMode(false);
- activeMakers.remove(player);
- updateMakeInfo(false);
+ else
+ // no rest - report no mana
+ {
+ target.sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_MP));
+ abort(); // false == don't resume
+ }
return false;
}
return true;
}
-
- private boolean validateMaterials()
+
+ private List<TempItem> listItems(boolean remove)
{
L2RecipeInstance[] recipes = recipeList.getRecipes();
-
Inventory inv = target.getInventory();
-
+ List<TempItem> materials = new FastList<TempItem>();
+
for (L2RecipeInstance recipe : recipes)
{
- if (recipe.getQuantity() != 0)
+ int quantity = recipeList.isConsumable() ? (int) (recipe.getQuantity() * Config.RATE_CONSUMABLE_COST)
+ : (int) recipe.getQuantity();
+
+ if (quantity > 0)
{
- L2ItemInstance invItem = inv.getItemByItemId(recipe.getItemId());
- if ((invItem == null)
- || ((recipeList.isConsumable() ? (int) (recipe.getQuantity() * Config.RATE_CONSUMABLE_COST)
- : recipe.getQuantity()) > invItem.getCount()))
+ L2ItemInstance item = inv.getItemByItemId(recipe.getItemId());
+
+ // now we verify that we have enough materials
+ if (item==null || item.getCount() < quantity)
{
target.sendMessage("You dont have the right elements for making this item"
- + ((recipeList.isConsumable() && Config.RATE_CONSUMABLE_COST != 1) ? ".\nDue to server rates you need "
- + Config.RATE_CONSUMABLE_COST
- + "x more material than listed in recipe"
- : ""));
- player.isInCraftMode(false);
- activeMakers.remove(player);
- updateMakeInfo(false);
- return false;
+ + ((recipeList.isConsumable() && Config.RATE_CONSUMABLE_COST != 1) ? ".\nDue to server rates you need "
+ + Config.RATE_CONSUMABLE_COST
+ + "x more material than listed in recipe"
+ : ""));
+ abort();
+ return null;
}
+
+ // make new temporary object, just for counting puroses, real item modification only
+ // on finishCrafting() so we minimize risk of losing items
+
+ TempItem temp = new TempItem(item, quantity);
+ materials.add(temp);
}
}
- for (L2RecipeInstance recipe : recipes)
+ if (remove)
{
- if (recipe.getQuantity() != 0)
- {
- L2ItemInstance invItem = inv.getItemByItemId(recipe.getItemId());
- invItem = inv.dropItem(
- "Manufacture",
- invItem.getObjectId(),
- recipeList.isConsumable() ? (int) (recipe.getQuantity() * Config.RATE_CONSUMABLE_COST)
- : recipe.getQuantity(), target,
- player);
- items.add(invItem);
- materialsRefPrice += invItem.getReferencePrice() * invItem.getCount();
- totalItems += invItem.getCount();
- }
- }
-
- return true;
+ _log.warning("item removal requested: ");
+ for(TempItem tmp : materials)
+ {
+ _log.warning("removed "+tmp.getQuantity()+" "+tmp.getItemName()+" from inventory");
+ inv.destroyItemByItemId("Manufacture", tmp.getItemId(), tmp.getQuantity(), target,
+ player);
+ }
+ }
+ return materials;
}
-
- private boolean validateSkillLevel()
+
+ private void abort()
{
- if (recipeList.getLevel() > skillLevel)
+ updateMakeInfo(false);
+ player.isInCraftMode(false);
+ activeMakers.remove(player);
+ }
+
+ /**
+ * TODO: This class should be in some other file, but I don't know where
+ *
+ * Class explanation:
+ * Use it for item counting or checking purposes. Any place you don't want to touch inventory
+ * class contains itemId, quantity, ownerId, referencePrice, but not objectId
+ */
+ private class TempItem
+ { // no object id stored, this will be only "list" of items with it's owner
+ private int _itemId;
+ private int _quantity;
+ private int _ownerId;
+ private int _referencePrice;
+ private String _itemName;
+
+ /**
+ * @param item
+ * @param quantity of that item
+ */
+ public TempItem(L2ItemInstance item, int quantity)
{
- player.sendMessage("Need skill level " + recipeList.getLevel());
- player.sendPacket(new ActionFailed());
- player.isInCraftMode(false);
- activeMakers.remove(player);
- updateMakeInfo(false);
- return false;
+ super();
+ _itemId = item.getItemId();
+ _quantity = quantity;
+ _ownerId = item.getOwnerId();
+ _itemName = item.getItem().getName();
+ _referencePrice = item.getReferencePrice();
}
- return true;
- }
-
- private boolean validateRecipeList()
- {
- if ((recipeList == null) || (recipeList.getRecipes().length == 0))
+
+ /**
+ * @return Returns the quantity.
+ */
+ public int getQuantity()
{
- player.sendMessage("No such recipe");
- player.isInCraftMode(false);
- activeMakers.remove(player);
- updateMakeInfo(false);
- return false;
+ return _quantity;
}
- return true;
+
+ /**
+ * @param quantity The quantity to set.
+ */
+ public void setQuantity(int quantity)
+ {
+ _quantity = quantity;
+ }
+
+ public int getReferencePrice()
+ {
+ return _referencePrice;
+ }
+
+ /**
+ * @return Returns the itemId.
+ */
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ /**
+ * @return Returns the ownerId.
+ */
+ public int getOwnerId()
+ {
+ return _ownerId;
+ }
+
+ /**
+ * @return Returns the itemName.
+ */
+ public String getItemName()
+ {
+ return _itemName;
+ }
}
-
+
private void RewardPlayer()
{
int itemId = recipeList.getItemId();
int itemCount = recipeList.getCount();
-
+
L2ItemInstance createdItem = target.getInventory().addItem("Manufacture", itemId, itemCount,
- target, player);
+ target, player);
+
+ // inform customer of earned item
SystemMessage sm = new SystemMessage(SystemMessage.EARNED_ITEM);
sm.addItemName(itemId);
sm.addNumber(itemCount);
target.sendPacket(sm);
-
+
+ if (target != player)
+ {
+ // inform manufacturer of earned profit
+ sm = new SystemMessage(SystemMessage.EARNED_ADENA);
+ sm.addNumber(price);
+ player.sendPacket(sm);
+ }
+
if (Config.ALT_GAME_CREATION)
{
int recipeLevel = recipeList.getLevel();
int exp = createdItem.getReferencePrice() * itemCount;
// one variation
- // exp -= materialsRefPrice;
+ // exp -= materialsRefPrice; // mat. ref. price is not accurate so other method is better
+
if (exp < 0) exp = 0;
// another variation
exp /= recipeLevel;
- for (int i = skillLevel; i > recipeLevel; i--) exp /= 4;
+ for (int i = skillLevel; i > recipeLevel; i--)
+ exp /= 4;
int sp = exp / 10;
- player.addExpAndSp((int) player.calcStat(Stats.EXPSP_RATE, exp * Config.RATE_XP, null,
- null),
- (int) player.calcStat(Stats.EXPSP_RATE, sp * Config.RATE_SP, null,
- null));
-
- sm = new SystemMessage(SystemMessage.YOU_EARNED_S1_EXP_AND_S2_SP);
- sm.addNumber((int) player.calcStat(Stats.EXPSP_RATE, exp * Config.RATE_XP, null, null));
- sm.addNumber((int) player.calcStat(Stats.EXPSP_RATE, sp * Config.RATE_SP, null, null));
- player.sendPacket(sm);
+
+ // FIXME: Added multiplication of Creation speed with XP/SP gain
+ // slower crafting -> more XP, faster crafting -> less XP
+ // admins: find balance you like ... you can use ALT_GAME_CREATION_RATE_XP/SP to
+ // compensate XP/SP (default = 1)
+ // goal is to make ALT_GAME_CREATION
+ // a bit slower, bit more interesting, and give some xp/sp but not too much
+
+ 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 - 1);
-
+
if ((recipeList == null) || (recipeList.getRecipes().length == 0))
{
player.sendMessage("No recipe for: " + id);
@@ -604,8 +768,5 @@
return null;
}
return recipeList;
- };
-
-
+ }
}
-