Recipes rework.

Adapted from: L2jUnity free files.
This commit is contained in:
MobiusDev 2017-11-21 04:25:11 +00:00
parent 6ccc5c8938
commit 7e1b0b4009
67 changed files with 32555 additions and 19075 deletions

File diff suppressed because it is too large Load Diff

View File

@ -90,12 +90,16 @@ public final class EffectMasterHandler
EffectHandler.getInstance().registerHandler("CpHealOverTime", CpHealOverTime::new);
EffectHandler.getInstance().registerHandler("CpHealPercent", CpHealPercent::new);
EffectHandler.getInstance().registerHandler("CpRegen", CpRegen::new);
EffectHandler.getInstance().registerHandler("CraftingCritical", CraftingCritical::new);
EffectHandler.getInstance().registerHandler("CreateCommonItem", CreateCommonItem::new);
EffectHandler.getInstance().registerHandler("CreateItem", CreateItem::new);
EffectHandler.getInstance().registerHandler("CreateItemRandom", CreateItemRandom::new);
EffectHandler.getInstance().registerHandler("CriticalDamage", CriticalDamage::new);
EffectHandler.getInstance().registerHandler("CriticalDamagePosition", CriticalDamagePosition::new);
EffectHandler.getInstance().registerHandler("CriticalRate", CriticalRate::new);
EffectHandler.getInstance().registerHandler("CriticalRatePositionBonus", CriticalRatePositionBonus::new);
EffectHandler.getInstance().registerHandler("CrystalGradeModify", CrystalGradeModify::new);
EffectHandler.getInstance().registerHandler("Crystallize", Crystallize::new);
EffectHandler.getInstance().registerHandler("CubicMastery", CubicMastery::new);
EffectHandler.getInstance().registerHandler("DamageBlock", DamageBlock::new);
EffectHandler.getInstance().registerHandler("DamageShield", DamageShield::new);
@ -265,6 +269,7 @@ public final class EffectMasterHandler
EffectHandler.getInstance().registerHandler("ReflectSkill", ReflectSkill::new);
EffectHandler.getInstance().registerHandler("RefuelAirship", RefuelAirship::new);
EffectHandler.getInstance().registerHandler("Relax", Relax::new);
EffectHandler.getInstance().registerHandler("RemoveEquipPenalty", RemoveEquipPenalty::new);
EffectHandler.getInstance().registerHandler("ResetInstanceEntry", ResetInstanceEntry::new);
EffectHandler.getInstance().registerHandler("ResistAbnormalByCategory", ResistAbnormalByCategory::new);
EffectHandler.getInstance().registerHandler("ResistDDMagic", ResistDDMagic::new);

View File

@ -1,48 +1,31 @@
/*
* 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 com.l2jmobius.gameserver.data.xml.impl.RecipeData;
public class L2ManufactureItem
{
private final int _recipeId;
private final long _cost;
private final boolean _isDwarven;
public L2ManufactureItem(int recipeId, long cost)
{
_recipeId = recipeId;
_cost = cost;
_isDwarven = RecipeData.getInstance().getRecipeList(_recipeId).isDwarvenRecipe();
}
public int getRecipeId()
{
return _recipeId;
}
public long getCost()
{
return _cost;
}
public boolean isDwarven()
{
return _isDwarven;
}
}
/*
* 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 handlers.effecthandlers;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.stats.Stats;
/**
* @author Nik
*/
public class CraftingCritical extends AbstractStatAddEffect
{
public CraftingCritical(StatsSet params)
{
super(params, Stats.CRAFTING_CRITICAL);
}
}

View File

@ -0,0 +1,64 @@
/*
* 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 handlers.effecthandlers;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.effects.AbstractEffect;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
/**
* An effect that allows the player to create common recipe items up to a certain level.
* @author Nik
*/
public final class CreateCommonItem extends AbstractEffect
{
private final int _recipeLevel;
public CreateCommonItem(StatsSet params)
{
_recipeLevel = params.getInt("value");
}
@Override
public boolean canStart(BuffInfo info)
{
return info.getEffected().isPlayer();
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
final L2PcInstance player = effected.getActingPlayer();
if (player != null)
{
player.setCreateCommonItemLevel(_recipeLevel);
}
}
@Override
public void onExit(BuffInfo info)
{
final L2PcInstance player = info.getEffected().getActingPlayer();
if (player != null)
{
player.setCreateCommonItemLevel(0);
}
}
}

View File

@ -0,0 +1,64 @@
/*
* 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 handlers.effecthandlers;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.effects.AbstractEffect;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
/**
* An effect that allows the player to create dwarven recipe items up to a certain level.
* @author Nik
*/
public final class CreateItem extends AbstractEffect
{
private final int _recipeLevel;
public CreateItem(StatsSet params)
{
_recipeLevel = params.getInt("value");
}
@Override
public boolean canStart(BuffInfo info)
{
return info.getEffected().isPlayer();
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
final L2PcInstance player = effected.getActingPlayer();
if (player != null)
{
player.setCreateItemLevel(_recipeLevel);
}
}
@Override
public void onExit(BuffInfo info)
{
final L2PcInstance player = info.getEffected().getActingPlayer();
if (player != null)
{
player.setCreateItemLevel(0);
}
}
}

View File

@ -29,11 +29,11 @@ import com.l2jmobius.gameserver.model.skills.Skill;
*/
public final class CrystalGradeModify extends AbstractEffect
{
private final int _grade;
private final int _amount;
public CrystalGradeModify(StatsSet params)
{
_grade = params.getInt("grade", 0);
_amount = params.getInt("_amount", 0);
}
@Override
@ -45,7 +45,7 @@ public final class CrystalGradeModify extends AbstractEffect
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
effected.getActingPlayer().setExpertisePenaltyBonus(_grade);
effected.getActingPlayer().setExpertisePenaltyBonus(_amount);
}
@Override

View File

@ -0,0 +1,65 @@
/*
* 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 handlers.effecthandlers;
import com.l2jmobius.gameserver.enums.ItemGrade;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.effects.AbstractEffect;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
/**
* An effect that allows the player to crystallize items up to a certain grade.
* @author Nik
*/
public final class Crystallize extends AbstractEffect
{
private final ItemGrade _grade;
public Crystallize(StatsSet params)
{
_grade = params.getEnum("grade", ItemGrade.class);
}
@Override
public boolean canStart(BuffInfo info)
{
return info.getEffected().isPlayer();
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
final L2PcInstance player = effected.getActingPlayer();
if (player != null)
{
player.setCrystallizeGrade(_grade);
}
}
@Override
public void onExit(BuffInfo info)
{
final L2PcInstance player = info.getEffected().getActingPlayer();
if (player != null)
{
player.setCrystallizeGrade(null);
}
}
}

View File

@ -16,7 +16,6 @@
*/
package handlers.effecthandlers;
import com.l2jmobius.gameserver.RecipeController;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character;
@ -25,6 +24,7 @@ import com.l2jmobius.gameserver.model.effects.AbstractEffect;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.RecipeBookItemList;
/**
* Open Common Recipe Book effect implementation.
@ -45,18 +45,24 @@ public final class OpenCommonRecipeBook extends AbstractEffect
@Override
public void instant(L2Character effector, L2Character effected, Skill skill, L2ItemInstance item)
{
if (!effector.isPlayer())
final L2PcInstance casterPlayer = effector.getActingPlayer();
if (casterPlayer == null)
{
return;
}
final L2PcInstance player = effector.getActingPlayer();
if (player.getPrivateStoreType() != PrivateStoreType.NONE)
if (casterPlayer.getPrivateStoreType() == PrivateStoreType.MANUFACTURE)
{
player.sendPacket(SystemMessageId.ITEM_CREATION_IS_NOT_POSSIBLE_WHILE_ENGAGED_IN_A_TRADE);
casterPlayer.sendPacket(SystemMessageId.YOU_MAY_NOT_ALTER_YOUR_RECIPE_BOOK_WHILE_ENGAGED_IN_MANUFACTURING);
return;
}
RecipeController.getInstance().requestBookOpen(player, false);
if (casterPlayer.isProcessingTransaction())
{
casterPlayer.sendPacket(SystemMessageId.ITEM_CREATION_IS_NOT_POSSIBLE_WHILE_ENGAGED_IN_A_TRADE);
return;
}
casterPlayer.sendPacket(new RecipeBookItemList(casterPlayer, false));
}
}

View File

@ -16,7 +16,6 @@
*/
package handlers.effecthandlers;
import com.l2jmobius.gameserver.RecipeController;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character;
@ -25,6 +24,7 @@ import com.l2jmobius.gameserver.model.effects.AbstractEffect;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.RecipeBookItemList;
/**
* Open Dwarf Recipe Book effect implementation.
@ -45,18 +45,24 @@ public final class OpenDwarfRecipeBook extends AbstractEffect
@Override
public void instant(L2Character effector, L2Character effected, Skill skill, L2ItemInstance item)
{
if (!effector.isPlayer())
final L2PcInstance casterPlayer = effector.getActingPlayer();
if (casterPlayer == null)
{
return;
}
final L2PcInstance player = effector.getActingPlayer();
if (player.getPrivateStoreType() != PrivateStoreType.NONE)
if (casterPlayer.getPrivateStoreType() == PrivateStoreType.MANUFACTURE)
{
player.sendPacket(SystemMessageId.ITEM_CREATION_IS_NOT_POSSIBLE_WHILE_ENGAGED_IN_A_TRADE);
casterPlayer.sendPacket(SystemMessageId.YOU_MAY_NOT_ALTER_YOUR_RECIPE_BOOK_WHILE_ENGAGED_IN_MANUFACTURING);
return;
}
RecipeController.getInstance().requestBookOpen(player, true);
if (casterPlayer.isProcessingTransaction())
{
casterPlayer.sendPacket(SystemMessageId.ITEM_CREATION_IS_NOT_POSSIBLE_WHILE_ENGAGED_IN_A_TRADE);
return;
}
casterPlayer.sendPacket(new RecipeBookItemList(casterPlayer, true));
}
}

View File

@ -0,0 +1,65 @@
/*
* 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 handlers.effecthandlers;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.effects.AbstractEffect;
import com.l2jmobius.gameserver.model.items.type.CrystalType;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
/**
* An effect that removes equipment grade penalty. Its the base effect for the grade penalty mechanics.
* @author Nik
*/
public final class RemoveEquipPenalty extends AbstractEffect
{
private final CrystalType _grade;
public RemoveEquipPenalty(StatsSet params)
{
_grade = params.getEnum("grade", CrystalType.class);
}
@Override
public boolean canStart(BuffInfo info)
{
return info.getEffected().isPlayer();
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
final L2PcInstance player = effected.getActingPlayer();
if (player != null)
{
player.setExpertiseLevel(_grade);
}
}
@Override
public void onExit(BuffInfo info)
{
final L2PcInstance player = info.getEffected().getActingPlayer();
if (player != null)
{
player.setExpertiseLevel(null);
}
}
}

View File

@ -42,7 +42,7 @@ public class CharmOfCourage implements IItemHandler
final L2PcInstance activeChar = playable.getActingPlayer();
int level = activeChar.getLevel();
final int itemLevel = item.getItem().getCrystalType().getId();
final int itemLevel = item.getItem().getCrystalType().getLevel();
if (level < 20)
{

View File

@ -18,9 +18,9 @@ package handlers.itemhandlers;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.handler.IItemHandler;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.model.actor.L2Playable;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
@ -40,15 +40,16 @@ public class Recipes implements IItemHandler
}
final L2PcInstance activeChar = playable.getActingPlayer();
if (activeChar.isInCraftMode())
if (activeChar.isCrafting())
{
activeChar.sendPacket(SystemMessageId.YOU_MAY_NOT_ALTER_YOUR_RECIPE_BOOK_WHILE_ENGAGED_IN_MANUFACTURING);
return false;
}
final L2RecipeList rp = RecipeData.getInstance().getRecipeByItemId(item.getId());
final RecipeHolder rp = RecipeData.getInstance().getRecipeByRecipeItemId(item.getId());
if (rp == null)
{
activeChar.sendPacket(SystemMessageId.THE_RECIPE_IS_INCORRECT);
return false;
}
@ -63,15 +64,15 @@ public class Recipes implements IItemHandler
boolean recipeLimit = false;
if (rp.isDwarvenRecipe())
{
canCraft = activeChar.hasDwarvenCraft();
recipeLevel = (rp.getLevel() > activeChar.getDwarvenCraft());
recipeLimit = (activeChar.getDwarvenRecipeBook().length >= activeChar.getDwarfRecipeLimit());
canCraft = activeChar.getCreateItemLevel() > 0;
recipeLevel = (rp.getLevel() > activeChar.getCreateItemLevel());
recipeLimit = (activeChar.getDwarvenRecipeBook().size() >= activeChar.getDwarfRecipeLimit());
}
else
{
canCraft = activeChar.hasCommonCraft();
recipeLevel = (rp.getLevel() > activeChar.getCommonCraft());
recipeLimit = (activeChar.getCommonRecipeBook().length >= activeChar.getCommonRecipeLimit());
canCraft = activeChar.getCreateCommonItemLevel() > 0;
recipeLevel = (rp.getLevel() > activeChar.getCreateCommonItemLevel());
recipeLimit = (activeChar.getCommonRecipeBook().size() >= activeChar.getCommonRecipeLimit());
}
if (!canCraft)

View File

@ -119,7 +119,7 @@ public final class SocialAction implements IPlayerActionHandler
}
SystemMessage sm;
if (player.isInStoreMode() || player.isInCraftMode())
if (player.isInStoreMode() || player.isCrafting())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_PRIVATE_STORE_MODE_OR_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(player);
@ -198,7 +198,7 @@ public final class SocialAction implements IPlayerActionHandler
// Checks for partner.
final L2PcInstance partner = target.getActingPlayer();
if (partner.isInStoreMode() || partner.isInCraftMode())
if (partner.isInStoreMode() || partner.isCrafting())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_PRIVATE_STORE_MODE_OR_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);

View File

@ -2727,6 +2727,27 @@
</magicLvl>
<operateType>P</operateType>
<magicCriticalRate>5</magicCriticalRate>
<effects>
<effect name="CreateItem">
<value>
<value level="1">1</value>
<value level="2">2</value>
<value level="3">3</value>
<value level="4">4</value>
<value level="5">5</value>
<value level="6">6</value>
<value level="7">7</value>
<value level="8">8</value>
<value level="9">9</value>
<value level="10">10</value>
<value level="11">11</value>
<value level="12">12</value>
<value level="13">13</value>
<value level="14">14</value>
<value level="15">15</value>
</value>
</effect>
</effects>
</skill>
<skill id="173" toLevel="2" name="Acrobatics">
<!-- Confirmed CT2.5 -->

View File

@ -2434,6 +2434,22 @@
</magicLvl>
<operateType>P</operateType>
<magicCriticalRate>5</magicCriticalRate>
<effects>
<effect name="RemoveEquipPenalty">
<grade>
<value level="1">D</value>
<value level="2">C</value>
<value level="3">B</value>
<value level="4">A</value>
<value level="5">S</value>
<value level="6">S80</value>
<value level="7">S80</value>
<value level="8">R</value>
<value level="9">R95</value>
<value level="10">R99</value>
</grade>
</effect>
</effects>
</skill>
<skill id="244" toLevel="3" name="Armor Mastery">
<!-- Confirmed CT2.5 -->
@ -2615,6 +2631,18 @@
</magicLvl>
<operateType>P</operateType>
<magicCriticalRate>5</magicCriticalRate>
<effects>
<effect name="Crystallize">
<grade>
<value level="1">D</value>
<value level="2">C</value>
<value level="3">B</value>
<value level="4">A</value>
<value level="5">S</value>
<value level="6">R</value>
</grade>
</effect>
</effects>
</skill>
<skill id="249" toLevel="42" name="Weapon Mastery">
<!-- Confirmed CT2.5 -->

View File

@ -666,6 +666,22 @@
</magicLvl>
<operateType>P</operateType>
<magicCriticalRate>5</magicCriticalRate>
<effects>
<effect name="CreateCommonItem">
<value>
<value level="1">1</value>
<value level="2">2</value>
<value level="3">3</value>
<value level="4">4</value>
<value level="5">5</value>
<value level="6">6</value>
<value level="7">7</value>
<value level="8">8</value>
<value level="9">9</value>
<value level="10">10</value>
</value>
</effect>
</effects>
</skill>
<skill id="1321" toLevel="1" name="Dwarven Craft">
<!-- Confirmed CT2.5 -->

View File

@ -509,10 +509,25 @@
</effects>
</skill>
<skill id="10312" toLevel="4" name="Crafting Mastery">
<!-- AUTO GENERATED SKILL -->
<!-- There is a small chance that the item quantity will double upon crafting. Critical level 1. -->
<icon>icon.skill10312</icon>
<magicLvl>
<value level="1">85</value>
<value level="2">90</value>
<value level="3">95</value>
<value level="4">99</value>
</magicLvl>
<operateType>P</operateType>
<effects>
<effect name="CraftingCritical">
<amount>
<value level="1">2.4</value>
<value level="2">3.8</value>
<value level="3">4.2</value>
<value level="4">5.4</value>
</amount>
</effect>
</effects>
</skill>
<skill id="10313" toLevel="4" name="Infinite Rush">
<!-- Rush toward the frontal enemies to inflict Shock for 9 sec. Requires a sword, blunt, spear, fist weapon, dual blunt, or dual sword. -->

View File

@ -1268,10 +1268,10 @@
</passiveConditions>
<effects>
<effect name="CrystalGradeModify">
<grade>
<amount>
<value level="1">3</value>
<value level="2">5</value>
</grade>
</amount>
</effect>
</effects>
</skill>

View File

@ -1320,13 +1320,13 @@
</passiveConditions>
<effects>
<effect name="CrystalGradeModify">
<grade>
<amount>
<value level="1">1</value>
<value level="2">2</value>
<value level="3">3</value>
<value level="4">4</value>
<value level="5">5</value>
</grade>
</amount>
</effect>
</effects>
</skill>

View File

@ -59,12 +59,16 @@ CpHealOverTime: Increases current CP by a given amount over time.
CpHealPercent: Increases current CP by a given percentage amount.
Cp: Increases current CP by a static amount.
CpRegen: CP Regeneration stat.
CraftingCritical: Crafting critical stat.
CreateCommonItem: Allows the player to create common recipe items up to a certain level.
CreateItem: Allows the player to create dwarven recipe items up to a certain level.
CreateItemRandom: Creates an item randomly from a given list. All extractable items with chances to get different items are using this effect.
CriticalDamage: Critical Damage stat.
CriticalDamagePosition: Critical Damage depending on position stat.
CriticalRate: Critical Rate stat.
CriticalRatePositionBonus: Critical Rate depending on position stat. Ignores the critical rate cap of 500.
CrystalGradeModify: Sets your Expertise Grade level. With this effect you can make lv. 40 player (C Grade) to wear S grade.
Crystallize: Allows the player to crystallize items up to a certain grade.
CubicMastery: Max cubics stat.
DamageBlock: Blocks Hp or Mp damage/heal.
DamageShield: Reflect damage percentage stat.
@ -233,6 +237,7 @@ ReflectMagic: Deflects magical damage back to the attacker.
ReflectSkill: Deflects physical/magical debuffs back to the attacker.
RefuelAirship: Increases Airship's fuel.
Relax: Sits down and increases HP regeneration until full.
RemoveEquipPenalty: Removes equipment grade penalty. Its the base effect for the grade penalty mechanics.
ResetInstanceEntry: Resets instance re-entry time. (l2jmobius)
ResistAbnormalByCategory: Buff/debuff resist stat.
ResistDDMagic: Magic resist stat (magic attack 50% effective or 1 damage)

View File

@ -2,88 +2,68 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="list">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="item" minOccurs="1" maxOccurs="unbounded">
<xs:sequence>
<xs:element name="recipe" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="altStatChange" minOccurs="0" maxOccurs="1">
<xs:sequence>
<xs:element name="materials">
<xs:complexType>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="GIM" />
<xs:enumeration value="SP" />
<xs:enumeration value="XP" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="value" type="xs:positiveInteger" use="required" />
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:attribute name="id" type="xs:int" />
<xs:attribute name="count" type="xs:long" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ingredient" minOccurs="1" maxOccurs="unbounded">
<xs:element name="product">
<xs:complexType>
<xs:attribute name="count" type="xs:positiveInteger" use="required" />
<xs:attribute name="id" type="xs:positiveInteger" use="required" />
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:attribute name="id" type="xs:int" />
<xs:attribute name="count" type="xs:long" />
<xs:attribute name="chance" type="xs:double" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="production" minOccurs="1" maxOccurs="1">
<xs:element name="npcFee" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:attribute name="count" type="xs:positiveInteger" use="required" />
<xs:attribute name="id" type="xs:positiveInteger" use="required" />
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="id" type="xs:int" />
<xs:attribute name="count" type="xs:long" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="productionRare" minOccurs="0" maxOccurs="1">
<xs:element name="statUse">
<xs:complexType>
<xs:attribute name="count" type="xs:positiveInteger" use="required" />
<xs:attribute name="id" type="xs:positiveInteger" use="required" />
<xs:attribute name="rarity" type="xs:positiveInteger" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="statUse" minOccurs="1" maxOccurs="1">
<xs:complexType>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="HP" />
<xs:enumeration value="MP" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="value" type="xs:positiveInteger" use="required" />
<xs:sequence>
<xs:element name="stat">
<xs:complexType>
<xs:attribute name="name" type="xs:string"></xs:attribute>
<xs:attribute name="val" type="xs:double" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="craftLevel" use="required">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1" />
<xs:maxInclusive value="14" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="id" type="xs:positiveInteger" use="required" />
<xs:attribute name="name" type="xs:normalizedString" use="required" />
<xs:attribute name="recipeId" type="xs:positiveInteger" use="required" />
<xs:attribute name="successRate" use="required">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:enumeration value="10" />
<xs:enumeration value="25" />
<xs:enumeration value="60" />
<xs:enumeration value="70" />
<xs:enumeration value="95" />
<xs:enumeration value="100" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="type" use="required">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="common" />
<xs:enumeration value="dwarven" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="id" type="xs:int" use="required" />
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="level" type="xs:int" use="required" />
<xs:attribute name="itemId" type="xs:int" use="required" />
<xs:attribute name="successRate" type="xs:double" use="required" />
<xs:attribute name="isCommonRecipe" type="xs:string" use="required" />
<xs:attribute name="maxOffering" type="xs:long" use="optional" />
<xs:attribute name="maxOfferingBonus" type="xs:double" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>

View File

@ -1197,6 +1197,21 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="grade">
<xs:complexType mixed="true">
<xs:sequence minOccurs="0">
<xs:element maxOccurs="unbounded" name="value">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="level" type="xs:unsignedByte" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="side" type="xs:string" />
<xs:element name="PARALYZE">
<xs:complexType mixed="true">
@ -2037,21 +2052,6 @@
<xs:element name="hp" type="xs:unsignedByte" />
<xs:element name="mp" type="xs:unsignedByte" />
<xs:element name="cp" type="xs:unsignedByte" />
<xs:element name="grade">
<xs:complexType mixed="true">
<xs:sequence minOccurs="0">
<xs:element maxOccurs="unbounded" name="value">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:unsignedByte">
<xs:attribute name="level" type="xs:unsignedByte" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="xp" type="xs:unsignedInt" />
<xs:element name="ACCURACY_COMBAT">
<xs:complexType mixed="true">

View File

@ -1,785 +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;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.enums.StatType;
import com.l2jmobius.gameserver.enums.StatusUpdateType;
import com.l2jmobius.gameserver.model.L2ManufactureItem;
import com.l2jmobius.gameserver.model.L2RecipeInstance;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.model.L2RecipeStatInstance;
import com.l2jmobius.gameserver.model.TempItem;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.skills.CommonSkill;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import com.l2jmobius.gameserver.network.serverpackets.ExUserInfoInvenWeight;
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
import com.l2jmobius.gameserver.network.serverpackets.RecipeBookItemList;
import com.l2jmobius.gameserver.network.serverpackets.RecipeItemMakeInfo;
import com.l2jmobius.gameserver.network.serverpackets.RecipeShopItemInfo;
import com.l2jmobius.gameserver.network.serverpackets.SetupGauge;
import com.l2jmobius.gameserver.network.serverpackets.StatusUpdate;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Util;
public class RecipeController
{
protected static final Map<Integer, RecipeItemMaker> _activeMakers = new ConcurrentHashMap<>();
protected RecipeController()
{
}
public void requestBookOpen(L2PcInstance player, boolean isDwarvenCraft)
{
// Check if player is trying to alter recipe book while engaged in manufacturing.
if (!_activeMakers.containsKey(player.getObjectId()))
{
final RecipeBookItemList response = new RecipeBookItemList(isDwarvenCraft, player.getMaxMp());
response.addRecipes(isDwarvenCraft ? player.getDwarvenRecipeBook() : player.getCommonRecipeBook());
player.sendPacket(response);
return;
}
player.sendPacket(SystemMessageId.YOU_MAY_NOT_ALTER_YOUR_RECIPE_BOOK_WHILE_ENGAGED_IN_MANUFACTURING);
}
public void requestMakeItemAbort(L2PcInstance player)
{
_activeMakers.remove(player.getObjectId()); // TODO: anything else here?
}
public void requestManufactureItem(L2PcInstance manufacturer, int recipeListId, L2PcInstance player)
{
final L2RecipeList recipeList = RecipeData.getInstance().getValidRecipeList(player, recipeListId);
if (recipeList == null)
{
return;
}
final List<L2RecipeList> dwarfRecipes = Arrays.asList(manufacturer.getDwarvenRecipeBook());
final 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;
}
// Check if manufacturer is under manufacturing store or private store.
if (Config.ALT_GAME_CREATION && _activeMakers.containsKey(manufacturer.getObjectId()))
{
player.sendPacket(SystemMessageId.PLEASE_CLOSE_THE_SETUP_WINDOW_FOR_YOUR_PRIVATE_WORKSHOP_OR_PRIVATE_STORE_AND_TRY_AGAIN);
return;
}
final RecipeItemMaker maker = new RecipeItemMaker(manufacturer, recipeList, player);
if (maker._isValid)
{
if (Config.ALT_GAME_CREATION)
{
_activeMakers.put(manufacturer.getObjectId(), maker);
ThreadPoolManager.schedule(maker, 100);
}
else
{
maker.run();
}
}
}
public void requestMakeItem(L2PcInstance player, int recipeListId)
{
// Check if player is trying to operate a private store or private workshop while engaged in combat.
if (player.isInCombat() || player.isInDuel())
{
player.sendPacket(SystemMessageId.WHILE_YOU_ARE_ENGAGED_IN_COMBAT_YOU_CANNOT_OPERATE_A_PRIVATE_STORE_OR_PRIVATE_WORKSHOP);
return;
}
final L2RecipeList recipeList = RecipeData.getInstance().getValidRecipeList(player, recipeListId);
if (recipeList == null)
{
return;
}
final List<L2RecipeList> dwarfRecipes = Arrays.asList(player.getDwarvenRecipeBook());
final 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;
}
// Check if player is busy (possible if alt game creation is enabled)
if (Config.ALT_GAME_CREATION && _activeMakers.containsKey(player.getObjectId()))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S2_S1);
sm.addItemName(recipeList.getItemId());
sm.addString("You are busy creating.");
player.sendPacket(sm);
return;
}
final RecipeItemMaker maker = new RecipeItemMaker(player, recipeList, player);
if (maker._isValid)
{
if (Config.ALT_GAME_CREATION)
{
_activeMakers.put(player.getObjectId(), maker);
ThreadPoolManager.schedule(maker, 100);
}
else
{
maker.run();
}
}
}
private static class RecipeItemMaker implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RecipeItemMaker.class.getName());
protected boolean _isValid;
protected List<TempItem> _items = null;
protected final L2RecipeList _recipeList;
protected final L2PcInstance _player; // "crafter"
protected final L2PcInstance _target; // "customer"
protected final Skill _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() ? CommonSkill.CREATE_DWARVEN.getId() : CommonSkill.CREATE_COMMON.getId();
_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)
{
final L2ManufactureItem item = _player.getManufactureItems().get(_recipeList.getId());
if (item != null)
{
_price = item.getCost();
if (_target.getAdena() < _price) // check price
{
_target.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
abort();
return;
}
}
}
// make temporary items
_items = listItems(false);
if (_items == 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))
{
LOGGER.warning("player or target == null (disconnected?), aborting" + _target + _player);
abort();
return;
}
if (!_player.isOnline() || !_target.isOnline())
{
LOGGER.warning("player or target is not online, aborting " + _target + _player);
abort();
return;
}
if (Config.ALT_GAME_CREATION && !_activeMakers.containsKey(_player.getObjectId()))
{
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())
{
_delay = (int) (Config.ALT_GAME_CREATION_SPEED * _player.getStat().getReuseTime(_skill) * GameTimeController.TICKS_PER_SECOND * GameTimeController.MILLIS_IN_TICK);
// FIXME: please fix this packet to show crafting animation (somebody)
final MagicSkillUse msk = new MagicSkillUse(_player, _skillId, _skillLevel, _delay, 0);
_player.broadcastPacket(msk);
_player.sendPacket(new SetupGauge(_player.getObjectId(), 0, _delay));
ThreadPoolManager.schedule(this, 100 + _delay);
}
else
{
// for alt mode, sleep delay msec before finishing
_player.sendPacket(new SetupGauge(_player.getObjectId(), 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
final L2ItemInstance adenatransfer = _target.transferItem("PayManufacture", _target.getInventory().getAdenaInstance().getObjectId(), _price, _player.getInventory(), _player);
if (adenatransfer == null)
{
_target.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
abort();
return;
}
}
_items = listItems(true); // this line actually takes materials from inventory
if (_items == null)
{
// 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()) || _target.tryLuck())
{
rewardPlayer(_target); // and immediately puts created item in its place
updateMakeInfo(true);
}
else
{
if (_target != _player)
{
SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_FAILED_TO_CREATE_S2_FOR_C1_AT_THE_PRICE_OF_S3_ADENA);
msg.addString(_target.getName());
msg.addItemName(_recipeList.getItemId());
msg.addLong(_price);
_player.sendPacket(msg);
msg = SystemMessage.getSystemMessage(SystemMessageId.C1_HAS_FAILED_TO_CREATE_S2_AT_THE_PRICE_OF_S3_ADENA);
msg.addString(_player.getName());
msg.addItemName(_recipeList.getItemId());
msg.addLong(_price);
_target.sendPacket(msg);
}
else
{
_target.sendPacket(SystemMessageId.YOU_FAILED_AT_MIXING_THE_ITEM);
}
updateMakeInfo(false);
}
// update load and mana bar of craft window
updateCurMp();
_activeMakers.remove(_player.getObjectId());
_player.isInCraftMode(false);
_target.sendItemList(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()
{
_target.sendPacket(new ExUserInfoInvenWeight(_target));
}
private void updateCurMp()
{
final StatusUpdate su = new StatusUpdate(_target);
su.addUpdate(StatusUpdateType.CUR_MP, (int) _target.getCurrentMp());
_target.sendPacket(su);
}
private void grabSomeItems()
{
int grabItems = _itemGrab;
while ((grabItems > 0) && !_items.isEmpty())
{
final 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)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.EQUIPPED_S1_S2); // you equipped ...
sm.addLong(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() == StatType.XP)
{
_exp = altStatChange.getValue();
}
else if (altStatChange.getType() == StatType.SP)
{
_sp = altStatChange.getValue();
}
else if (altStatChange.getType() == 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())
{
final double modifiedValue = statUse.getValue() / _creationPasses;
if (statUse.getType() == 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(_player.getObjectId(), 0, _delay));
ThreadPoolManager.schedule(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() == StatType.MP)
{
if (_player.getCurrentMp() < modifiedValue)
{
// rest (wait for MP)
if (Config.ALT_GAME_CREATION && isWait)
{
_player.sendPacket(new SetupGauge(_player.getObjectId(), 0, _delay));
ThreadPoolManager.schedule(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)
{
final L2RecipeInstance[] recipes = _recipeList.getRecipes();
final Inventory inv = _target.getInventory();
final List<TempItem> materials = new ArrayList<>();
SystemMessage sm;
for (L2RecipeInstance recipe : recipes)
{
if (recipe.getQuantity() > 0)
{
final L2ItemInstance item = inv.getItemByItemId(recipe.getItemId());
final long itemQuantityAmount = item == null ? 0 : item.getCount();
// check materials
if (itemQuantityAmount < recipe.getQuantity())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_NEED_S2_MORE_S1_S);
sm.addItemName(recipe.getItemId());
sm.addLong(recipe.getQuantity() - itemQuantityAmount);
_target.sendPacket(sm);
abort();
return null;
}
// make new temporary object, just for counting purposes
materials.add(new TempItem(item, recipe.getQuantity()));
}
}
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_S_DISAPPEARED);
sm.addItemName(tmp.getItemId());
sm.addLong(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(L2PcInstance player)
{
final int rareProdId = _recipeList.getRareItemId();
int itemId = _recipeList.getItemId();
int itemCount = _recipeList.getCount();
final 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();
}
}
if (player.tryLuck())
{
itemCount *= 2;
}
_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_HAS_BEEN_CREATED_FOR_C1_AFTER_THE_PAYMENT_OF_S3_ADENA_WAS_RECEIVED);
sm.addString(_target.getName());
sm.addItemName(itemId);
sm.addLong(_price);
_player.sendPacket(sm);
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_CREATED_S2_AFTER_RECEIVING_S3_ADENA);
sm.addString(_player.getName());
sm.addItemName(itemId);
sm.addLong(_price);
_target.sendPacket(sm);
}
else
{
sm = SystemMessage.getSystemMessage(SystemMessageId.S3_S2_S_HAVE_BEEN_CREATED_FOR_C1_AT_THE_PRICE_OF_S4_ADENA);
sm.addString(_target.getName());
sm.addInt(itemCount);
sm.addItemName(itemId);
sm.addLong(_price);
_player.sendPacket(sm);
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_CREATED_S3_S2_S_AT_THE_PRICE_OF_S4_ADENA);
sm.addString(_player.getName());
sm.addInt(itemCount);
sm.addItemName(itemId);
sm.addLong(_price);
_target.sendPacket(sm);
}
}
if (itemCount > 1)
{
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
sm.addItemName(itemId);
sm.addLong(itemCount);
_target.sendPacket(sm);
}
else
{
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
sm.addItemName(itemId);
_target.sendPacket(sm);
}
if (Config.ALT_GAME_CREATION)
{
final 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.getStat().getValue(Stats.EXPSP_RATE, _exp * Config.ALT_GAME_CREATION_XP_RATE * Config.ALT_GAME_CREATION_SPEED), (int) _player.getStat().getValue(Stats.EXPSP_RATE, _sp * Config.ALT_GAME_CREATION_SP_RATE * Config.ALT_GAME_CREATION_SPEED));
}
updateMakeInfo(true); // success
}
}
public static RecipeController getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final RecipeController _instance = new RecipeController();
}
}

View File

@ -21,6 +21,9 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -28,7 +31,6 @@ import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.LoginServerThread;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.L2ManufactureItem;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.TradeItem;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
@ -133,12 +135,12 @@ public class OfflineTradersTable
continue;
}
title = pc.getStoreName();
for (L2ManufactureItem i : pc.getManufactureItems().values())
for (Entry<Integer, Long> entry : pc.getManufactureItems().entrySet())
{
stm_items.setInt(1, pc.getObjectId());
stm_items.setInt(2, i.getRecipeId());
stm_items.setInt(2, entry.getKey());
stm_items.setLong(3, 0);
stm_items.setLong(4, i.getCost());
stm_items.setLong(4, entry.getValue());
stm_items.executeUpdate();
stm_items.clearParameters();
}
@ -274,10 +276,12 @@ public class OfflineTradersTable
}
case MANUFACTURE:
{
final Map<Integer, Long> manufactureItems = new HashMap<>();
while (items.next())
{
player.getManufactureItems().put(items.getInt(2), new L2ManufactureItem(items.getInt(2), items.getLong(4)));
manufactureItems.put(items.getInt(2), items.getLong(4));
}
player.setManufactureItems(manufactureItems);
player.setStoreName(rs.getString("title"));
break;
}
@ -407,12 +411,12 @@ public class OfflineTradersTable
{
title = trader.getStoreName();
}
for (L2ManufactureItem i : trader.getManufactureItems().values())
for (Entry<Integer, Long> entry : trader.getManufactureItems().entrySet())
{
stm3.setInt(1, trader.getObjectId());
stm3.setInt(2, i.getRecipeId());
stm3.setInt(2, entry.getKey());
stm3.setLong(3, 0);
stm3.setLong(4, i.getCost());
stm3.setLong(4, entry.getValue());
stm3.executeUpdate();
stm3.clearParameters();
}

View File

@ -18,35 +18,33 @@ package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.L2RecipeInstance;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.model.L2RecipeStatInstance;
import com.l2jmobius.gameserver.enums.StatusUpdateType;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.ItemChanceHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
/**
* The Class RecipeData.
* @author Zoey76
* @author Nik
*/
public class RecipeData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(RecipeData.class.getName());
private final Map<Integer, L2RecipeList> _recipes = new HashMap<>();
private final Map<Integer, RecipeHolder> _recipes = new HashMap<>();
/**
* Instantiates a new recipe data.
*/
protected RecipeData()
{
load();
@ -63,205 +61,108 @@ public class RecipeData implements IGameXmlReader
@Override
public void parseDocument(Document doc, File f)
{
// TODO: Cleanup checks enforced by XSD.
final List<L2RecipeInstance> recipePartList = new ArrayList<>();
final List<L2RecipeStatInstance> recipeStatUseList = new ArrayList<>();
final List<L2RecipeStatInstance> recipeAltStatChangeList = new ArrayList<>();
StatsSet set;
Node att;
NamedNodeMap attrs;
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
RECIPES_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("item".equalsIgnoreCase(d.getNodeName()))
if ("recipe".equalsIgnoreCase(d.getNodeName()))
{
recipePartList.clear();
recipeStatUseList.clear();
recipeAltStatChangeList.clear();
final NamedNodeMap attrs = d.getAttributes();
Node att;
int id = -1;
boolean haveRare = false;
final StatsSet set = new StatsSet();
att = attrs.getNamedItem("id");
if (att == null)
attrs = d.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing id for recipe item, skipping");
continue;
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
id = Integer.parseInt(att.getNodeValue());
set.set("id", id);
att = attrs.getNamedItem("recipeId");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing recipeId for recipe item id: " + id + ", skipping");
continue;
}
set.set("recipeId", Integer.parseInt(att.getNodeValue()));
att = attrs.getNamedItem("name");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing name for recipe item id: " + id + ", skipping");
continue;
}
set.set("recipeName", att.getNodeValue());
att = attrs.getNamedItem("craftLevel");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing level for recipe item id: " + id + ", skipping");
continue;
}
set.set("craftLevel", Integer.parseInt(att.getNodeValue()));
att = attrs.getNamedItem("type");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing type for recipe item id: " + id + ", skipping");
continue;
}
set.set("isDwarvenRecipe", att.getNodeValue().equalsIgnoreCase("dwarven"));
att = attrs.getNamedItem("successRate");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing successRate for recipe item id: " + id + ", skipping");
continue;
}
set.set("successRate", Integer.parseInt(att.getNodeValue()));
final int recipeId = set.getInt("id");
List<ItemHolder> materials = Collections.emptyList();
List<ItemChanceHolder> productGroup = Collections.emptyList();
List<ItemHolder> npcFee = Collections.emptyList();
final Map<StatusUpdateType, Double> statUse = new HashMap<>();
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("statUse".equalsIgnoreCase(c.getNodeName()))
if ("materials".equalsIgnoreCase(c.getNodeName()))
{
final String statName = c.getAttributes().getNamedItem("name").getNodeValue();
final int value = Integer.parseInt(c.getAttributes().getNamedItem("value").getNodeValue());
try
{
recipeStatUseList.add(new L2RecipeStatInstance(statName, value));
}
catch (Exception e)
{
LOGGER.severe(getClass().getSimpleName() + ": Error in StatUse parameter for recipe item id: " + id + ", skipping");
continue RECIPES_FILE;
}
materials = getItemList(c);
}
else if ("altStatChange".equalsIgnoreCase(c.getNodeName()))
else if ("product".equalsIgnoreCase(c.getNodeName()))
{
final String statName = c.getAttributes().getNamedItem("name").getNodeValue();
final int value = Integer.parseInt(c.getAttributes().getNamedItem("value").getNodeValue());
try
productGroup = getItemList(c).stream().map(ItemChanceHolder.class::cast).collect(Collectors.toList());
}
else if ("npcFee".equalsIgnoreCase(c.getNodeName()))
{
npcFee = getItemList(c);
}
else if ("statUse".equalsIgnoreCase(c.getNodeName()))
{
for (Node b = c.getFirstChild(); b != null; b = b.getNextSibling())
{
recipeAltStatChangeList.add(new L2RecipeStatInstance(statName, value));
if ("stat".equalsIgnoreCase(b.getNodeName()))
{
StatusUpdateType stat = StatusUpdateType.valueOf(b.getAttributes().getNamedItem("name").getNodeValue());
double value = Double.parseDouble(b.getAttributes().getNamedItem("val").getNodeValue());
statUse.put(stat, value);
}
}
catch (Exception e)
{
LOGGER.severe(getClass().getSimpleName() + ": Error in AltStatChange parameter for recipe item id: " + id + ", skipping");
continue RECIPES_FILE;
}
}
else if ("ingredient".equalsIgnoreCase(c.getNodeName()))
{
final int ingId = Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue());
final 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;
}
}
final 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);
}
_recipes.put(id, recipeList);
_recipes.put(recipeId, new RecipeHolder(set, materials, productGroup, npcFee, statUse));
}
}
}
}
}
/**
* Gets the recipe list.
* @param listId the list id
* @return the recipe list
*/
public L2RecipeList getRecipeList(int listId)
private List<ItemHolder> getItemList(Node c)
{
return _recipes.get(listId);
}
/**
* Gets the recipe by item id.
* @param itemId the item id
* @return the recipe by item id
*/
public L2RecipeList getRecipeByItemId(int itemId)
{
for (L2RecipeList find : _recipes.values())
final List<ItemHolder> items = new ArrayList<>();
for (Node b = c.getFirstChild(); b != null; b = b.getNextSibling())
{
if (find.getRecipeId() == itemId)
if ("item".equalsIgnoreCase(b.getNodeName()))
{
return find;
int itemId = Integer.parseInt(b.getAttributes().getNamedItem("id").getNodeValue());
long itemCount = Long.parseLong(b.getAttributes().getNamedItem("count").getNodeValue());
if (b.getAttributes().getNamedItem("chance") != null)
{
double chance = Double.parseDouble(b.getAttributes().getNamedItem("chance").getNodeValue());
items.add(new ItemChanceHolder(itemId, chance, itemCount));
}
else
{
items.add(new ItemHolder(itemId, itemCount));
}
}
}
return null;
return items;
}
/**
* Gets the all item ids.
* @return the all item ids
* Gets the recipe by recipe item id.
* @param itemId the recipe's item id
* @return {@code RecipeHolder} for the given recipe item id {@code null} if there is no recipe data connected with this recipe item id.
*/
public int[] getAllItemIds()
public RecipeHolder getRecipeByRecipeItemId(int itemId)
{
final int[] idList = new int[_recipes.size()];
int i = 0;
for (L2RecipeList rec : _recipes.values())
{
idList[i++] = rec.getRecipeId();
}
return idList;
return _recipes.values().stream().filter(r -> r.getItemId() == itemId).findAny().orElse(null);
}
/**
* Gets the valid recipe list.
* @param player the player
* @param id the recipe list id
* @return the valid recipe list
* @param recipeId the id of the recipe, NOT the recipe item id.
* @return {@code RecipeHolder} containing all the info necessary for crafting a recipe or {@code null} if there is no data for this recipeId.
*/
public L2RecipeList getValidRecipeList(L2PcInstance player, int id)
public RecipeHolder getRecipe(int recipeId)
{
final L2RecipeList recipeList = _recipes.get(id);
if ((recipeList == null) || (recipeList.getRecipes().length == 0))
{
player.sendMessage("No recipe for: " + id);
player.isInCraftMode(false);
return null;
}
return recipeList;
return _recipes.get(recipeId);
}
/**

View File

@ -74,7 +74,6 @@ import com.l2jmobius.gameserver.model.conditions.ConditionPlayerCloakStatus;
import com.l2jmobius.gameserver.model.conditions.ConditionPlayerCp;
import com.l2jmobius.gameserver.model.conditions.ConditionPlayerDualclass;
import com.l2jmobius.gameserver.model.conditions.ConditionPlayerFlyMounted;
import com.l2jmobius.gameserver.model.conditions.ConditionPlayerGrade;
import com.l2jmobius.gameserver.model.conditions.ConditionPlayerHasCastle;
import com.l2jmobius.gameserver.model.conditions.ConditionPlayerHasClanHall;
import com.l2jmobius.gameserver.model.conditions.ConditionPlayerHasFort;
@ -511,12 +510,6 @@ public abstract class DocumentBase
cond = joinAnd(cond, new ConditionPlayerCp(cp));
break;
}
case "grade":
{
final int expIndex = Integer.decode(getValue(a.getNodeValue(), template));
cond = joinAnd(cond, new ConditionPlayerGrade(expIndex));
break;
}
case "pkcount":
{
final int expIndex = Integer.decode(getValue(a.getNodeValue(), template));

View File

@ -182,7 +182,7 @@ public class Fishing
return;
}
if (_player.isInCraftMode() || _player.isInStoreMode())
if (_player.isCrafting() || _player.isInStoreMode())
{
_player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
_player.sendPacket(ActionFailed.STATIC_PACKET);

View File

@ -1,57 +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;
/**
* This class describes a RecipeList component (1 line of the recipe : Item-Quantity needed).
*/
public class L2RecipeInstance
{
/** The Identifier of the item needed in the L2RecipeInstance */
private final int _itemId;
/** The item quantity needed in the L2RecipeInstance */
private final int _quantity;
/**
* Constructor of L2RecipeInstance (create a new line in a RecipeList).
* @param itemId
* @param quantity
*/
public L2RecipeInstance(int itemId, int quantity)
{
_itemId = itemId;
_quantity = quantity;
}
/**
* @return the Identifier of the L2RecipeInstance Item needed.
*/
public int getItemId()
{
return _itemId;
}
/**
* @return the Item quantity needed of the L2RecipeInstance.
*/
public int getQuantity()
{
return _quantity;
}
}

View File

@ -1,242 +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;
/**
* This class describes a Recipe used by Dwarf to craft Item. All L2RecipeList are made of L2RecipeInstance (1 line of the recipe : Item-Quantity needed).
*/
public class L2RecipeList
{
/** The table containing all L2RecipeInstance (1 line of the recipe : Item-Quantity needed) of the L2RecipeList */
private L2RecipeInstance[] _recipes;
/** The table containing all L2RecipeStatInstance for the statUse parameter of the L2RecipeList */
private L2RecipeStatInstance[] _statUse;
/** The table containing all L2RecipeStatInstance for the altStatChange parameter of the L2RecipeList */
private L2RecipeStatInstance[] _altStatChange;
/** The Identifier of the Instance */
private final int _id;
/** The crafting level needed to use this L2RecipeList */
private final int _level;
/** The Identifier of the L2RecipeList */
private final int _recipeId;
/** The name of the L2RecipeList */
private final String _recipeName;
/** The crafting success rate when using the L2RecipeList */
private final int _successRate;
/** The Identifier of the Item crafted with this L2RecipeList */
private final int _itemId;
/** The quantity of Item crafted when using this L2RecipeList */
private final int _count;
/** The Identifier of the Rare Item crafted with this L2RecipeList */
private int _rareItemId;
/** The quantity of Rare Item crafted when using this L2RecipeList */
private int _rareCount;
/** The chance of Rare Item crafted when using this L2RecipeList */
private int _rarity;
/** If this a common or a dwarven recipe */
private final boolean _isDwarvenRecipe;
/**
* Constructor of L2RecipeList (create a new Recipe).
* @param set
* @param haveRare
*/
public L2RecipeList(StatsSet set, boolean haveRare)
{
_recipes = new L2RecipeInstance[0];
_statUse = new L2RecipeStatInstance[0];
_altStatChange = new L2RecipeStatInstance[0];
_id = set.getInt("id");
_level = set.getInt("craftLevel");
_recipeId = set.getInt("recipeId");
_recipeName = set.getString("recipeName");
_successRate = set.getInt("successRate");
_itemId = set.getInt("itemId");
_count = set.getInt("count");
if (haveRare)
{
_rareItemId = set.getInt("rareItemId");
_rareCount = set.getInt("rareCount");
_rarity = set.getInt("rarity");
}
_isDwarvenRecipe = set.getBoolean("isDwarvenRecipe");
}
/**
* Add a L2RecipeInstance to the L2RecipeList (add a line Item-Quantity needed to the Recipe).
* @param recipe
*/
public void addRecipe(L2RecipeInstance recipe)
{
final int len = _recipes.length;
final L2RecipeInstance[] tmp = new L2RecipeInstance[len + 1];
System.arraycopy(_recipes, 0, tmp, 0, len);
tmp[len] = recipe;
_recipes = tmp;
}
/**
* Add a L2RecipeStatInstance of the statUse parameter to the L2RecipeList.
* @param statUse
*/
public void addStatUse(L2RecipeStatInstance statUse)
{
final int len = _statUse.length;
final L2RecipeStatInstance[] tmp = new L2RecipeStatInstance[len + 1];
System.arraycopy(_statUse, 0, tmp, 0, len);
tmp[len] = statUse;
_statUse = tmp;
}
/**
* Add a L2RecipeStatInstance of the altStatChange parameter to the L2RecipeList.
* @param statChange
*/
public void addAltStatChange(L2RecipeStatInstance statChange)
{
final int len = _altStatChange.length;
final L2RecipeStatInstance[] tmp = new L2RecipeStatInstance[len + 1];
System.arraycopy(_altStatChange, 0, tmp, 0, len);
tmp[len] = statChange;
_altStatChange = tmp;
}
/**
* @return the Identifier of the Instance.
*/
public int getId()
{
return _id;
}
/**
* @return the crafting level needed to use this L2RecipeList.
*/
public int getLevel()
{
return _level;
}
/**
* @return the Identifier of the L2RecipeList.
*/
public int getRecipeId()
{
return _recipeId;
}
/**
* @return the name of the L2RecipeList.
*/
public String getRecipeName()
{
return _recipeName;
}
/**
* @return the crafting success rate when using the L2RecipeList.
*/
public int getSuccessRate()
{
return _successRate;
}
/**
* @return the Identifier of the Item crafted with this L2RecipeList.
*/
public int getItemId()
{
return _itemId;
}
/**
* @return the quantity of Item crafted when using this L2RecipeList.
*/
public int getCount()
{
return _count;
}
/**
* @return the Identifier of the Rare Item crafted with this L2RecipeList.
*/
public int getRareItemId()
{
return _rareItemId;
}
/**
* @return the quantity of Rare Item crafted when using this L2RecipeList.
*/
public int getRareCount()
{
return _rareCount;
}
/**
* @return the chance of Rare Item crafted when using this L2RecipeList.
*/
public int getRarity()
{
return _rarity;
}
/**
* @return {@code true} if this a Dwarven recipe or {@code false} if its a Common recipe
*/
public boolean isDwarvenRecipe()
{
return _isDwarvenRecipe;
}
/**
* @return the table containing all L2RecipeInstance (1 line of the recipe : Item-Quantity needed) of the L2RecipeList.
*/
public L2RecipeInstance[] getRecipes()
{
return _recipes;
}
/**
* @return the table containing all L2RecipeStatInstance of the statUse parameter of the L2RecipeList.
*/
public L2RecipeStatInstance[] getStatUse()
{
return _statUse;
}
/**
* @return the table containing all L2RecipeStatInstance of the AltStatChange parameter of the L2RecipeList.
*/
public L2RecipeStatInstance[] getAltStatChange()
{
return _altStatChange;
}
}

View File

@ -1,59 +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;
import com.l2jmobius.gameserver.enums.StatType;
/**
* This class describes a RecipeList statUse and altStatChange component.
*/
public class L2RecipeStatInstance
{
/** The Identifier of the statType */
private final StatType _type;
/** The value of the statType */
private final int _value;
/**
* Constructor of L2RecipeStatInstance.
* @param type
* @param value
*/
public L2RecipeStatInstance(String type, int value)
{
_type = Enum.valueOf(StatType.class, type);
_value = value;
}
/**
* @return the the type of the L2RecipeStatInstance.
*/
public StatType getType()
{
return _type;
}
/**
* @return the value of the L2RecipeStatInstance.
*/
public int getValue()
{
return _value;
}
}

View File

@ -32,8 +32,8 @@ public final class L2Seed
private final boolean _isAlternative;
private final int _limitSeeds;
private final int _limitCrops;
private final int _seedReferencePrice;
private final int _cropReferencePrice;
private final long _seedReferencePrice;
private final long _cropReferencePrice;
public L2Seed(StatsSet set)
{
@ -99,27 +99,27 @@ public final class L2Seed
return _limitCrops * Config.RATE_DROP_MANOR;
}
public final int getSeedReferencePrice()
public final long getSeedReferencePrice()
{
return _seedReferencePrice;
}
public final int getSeedMaxPrice()
public final long getSeedMaxPrice()
{
return _seedReferencePrice * 10;
}
public final int getSeedMinPrice()
public final long getSeedMinPrice()
{
return (int) (_seedReferencePrice * 0.6);
}
public final int getCropReferencePrice()
public final long getCropReferencePrice()
{
return _cropReferencePrice;
}
public final int getCropMaxPrice()
public final long getCropMaxPrice()
{
return _cropReferencePrice * 10;
}

View File

@ -28,7 +28,7 @@ public final class TempItem
{
private final int _itemId;
private int _quantity;
private final int _referencePrice;
private final long _referencePrice;
private final String _itemName;
/**
@ -60,7 +60,7 @@ public final class TempItem
_quantity = quantity;
}
public int getReferencePrice()
public long getReferencePrice()
{
return _referencePrice;
}

View File

@ -27,7 +27,6 @@ import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -46,11 +45,11 @@ import java.util.stream.Collectors;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.util.CommonUtil;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.GameTimeController;
import com.l2jmobius.gameserver.ItemsAutoDestroy;
import com.l2jmobius.gameserver.LoginServerThread;
import com.l2jmobius.gameserver.RecipeController;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.ai.L2CharacterAI;
@ -63,6 +62,7 @@ import com.l2jmobius.gameserver.data.sql.impl.CharNameTable;
import com.l2jmobius.gameserver.data.sql.impl.CharSummonTable;
import com.l2jmobius.gameserver.data.sql.impl.ClanTable;
import com.l2jmobius.gameserver.data.xml.impl.AdminData;
import com.l2jmobius.gameserver.data.xml.impl.CategoryData;
import com.l2jmobius.gameserver.data.xml.impl.ClassListData;
import com.l2jmobius.gameserver.data.xml.impl.ExperienceData;
import com.l2jmobius.gameserver.data.xml.impl.HennaData;
@ -85,6 +85,7 @@ import com.l2jmobius.gameserver.enums.GroupType;
import com.l2jmobius.gameserver.enums.HtmlActionScope;
import com.l2jmobius.gameserver.enums.IllegalActionPunishmentType;
import com.l2jmobius.gameserver.enums.InstanceType;
import com.l2jmobius.gameserver.enums.ItemGrade;
import com.l2jmobius.gameserver.enums.MountType;
import com.l2jmobius.gameserver.enums.NextActionType;
import com.l2jmobius.gameserver.enums.PartyDistributionType;
@ -116,6 +117,7 @@ import com.l2jmobius.gameserver.instancemanager.MatchingRoomManager;
import com.l2jmobius.gameserver.instancemanager.MentorManager;
import com.l2jmobius.gameserver.instancemanager.PunishmentManager;
import com.l2jmobius.gameserver.instancemanager.QuestManager;
import com.l2jmobius.gameserver.instancemanager.SellBuffsManager;
import com.l2jmobius.gameserver.instancemanager.SiegeManager;
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
@ -128,7 +130,6 @@ import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
import com.l2jmobius.gameserver.model.L2CommandChannel;
import com.l2jmobius.gameserver.model.L2ContactList;
import com.l2jmobius.gameserver.model.L2ManufactureItem;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Party;
import com.l2jmobius.gameserver.model.L2Party.MessageType;
@ -136,7 +137,6 @@ import com.l2jmobius.gameserver.model.L2PetData;
import com.l2jmobius.gameserver.model.L2PetLevelData;
import com.l2jmobius.gameserver.model.L2PremiumItem;
import com.l2jmobius.gameserver.model.L2Radar;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.model.L2Request;
import com.l2jmobius.gameserver.model.L2SkillLearn;
import com.l2jmobius.gameserver.model.L2World;
@ -163,7 +163,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;
@ -180,8 +179,6 @@ import com.l2jmobius.gameserver.model.actor.tasks.player.WaterTask;
import com.l2jmobius.gameserver.model.actor.templates.L2PcTemplate;
import com.l2jmobius.gameserver.model.actor.transform.Transform;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.model.base.ClassLevel;
import com.l2jmobius.gameserver.model.base.PlayerClass;
import com.l2jmobius.gameserver.model.base.SubClass;
import com.l2jmobius.gameserver.model.ceremonyofchaos.CeremonyOfChaosEvent;
import com.l2jmobius.gameserver.model.cubic.CubicInstance;
@ -215,6 +212,7 @@ import com.l2jmobius.gameserver.model.holders.MonsterBookCardHolder;
import com.l2jmobius.gameserver.model.holders.MonsterBookRewardHolder;
import com.l2jmobius.gameserver.model.holders.MovieHolder;
import com.l2jmobius.gameserver.model.holders.PlayerEventHolder;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.model.holders.SellBuffHolder;
import com.l2jmobius.gameserver.model.holders.SkillUseHolder;
import com.l2jmobius.gameserver.model.holders.TrainingHolder;
@ -235,6 +233,7 @@ import com.l2jmobius.gameserver.model.items.L2Weapon;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.items.type.ActionType;
import com.l2jmobius.gameserver.model.items.type.ArmorType;
import com.l2jmobius.gameserver.model.items.type.CrystalType;
import com.l2jmobius.gameserver.model.items.type.EtcItemType;
import com.l2jmobius.gameserver.model.items.type.WeaponType;
import com.l2jmobius.gameserver.model.matching.MatchingRoom;
@ -293,7 +292,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;
@ -523,13 +521,13 @@ public final class L2PcInstance extends L2Playable
private AdminTeleportType _teleportType = AdminTeleportType.NORMAL;
private boolean _inCrystallize;
private boolean _inCraftMode;
private volatile boolean _isCrafting;
private long _offlineShopStart = 0;
/** The table containing all L2RecipeList of the L2PcInstance */
private final Map<Integer, L2RecipeList> _dwarvenRecipeBook = new ConcurrentSkipListMap<>();
private final Map<Integer, L2RecipeList> _commonRecipeBook = new ConcurrentSkipListMap<>();
private final Map<Integer, RecipeHolder> _dwarvenRecipeBook = new ConcurrentSkipListMap<>();
private final Map<Integer, RecipeHolder> _commonRecipeBook = new ConcurrentSkipListMap<>();
/** Premium Items */
private final Map<Integer, L2PremiumItem> _premiumItems = new ConcurrentSkipListMap<>();
@ -564,7 +562,7 @@ public final class L2PcInstance extends L2Playable
private TradeList _activeTradeList;
private ItemContainer _activeWarehouse;
private volatile Map<Integer, L2ManufactureItem> _manufactureItems;
private volatile Map<Integer, Long> _manufactureItems;
private String _storeName = "";
private TradeList _sellList;
private TradeList _buyList;
@ -619,8 +617,6 @@ public final class L2PcInstance extends L2Playable
// after Freya players can control more than one tamed beast
private volatile Set<L2TamedBeastInstance> _tamedBeast = null;
private boolean _minimapAllowed = false;
// client radar
// TODO: This needs to be better integrated and saved/loaded
private final L2Radar _radar;
@ -712,6 +708,10 @@ public final class L2PcInstance extends L2Playable
// private byte _updateKnownCounter = 0;
private int _createItemLevel;
private int _createCommonItemLevel;
private ItemGrade _crystallizeGrade = ItemGrade.NONE;
private CrystalType _expertiseLevel = CrystalType.NONE;
private int _expertiseArmorPenalty = 0;
private int _expertiseWeaponPenalty = 0;
private int _expertisePenaltyBonus = 0;
@ -1259,14 +1259,14 @@ public final class L2PcInstance extends L2Playable
return getPrivateStoreType() != PrivateStoreType.NONE;
}
public boolean isInCraftMode()
public boolean isCrafting()
{
return _inCraftMode;
return _isCrafting;
}
public void isInCraftMode(boolean b)
public void setIsCrafting(boolean isCrafting)
{
_inCraftMode = b;
_isCrafting = isCrafting;
}
/**
@ -1304,17 +1304,17 @@ public final class L2PcInstance extends L2Playable
/**
* @return a table containing all Common L2RecipeList of the L2PcInstance.
*/
public L2RecipeList[] getCommonRecipeBook()
public Collection<RecipeHolder> getCommonRecipeBook()
{
return _commonRecipeBook.values().toArray(new L2RecipeList[_commonRecipeBook.values().size()]);
return _commonRecipeBook.values();
}
/**
* @return a table containing all Dwarf L2RecipeList of the L2PcInstance.
*/
public L2RecipeList[] getDwarvenRecipeBook()
public Collection<RecipeHolder> getDwarvenRecipeBook()
{
return _dwarvenRecipeBook.values().toArray(new L2RecipeList[_dwarvenRecipeBook.values().size()]);
return _dwarvenRecipeBook.values();
}
/**
@ -1322,7 +1322,7 @@ public final class L2PcInstance extends L2Playable
* @param recipe The L2RecipeList to add to the _recipebook
* @param saveToDb
*/
public void registerCommonRecipeList(L2RecipeList recipe, boolean saveToDb)
public void registerCommonRecipeList(RecipeHolder recipe, boolean saveToDb)
{
_commonRecipeBook.put(recipe.getId(), recipe);
@ -1337,7 +1337,7 @@ public final class L2PcInstance extends L2Playable
* @param recipe The L2RecipeList to add to the _recipebook
* @param saveToDb
*/
public void registerDwarvenRecipeList(L2RecipeList recipe, boolean saveToDb)
public void registerDwarvenRecipeList(RecipeHolder recipe, boolean saveToDb)
{
_dwarvenRecipeBook.put(recipe.getId(), recipe);
@ -1867,29 +1867,39 @@ public final class L2PcInstance extends L2Playable
}
/**
* @return True if the L2PcInstance can Craft Dwarven Recipes.
* @return the maximum dwarven recipe level this character can craft.
*/
public boolean hasDwarvenCraft()
public int getCreateItemLevel()
{
return getSkillLevel(CommonSkill.CREATE_DWARVEN.getId()) >= 1;
return _createItemLevel;
}
public int getDwarvenCraft()
public void setCreateItemLevel(int createItemLevel)
{
return getSkillLevel(CommonSkill.CREATE_DWARVEN.getId());
_createItemLevel = createItemLevel;
}
/**
* @return True if the L2PcInstance can Craft Dwarven Recipes.
* @return the maximum common recipe level this character can craft.
*/
public boolean hasCommonCraft()
public int getCreateCommonItemLevel()
{
return getSkillLevel(CommonSkill.CREATE_COMMON.getId()) >= 1;
return _createCommonItemLevel;
}
public int getCommonCraft()
public void setCreateCommonItemLevel(int createCommonItemLevel)
{
return getSkillLevel(CommonSkill.CREATE_COMMON.getId());
_createCommonItemLevel = createCommonItemLevel;
}
public ItemGrade getCrystallizeGrade()
{
return _crystallizeGrade;
}
public void setCrystallizeGrade(ItemGrade crystallizeGrade)
{
_crystallizeGrade = crystallizeGrade != null ? crystallizeGrade : ItemGrade.NONE;
}
/**
@ -2073,11 +2083,7 @@ public final class L2PcInstance extends L2Playable
public int getWeightPenalty()
{
if (_dietMode)
{
return 0;
}
return _curWeightPenalty;
return _dietMode ? 0 : _curWeightPenalty;
}
/**
@ -2141,37 +2147,26 @@ public final class L2PcInstance extends L2Playable
return;
}
final int expertiseLevel = getExpertiseLevel();
final CrystalType expertiseLevel = getExpertiseLevel().plusLevel(getExpertisePenaltyBonus());
int armorPenalty = 0;
int weaponPenalty = 0;
int crystaltype;
for (L2ItemInstance item : getInventory().getItems())
for (L2ItemInstance item : getInventory().getPaperdollItems(item -> (item != null) && ((item.getItemType() != EtcItemType.ARROW) && (item.getItemType() != EtcItemType.BOLT)) && item.getItem().getCrystalType().isGreater(expertiseLevel)))
{
if ((item != null) && item.isEquipped() && ((item.getItemType() != EtcItemType.ARROW) && (item.getItemType() != EtcItemType.BOLT)))
if (item.isArmor())
{
crystaltype = item.getItem().getCrystalType().getId();
if (crystaltype > expertiseLevel)
{
if (item.isWeapon() && (crystaltype > weaponPenalty))
{
weaponPenalty = crystaltype;
}
else if (crystaltype > armorPenalty)
{
armorPenalty = crystaltype;
}
}
// Armor penalty level increases depending on amount of penalty armors equipped, not grade level difference.
armorPenalty = CommonUtil.constrain(armorPenalty + 1, 0, 4);
}
else
{
// Weapon penalty level increases based on grade difference.
weaponPenalty = CommonUtil.constrain(item.getItem().getCrystalType().getLevel() - expertiseLevel.getLevel(), 0, 4);
}
}
boolean changed = false;
final int bonus = getExpertisePenaltyBonus();
// calc weapon penalty
weaponPenalty = weaponPenalty - expertiseLevel - bonus;
weaponPenalty = Math.min(Math.max(weaponPenalty, 0), 4);
if ((getExpertiseWeaponPenalty() != weaponPenalty) || (getSkillLevel(CommonSkill.WEAPON_GRADE_PENALTY.getId()) != weaponPenalty))
{
@ -2182,15 +2177,11 @@ public final class L2PcInstance extends L2Playable
}
else
{
removeSkill(getKnownSkill(CommonSkill.WEAPON_GRADE_PENALTY.getId()), false, true);
removeSkill(CommonSkill.WEAPON_GRADE_PENALTY.getId(), true);
}
changed = true;
}
// calc armor penalty
armorPenalty = armorPenalty - expertiseLevel - bonus;
armorPenalty = Math.min(Math.max(armorPenalty, 0), 4);
if ((getExpertiseArmorPenalty() != armorPenalty) || (getSkillLevel(CommonSkill.ARMOR_GRADE_PENALTY.getId()) != armorPenalty))
{
_expertiseArmorPenalty = armorPenalty;
@ -2200,13 +2191,14 @@ public final class L2PcInstance extends L2Playable
}
else
{
removeSkill(getKnownSkill(CommonSkill.ARMOR_GRADE_PENALTY.getId()), false, true);
removeSkill(CommonSkill.ARMOR_GRADE_PENALTY.getId(), true);
}
changed = true;
}
if (changed)
{
sendSkillList(); // Update expertise penalty icon in skill list.
sendPacket(new EtcStatusUpdate(this));
}
}
@ -2383,7 +2375,7 @@ public final class L2PcInstance extends L2Playable
try
{
if ((getLvlJoinedAcademy() != 0) && (_clan != null) && (PlayerClass.values()[Id].getLevel() == ClassLevel.THIRD))
if ((getLvlJoinedAcademy() != 0) && (_clan != null) && CategoryData.getInstance().isInCategory(CategoryType.THIRD_CLASS_GROUP, Id))
{
if (getLvlJoinedAcademy() <= 16)
{
@ -2416,7 +2408,7 @@ public final class L2PcInstance extends L2Playable
setTarget(this);
broadcastPacket(new MagicSkillUse(this, 5103, 1, 1000, 0));
setClassTemplate(Id);
if (getClassId().level() == 3)
if (isInCategory(CategoryType.FOURTH_CLASS_GROUP))
{
sendPacket(SystemMessageId.CONGRATULATIONS_YOU_VE_COMPLETED_YOUR_THIRD_CLASS_TRANSFER_QUEST);
}
@ -2710,18 +2702,6 @@ public final class L2PcInstance extends L2Playable
return _radar;
}
/* Return true if Hellbound minimap allowed */
public boolean isMinimapAllowed()
{
return _minimapAllowed;
}
/* Enable or disable minimap on Hellbound */
public void setMinimapAllowed(boolean b)
{
_minimapAllowed = b;
}
/**
* @return the SP amount of the L2PcInstance.
*/
@ -4355,6 +4335,8 @@ public final class L2PcInstance extends L2Playable
return getClan().getAllyCrestId();
}
//@formatter:off
/*
public void queryGameGuard()
{
if (getClient() != null)
@ -4364,9 +4346,10 @@ public final class L2PcInstance extends L2Playable
}
if (Config.GAMEGUARD_ENFORCE)
{
ThreadPoolManager.schedule(new GameGuardCheckTask(this), 30 * 1000);
ThreadPool.scheduleGeneral(new GameGuardCheckTask(this), 30 * 1000);
}
}
}*/
//@formatter:on
/**
* Send a Server->Client packet StatusUpdate to the L2PcInstance.
@ -4404,22 +4387,28 @@ public final class L2PcInstance extends L2Playable
{
if (target instanceof L2PcInstance)
{
final L2PcInstance temp = (L2PcInstance) target;
final L2PcInstance targetPlayer = (L2PcInstance) target;
sendPacket(ActionFailed.STATIC_PACKET);
if ((temp.getPrivateStoreType() == PrivateStoreType.SELL) || (temp.getPrivateStoreType() == PrivateStoreType.PACKAGE_SELL))
if ((targetPlayer.getPrivateStoreType() == PrivateStoreType.SELL) || (targetPlayer.getPrivateStoreType() == PrivateStoreType.PACKAGE_SELL))
{
sendPacket(new PrivateStoreListSell(this, temp));
if (isSellingBuffs())
{
SellBuffsManager.getInstance().sendBuffMenu(this, targetPlayer, 0);
}
else
{
sendPacket(new PrivateStoreListSell(this, targetPlayer));
}
}
else if (temp.getPrivateStoreType() == PrivateStoreType.BUY)
else if (targetPlayer.getPrivateStoreType() == PrivateStoreType.BUY)
{
sendPacket(new PrivateStoreListBuy(this, temp));
sendPacket(new PrivateStoreListBuy(this, targetPlayer));
}
else if (temp.getPrivateStoreType() == PrivateStoreType.MANUFACTURE)
else if (targetPlayer.getPrivateStoreType() == PrivateStoreType.MANUFACTURE)
{
sendPacket(new RecipeShopSellList(this, temp));
sendPacket(new RecipeShopSellList(this, targetPlayer));
}
}
else if (target != null) // _interactTarget=null should never happen but one never knows ^^;
{
@ -5057,6 +5046,9 @@ public final class L2PcInstance extends L2Playable
// Clear resurrect xp calculation
setExpBeforeDeath(0);
// Calculate Shilen's Breath debuff level. It must happen right before death, because buffs aren't applied on dead characters.
calculateShilensBreathDebuffLevel(killer);
// Kill the L2PcInstance
if (!super.doDie(killer))
{
@ -5110,9 +5102,6 @@ public final class L2PcInstance extends L2Playable
}
}
// calculate Shilen's Breath debuff level
calculateShilensBreathDebuffLevel(killer);
if (isMounted())
{
stopFeed();
@ -5778,21 +5767,21 @@ public final class L2PcInstance extends L2Playable
* Get the manufacture items map of this player.
* @return the the manufacture items map
*/
public Map<Integer, L2ManufactureItem> getManufactureItems()
public Map<Integer, Long> getManufactureItems()
{
if (_manufactureItems == null)
{
synchronized (this)
{
if (_manufactureItems == null)
{
_manufactureItems = Collections.synchronizedMap(new LinkedHashMap<>());
}
}
return Collections.emptyMap();
}
return _manufactureItems;
}
public void setManufactureItems(Map<Integer, Long> manufactureItems)
{
_manufactureItems = manufactureItems;
}
/**
* Get the store name, if any.
* @return the store name
@ -6524,7 +6513,7 @@ public final class L2PcInstance extends L2Playable
statement.setInt(23, getRace().ordinal());
statement.setInt(24, getClassId().getId());
statement.setLong(25, getDeleteTimer());
statement.setInt(26, hasDwarvenCraft() ? 1 : 0);
statement.setInt(26, getCreateItemLevel() > 0 ? 1 : 0);
statement.setString(27, getTitle());
statement.setInt(28, getAppearance().getTitleColor());
statement.setInt(29, isOnlineInt());
@ -6994,11 +6983,11 @@ public final class L2PcInstance extends L2Playable
{
_dwarvenRecipeBook.clear();
L2RecipeList recipe;
final RecipeData rd = RecipeData.getInstance();
RecipeHolder recipe;
RecipeData rd = RecipeData.getInstance();
while (rset.next())
{
recipe = rd.getRecipeList(rset.getInt("id"));
recipe = rd.getRecipe(rset.getInt("id"));
if (loadCommon)
{
if (rset.getInt(2) == 1)
@ -8770,7 +8759,7 @@ public final class L2PcInstance extends L2Playable
{
for (int itemId : _activeSoulShots)
{
if (ItemTable.getInstance().getTemplate(itemId).getCrystalType().getId() == crystalType)
if (ItemTable.getInstance().getTemplate(itemId).getCrystalType().getLevel() == crystalType)
{
disableAutoShot(itemId);
}
@ -10290,17 +10279,17 @@ public final class L2PcInstance extends L2Playable
}
/**
* Expertise of the L2PcInstance (None=0, D=1, C=2, B=3, A=4, S=5, S80=6, S84=7)
* @return int Expertise skill level.
* Expertise of the L2PcInstance (None=0, D=1, C=2, B=3, A=4, S=5, S80=6, S84=7, R=8, R95=9, R99=10)
* @return CrystalTyperepresenting expertise level..
*/
public int getExpertiseLevel()
public CrystalType getExpertiseLevel()
{
int level = getSkillLevel(239);
if (level < 0)
{
level = 0;
}
return level;
return _expertiseLevel;
}
public void setExpertiseLevel(CrystalType crystalType)
{
_expertiseLevel = crystalType != null ? crystalType : CrystalType.NONE;
}
@Override
@ -10864,16 +10853,6 @@ public final class L2PcInstance extends L2Playable
_log.log(Level.SEVERE, "deleteMe()", e);
}
// Stop crafting, if in progress
try
{
RecipeController.getInstance().requestMakeItemAbort(this);
}
catch (Exception e)
{
_log.log(Level.SEVERE, "deleteMe()", e);
}
// Cancel Attak or Cast
try
{
@ -12501,11 +12480,11 @@ public final class L2PcInstance extends L2Playable
{
final AtomicInteger slot = new AtomicInteger(1);
con.setAutoCommit(false);
for (L2ManufactureItem item : _manufactureItems.values())
for (Entry<Integer, Long> entry : _manufactureItems.entrySet())
{
st.setInt(1, getObjectId());
st.setInt(2, item.getRecipeId());
st.setLong(3, item.getCost());
st.setInt(2, entry.getKey());
st.setLong(3, entry.getValue());
st.setInt(4, slot.getAndIncrement());
st.addBatch();
}
@ -12522,10 +12501,7 @@ public final class L2PcInstance extends L2Playable
private void restoreRecipeShopList()
{
if (_manufactureItems != null)
{
_manufactureItems.clear();
}
final Map<Integer, Long> manufactureItems = new HashMap<>();
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(RESTORE_CHAR_RECIPE_SHOP))
@ -12535,7 +12511,7 @@ public final class L2PcInstance extends L2Playable
{
while (rset.next())
{
getManufactureItems().put(rset.getInt("recipeId"), new L2ManufactureItem(rset.getInt("recipeId"), rset.getLong("price")));
manufactureItems.put(rset.getInt("recipeId"), rset.getLong("price"));
}
}
}
@ -12543,6 +12519,8 @@ public final class L2PcInstance extends L2Playable
{
_log.log(Level.SEVERE, "Could not restore recipe shop list data for playerId: " + getObjectId(), e);
}
_manufactureItems = manufactureItems;
}
@Override

View File

@ -78,7 +78,7 @@ public class PcStatus extends PlayableStatus
}
// If OFFLINE_MODE_NO_DAMAGE is enabled and player is offline and he is in store/craft mode, no damage is taken.
if (Config.OFFLINE_MODE_NO_DAMAGE && (getActiveChar().getClient() != null) && getActiveChar().getClient().isDetached() && ((Config.OFFLINE_TRADE_ENABLE && ((getActiveChar().getPrivateStoreType() == PrivateStoreType.SELL) || (getActiveChar().getPrivateStoreType() == PrivateStoreType.BUY))) || (Config.OFFLINE_CRAFT_ENABLE && (getActiveChar().isInCraftMode() || (getActiveChar().getPrivateStoreType() == PrivateStoreType.MANUFACTURE)))))
if (Config.OFFLINE_MODE_NO_DAMAGE && (getActiveChar().getClient() != null) && getActiveChar().getClient().isDetached() && ((Config.OFFLINE_TRADE_ENABLE && ((getActiveChar().getPrivateStoreType() == PrivateStoreType.SELL) || (getActiveChar().getPrivateStoreType() == PrivateStoreType.BUY))) || (Config.OFFLINE_CRAFT_ENABLE && (getActiveChar().isCrafting() || (getActiveChar().getPrivateStoreType() == PrivateStoreType.MANUFACTURE)))))
{
return;
}
@ -100,7 +100,7 @@ public class PcStatus extends PlayableStatus
getActiveChar().stopEffectsOnDamage();
}
// Attacked players in craft/shops stand up.
if (getActiveChar().isInCraftMode() || getActiveChar().isInStoreMode())
if (getActiveChar().isCrafting() || getActiveChar().isInStoreMode())
{
getActiveChar().setPrivateStoreType(PrivateStoreType.NONE);
getActiveChar().standUp();

View File

@ -1,61 +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.conditions;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.skills.Skill;
/**
* The Class ConditionPlayerGrade.
* @author Gigiikun
*/
public final class ConditionPlayerGrade extends Condition
{
protected static final Logger _log = Logger.getLogger(ConditionPlayerGrade.class.getName());
// conditional values
public static final int COND_NO_GRADE = 0x0001;
public static final int COND_D_GRADE = 0x0002;
public static final int COND_C_GRADE = 0x0004;
public static final int COND_B_GRADE = 0x0008;
public static final int COND_A_GRADE = 0x0010;
public static final int COND_S_GRADE = 0x0020;
public static final int COND_S80_GRADE = 0x0040;
public static final int COND_S84_GRADE = 0x0080;
private final int _value;
/**
* Instantiates a new condition player grade.
* @param value the value
*/
public ConditionPlayerGrade(int value)
{
_value = value;
}
/**
*
*/
@Override
public boolean testImpl(L2Character effector, L2Character effected, Skill skill, L2Item item)
{
return (effector.getActingPlayer() != null) && (_value == (byte) effector.getActingPlayer().getExpertiseLevel());
}
}

View File

@ -0,0 +1,336 @@
/*
* 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.Map;
import java.util.Map.Entry;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.enums.StatusUpdateType;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.interfaces.IIdentifiable;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* A holder representing a craftable recipe based on the former L2RecipeList.<br>
* It contains all the recipe data and methods required for crafting this recipe.
* @author Nik
*/
public class RecipeHolder implements IIdentifiable
{
/** List of materials required to craft this recipe. */
private final List<ItemHolder> _materials;
/** Group of products where a single product will randomly be selected upon crafting. */
private final List<ItemChanceHolder> _productGroup;
private final List<ItemHolder> _npcFee;
/** Stats and amount required to perform the craft. */
private final Map<StatusUpdateType, Double> _statUse;
private final int _id;
private final int _level;
private final int _itemId;
private final String _name;
private final double _successRate;
private final boolean _isCommonRecipe;
private final double _maxOfferingBonus;
private final long _maxOffering;
public RecipeHolder(StatsSet set, List<ItemHolder> ingredients, List<ItemChanceHolder> productGroup, List<ItemHolder> npcFee, Map<StatusUpdateType, Double> statUse)
{
_id = set.getInt("id");
_level = set.getInt("level");
_itemId = set.getInt("itemId");
_name = set.getString("name");
_successRate = set.getDouble("successRate");
_isCommonRecipe = set.getBoolean("isCommonRecipe");
_maxOfferingBonus = set.getDouble("maxOfferingBonus", Math.max(0, 100 - _successRate));
_maxOffering = set.getLong("maxOffering", 0);
_materials = Collections.unmodifiableList(ingredients);
_productGroup = Collections.unmodifiableList(productGroup);
_npcFee = Collections.unmodifiableList(npcFee);
_statUse = Collections.unmodifiableMap(statUse);
}
/**
* @return the recipe id, NOT the recipe's item id
*/
@Override
public int getId()
{
return _id;
}
/**
* @return the crafting level needed to use this L2RecipeList.
*/
public int getLevel()
{
return _level;
}
/**
* @return the recipe's item id.
*/
public int getItemId()
{
return _itemId;
}
/**
* @return the name of the L2RecipeList.
*/
public String getName()
{
return _name;
}
/**
* @return the crafting success rate when using the L2RecipeList.
*/
public double getSuccessRate()
{
return _successRate;
}
/**
* @return {@code true} if this a Dwarven recipe or {@code false} if its a Common recipe
*/
public boolean isDwarvenRecipe()
{
return !_isCommonRecipe;
}
/**
* @return list of materials required to complete the recipe.
*/
public List<ItemHolder> getMaterials()
{
return _materials;
}
/**
* @return the whole group of products from which one random item will result in being crafted.
*/
public List<ItemChanceHolder> getProductGroup()
{
return _productGroup;
}
/**
* @return list of items that NPCs take for crafting this recipe.
*/
public List<ItemHolder> getNpcFee()
{
return _npcFee;
}
/**
* @return the table containing all L2RecipeStatInstance of the statUse parameter of the L2RecipeList.
*/
public Map<StatusUpdateType, Double> getStatUse()
{
return _statUse;
}
/**
* @return Maximum bonus success rate when maximum offering is reached. Default is the rate needed to reach 100% success rate.
*/
public double getMaxOfferingBonus()
{
return _maxOfferingBonus;
}
/**
* @return Maximum amount of items' adena worth offering. {@code 0} if this recipe does not allow offering.
*/
public long getMaxOffering()
{
return _maxOffering;
}
/**
* Picks a random number then attempts to get a product from the group based on it.
* @return {@code ItemChanceHolder} that is the randomly picked product from the group,<br>
* or {@code null} if the whole chance sum of the products in the group didn't manage to outnumber the random.
*/
public ItemChanceHolder getRandomProduct()
{
double random = Rnd.get(100);
for (ItemChanceHolder product : _productGroup)
{
if (product.getChance() > random)
{
return product;
}
random -= product.getChance();
}
return null;
}
public boolean checkNecessaryStats(L2PcInstance player, L2PcInstance manufacturer, boolean sendMessage)
{
for (Entry<StatusUpdateType, Double> entry : _statUse.entrySet())
{
final StatusUpdateType stat = entry.getKey();
final double requiredAmount = entry.getValue();
// Less than or equals to because some stats bad interraction - like HP could kill the player if its taken all.
if (stat.getValue(manufacturer) <= requiredAmount)
{
if (sendMessage)
{
switch (stat)
{
case CUR_HP:
{
player.sendPacket(SystemMessageId.NOT_ENOUGH_HP);
break;
}
case CUR_MP:
{
player.sendPacket(SystemMessageId.NOT_ENOUGH_MP);
break;
}
default:
{
player.sendMessage("You need " + requiredAmount + " " + stat.toString().toLowerCase() + " to perform this craft.");
break;
}
}
}
return false;
}
}
return true;
}
/**
* @param player the player's inventory to check.
* @param sendMessage send system messages for item requirements if there is missing ingredient.
* @return {@code true} if all necessary ingredients are met, {@code false} if there are missing ingredients.
*/
public boolean checkNecessaryIngredients(L2PcInstance player, boolean sendMessage)
{
for (ItemHolder ingredient : getMaterials())
{
final long count = player.getInventory().getInventoryItemCount(ingredient.getId(), -1);
if (count < ingredient.getCount())
{
if (sendMessage)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_NEED_S2_MORE_S1_S);
sm.addItemName(ingredient.getId());
sm.addLong(ingredient.getCount() - count);
player.sendPacket(sm);
}
return false;
}
}
return true;
}
/**
* @param player the player requesting the craft.
* @param manufacturer the player doing the craft (either the same player or manufacture shop).
* @param success {@code true} to give the product item to the player, {@code false} otherwise.
* @param craftingCritical {@code true} to give double of the product (if success), {@code false} otherwise.
* @param sendMessage send system messages of the process.
* @return {@code ItemHolder} of the randomly created product (even if its failing craft), {@code null} if the item creation was not performed due to failed checks.
*/
public ItemHolder doCraft(L2PcInstance player, L2PcInstance manufacturer, boolean success, boolean craftingCritical, boolean sendMessage)
{
if (!checkNecessaryStats(player, manufacturer, sendMessage))
{
return null;
}
if (!checkNecessaryIngredients(player, sendMessage))
{
return null;
}
// Take necessary stats.
for (Entry<StatusUpdateType, Double> entry : _statUse.entrySet())
{
final StatusUpdateType stat = entry.getKey();
final double requiredAmount = entry.getValue();
switch (stat)
{
case CUR_HP:
{
manufacturer.reduceCurrentHp(requiredAmount, manufacturer, null);
break;
}
case CUR_MP:
{
manufacturer.reduceCurrentMp(requiredAmount);
break;
}
case CUR_CP:
{
manufacturer.getStatus().reduceCp((int) requiredAmount);
break;
}
case EXP:
{
manufacturer.getStat().removeExp((long) requiredAmount);
break;
}
case REPUTATION:
{
manufacturer.setReputation((int) (manufacturer.getReputation() - requiredAmount));
break;
}
}
}
// Take necessary ingredients. If there was problem destroying item, return null to insicate that process didn't go well.
if (getMaterials().stream().anyMatch(i -> !player.destroyItemByItemId("Recipe " + getId(), i.getId(), i.getCount(), manufacturer, sendMessage)))
{
return null;
}
// Check if success. Luck triggers no matter the success rate - even with 100% craft. Luck chance is taken from your stat and not manufacturer's stat.
final ItemHolder result = getRandomProduct();
if (success)
{
player.addItem("Craft", result, manufacturer, true);
// Award another item if its crafting critical. Double blessed items is very, very rare, but still possible.
if (craftingCritical)
{
player.addItem("CraftCritical", result, manufacturer, true);
}
}
return result;
}
}

View File

@ -401,7 +401,7 @@ public abstract class Inventory extends ItemContainer
final L2PcInstance player = (L2PcInstance) inventory.getOwner();
// Any items equipped that result in expertise penalty do not give any skills at all.
if (item.getItem().getCrystalType().getId() > player.getExpertiseLevel())
if (item.getItem().getCrystalType().isGreater(player.getExpertiseLevel()))
{
return;
}

View File

@ -134,7 +134,7 @@ public abstract class L2Item extends ListenersContainer implements IIdentifiable
private int _time;
private int _autoDestroyTime;
private int _bodyPart;
private int _referencePrice;
private long _referencePrice;
private int _crystalCount;
private boolean _sellable;
private boolean _dropable;
@ -200,7 +200,7 @@ public abstract class L2Item extends ListenersContainer implements IIdentifiable
_time = set.getInt("time", -1);
_autoDestroyTime = set.getInt("auto_destroy_time", -1) * 1000;
_bodyPart = ItemTable.SLOTS.get(set.getString("bodypart", "none"));
_referencePrice = set.getInt("price", 0);
_referencePrice = set.getLong("price", 0);
_crystalType = set.getEnum("crystal_type", CrystalType.class, CrystalType.NONE);
_crystalCount = set.getInt("crystal_count", 0);
@ -538,7 +538,7 @@ public abstract class L2Item extends ListenersContainer implements IIdentifiable
/**
* @return the price of reference of the item.
*/
public final int getReferencePrice()
public final long getReferencePrice()
{
return _referencePrice;
}

View File

@ -731,7 +731,7 @@ public final class L2ItemInstance extends L2Object
/**
* @return the reference price of the item.
*/
public int getReferencePrice()
public long getReferencePrice()
{
return _item.getReferencePrice();
}

View File

@ -35,14 +35,14 @@ public enum CrystalType
R99(10, 17371, 30, 500),
EVENT(11, 0, 0, 0);
private final int _id;
private final int _level;
private final int _crystalId;
private final int _crystalEnchantBonusArmor;
private final int _crystalEnchantBonusWeapon;
CrystalType(int id, int crystalId, int crystalEnchantBonusArmor, int crystalEnchantBonusWeapon)
CrystalType(int level, int crystalId, int crystalEnchantBonusArmor, int crystalEnchantBonusWeapon)
{
_id = id;
_level = level;
_crystalId = crystalId;
_crystalEnchantBonusArmor = crystalEnchantBonusArmor;
_crystalEnchantBonusWeapon = crystalEnchantBonusWeapon;
@ -52,9 +52,9 @@ public enum CrystalType
* Gets the crystal type ID.
* @return the crystal type ID
*/
public int getId()
public int getLevel()
{
return _id;
return _level;
}
/**
@ -78,11 +78,41 @@ public enum CrystalType
public boolean isGreater(CrystalType crystalType)
{
return getId() > crystalType.getId();
return getLevel() > crystalType.getLevel();
}
public boolean isLesser(CrystalType crystalType)
{
return getId() < crystalType.getId();
return getLevel() < crystalType.getLevel();
}
public CrystalType plusLevel(int level)
{
level += getLevel();
if (level >= CrystalType.R99.getLevel())
{
return CrystalType.R99;
}
if (level <= CrystalType.NONE.getLevel())
{
return CrystalType.NONE;
}
return getByLevel(level);
}
public static CrystalType getByLevel(int level)
{
for (CrystalType crystalType : values())
{
if (crystalType.getLevel() == level)
{
return crystalType;
}
}
return null;
}
}

View File

@ -266,6 +266,7 @@ public enum Stats
// Which base stat ordinal should alter skill critical formula.
STAT_BONUS_SKILL_CRITICAL("statSkillCritical"),
STAT_BONUS_SPEED("statSpeed"),
CRAFTING_CRITICAL("craftingCritical"),
SHOTS_BONUS("shotBonus", new ShotsBonusFinalizer());
static final Logger LOGGER = Logger.getLogger(Stats.class.getName());

View File

@ -790,7 +790,7 @@ public final class L2GameClient extends ChannelInboundHandler<L2GameClient>
}
default:
{
canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode();
canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isCrafting();
break;
}
}

View File

@ -18,9 +18,11 @@ package com.l2jmobius.gameserver.network.clientpackets;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.RecipeBookItemList;
public final class RequestRecipeBookDestroy implements IClientIncomingPacket
@ -48,23 +50,24 @@ public final class RequestRecipeBookDestroy implements IClientIncomingPacket
return;
}
final L2RecipeList rp = RecipeData.getInstance().getRecipeList(_recipeID);
if (rp == null)
if ((activeChar.getPrivateStoreType() == PrivateStoreType.MANUFACTURE) || activeChar.isCrafting())
{
activeChar.sendPacket(SystemMessageId.YOU_MAY_NOT_ALTER_YOUR_RECIPE_BOOK_WHILE_ENGAGED_IN_MANUFACTURING);
return;
}
final RecipeHolder rp = RecipeData.getInstance().getRecipe(_recipeID);
if (rp == null)
{
client.sendPacket(SystemMessageId.THE_RECIPE_IS_INCORRECT);
return;
}
// Remove the recipe from the list.
activeChar.unregisterRecipeList(_recipeID);
final RecipeBookItemList response = new RecipeBookItemList(rp.isDwarvenRecipe(), activeChar.getMaxMp());
if (rp.isDwarvenRecipe())
{
response.addRecipes(activeChar.getDwarvenRecipeBook());
}
else
{
response.addRecipes(activeChar.getCommonRecipeBook());
}
// Send the new recipe book.
final RecipeBookItemList response = new RecipeBookItemList(activeChar, rp.isDwarvenRecipe());
activeChar.sendPacket(response);
}
}

View File

@ -17,10 +17,11 @@
package com.l2jmobius.gameserver.network.clientpackets;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.RecipeController;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.RecipeBookItemList;
public final class RequestRecipeBookOpen implements IClientIncomingPacket
{
@ -48,12 +49,19 @@ public final class RequestRecipeBookOpen implements IClientIncomingPacket
return;
}
if (activeChar.getActiveRequester() != null)
if (activeChar.getPrivateStoreType() == PrivateStoreType.MANUFACTURE)
{
activeChar.sendMessage("You may not alter your recipe book while trading.");
client.sendPacket(SystemMessageId.YOU_MAY_NOT_ALTER_YOUR_RECIPE_BOOK_WHILE_ENGAGED_IN_MANUFACTURING);
return;
}
RecipeController.getInstance().requestBookOpen(activeChar, _isDwarvenCraft);
if (activeChar.isProcessingTransaction())
{
client.sendPacket(SystemMessageId.ITEM_CREATION_IS_NOT_POSSIBLE_WHILE_ENGAGED_IN_A_TRADE);
return;
}
final RecipeBookItemList response = new RecipeBookItemList(activeChar, _isDwarvenCraft);
activeChar.sendPacket(response);
}
}

View File

@ -17,8 +17,11 @@
package com.l2jmobius.gameserver.network.clientpackets;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.RecipeItemMakeInfo;
public final class RequestRecipeItemMakeInfo implements IClientIncomingPacket
@ -41,6 +44,13 @@ public final class RequestRecipeItemMakeInfo implements IClientIncomingPacket
return;
}
client.sendPacket(new RecipeItemMakeInfo(_id, player));
final RecipeHolder recipe = RecipeData.getInstance().getRecipe(_id);
if (recipe == null)
{
player.sendPacket(SystemMessageId.THE_RECIPE_IS_INCORRECT);
return;
}
client.sendPacket(new RecipeItemMakeInfo(_id, player, recipe.getMaxOffering()));
}
}

View File

@ -16,23 +16,45 @@
*/
package com.l2jmobius.gameserver.network.clientpackets;
import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.RecipeController;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.stats.Stats;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.RecipeItemMakeInfo;
import com.l2jmobius.gameserver.util.Util;
/**
* @author Administrator
* @author Nik
*/
public final class RequestRecipeItemMakeSelf implements IClientIncomingPacket
{
private int _id;
private ItemHolder[] _offeredItems;
@Override
public boolean read(L2GameClient client, PacketReader packet)
{
_id = packet.readD();
final int offeringsCount = packet.readD();
if (offeringsCount > 0)
{
_offeredItems = new ItemHolder[offeringsCount];
for (int i = 0; i < offeringsCount; i++)
{
final int objectId = packet.readD();
final long count = packet.readQ();
_offeredItems[i] = new ItemHolder(objectId, count);
}
}
return true;
}
@ -45,23 +67,122 @@ public final class RequestRecipeItemMakeSelf implements IClientIncomingPacket
return;
}
if (!Config.IS_CRAFTING_ENABLED)
{
activeChar.sendMessage("Item creation is currently disabled.");
return;
}
if (!client.getFloodProtectors().getManufacture().tryPerformAction("RecipeMakeSelf"))
{
return;
}
if (activeChar.getPrivateStoreType() != PrivateStoreType.NONE)
if (activeChar.isCastingNow())
{
activeChar.sendMessage("You cannot create items while trading.");
activeChar.sendPacket(SystemMessageId.YOUR_RECIPE_BOOK_MAY_NOT_BE_ACCESSED_WHILE_USING_A_SKILL);
return;
}
if (activeChar.isInCraftMode())
if (activeChar.getPrivateStoreType() == PrivateStoreType.MANUFACTURE)
{
activeChar.sendMessage("You are currently in Craft Mode.");
activeChar.sendPacket(SystemMessageId.YOU_MAY_NOT_ALTER_YOUR_RECIPE_BOOK_WHILE_ENGAGED_IN_MANUFACTURING);
return;
}
RecipeController.getInstance().requestMakeItem(activeChar, _id);
if (activeChar.isProcessingTransaction())
{
activeChar.sendPacket(SystemMessageId.ITEM_CREATION_IS_NOT_POSSIBLE_WHILE_ENGAGED_IN_A_TRADE);
return;
}
// TODO: Check if its a retail-like check.
if (activeChar.isAlikeDead())
{
return;
}
// On retail if player is requesting trade, it is instantly canceled.
activeChar.cancelActiveTrade();
final RecipeHolder recipe = RecipeData.getInstance().getRecipe(_id);
if (recipe == null)
{
activeChar.sendPacket(SystemMessageId.THE_RECIPE_IS_INCORRECT);
return;
}
if (!activeChar.hasRecipeList(recipe.getId()))
{
Util.handleIllegalPlayerAction(activeChar, "Warning!! Character " + activeChar.getName() + " of account " + activeChar.getAccountName() + " sent a false recipe id.", Config.DEFAULT_PUNISH);
return;
}
// Check if stats or ingredients are met.
if (!recipe.checkNecessaryStats(activeChar, activeChar, true) || !recipe.checkNecessaryIngredients(activeChar, true))
{
return;
}
// Check if all offerings are legit.
if ((_offeredItems != null) && (recipe.getMaxOffering() > 0) && (recipe.getMaxOfferingBonus() > 0))
{
for (ItemHolder offer : _offeredItems)
{
final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(offer.getId());
if ((item == null) || (item.getCount() < offer.getCount()) || !item.isDestroyable())
{
return;
}
}
}
if (activeChar.isCrafting())
{
activeChar.sendPacket(SystemMessageId.CURRENTLY_CRAFTING_AN_ITEM_PLEASE_WAIT);
return;
}
activeChar.setIsCrafting(true);
// Take offerings to increase chance
double offeringBonus = 0;
if ((_offeredItems != null) && (recipe.getMaxOffering() > 0) && (recipe.getMaxOfferingBonus() > 0))
{
long offeredAdenaWorth = 0;
for (ItemHolder offer : _offeredItems)
{
final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(offer.getId());
if (activeChar.destroyItem("CraftOffering", item, offer.getCount(), null, true))
{
offeredAdenaWorth += (item.getItem().getReferencePrice() * offer.getCount());
}
}
offeringBonus = Math.min((offeredAdenaWorth / recipe.getMaxOffering()) * recipe.getMaxOfferingBonus(), recipe.getMaxOfferingBonus());
}
final boolean success = activeChar.tryLuck() || ((recipe.getSuccessRate() + offeringBonus) > Rnd.get(100));
final boolean craftingCritical = success && (activeChar.getStat().getValue(Stats.CRAFTING_CRITICAL) > Rnd.get(100));
if (success) // Successful craft.
{
if (craftingCritical)
{
activeChar.sendPacket(SystemMessageId.CRAFTING_CRITICAL);
}
}
else // Failed craft.
{
activeChar.sendPacket(SystemMessageId.YOU_FAILED_AT_MIXING_THE_ITEM);
}
// Perform the crafting: take the items and give reward if success.
recipe.doCraft(activeChar, activeChar, success, craftingCritical, true);
// Send craft window. Must be sent after crafting so it properly counts the items.
activeChar.sendPacket(new RecipeItemMakeInfo(recipe.getId(), activeChar, success, recipe.getMaxOffering()));
activeChar.setIsCrafting(false);
}
}

View File

@ -18,16 +18,17 @@ package com.l2jmobius.gameserver.network.clientpackets;
import static com.l2jmobius.gameserver.model.itemcontainer.Inventory.MAX_ADENA;
import java.util.Arrays;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.L2ManufactureItem;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
@ -44,28 +45,28 @@ public final class RequestRecipeShopListSet implements IClientIncomingPacket
{
private static final int BATCH_LENGTH = 12;
private L2ManufactureItem[] _items = null;
private Map<Integer, Long> _manufactureRecipes = null;
@Override
public boolean read(L2GameClient client, PacketReader packet)
{
final int count = packet.readD();
int count = packet.readD();
if ((count <= 0) || (count > Config.MAX_ITEM_IN_PACKET) || ((count * BATCH_LENGTH) != packet.getReadableBytes()))
{
return false;
}
_items = new L2ManufactureItem[count];
_manufactureRecipes = new HashMap<>(count);
for (int i = 0; i < count; i++)
{
final int id = packet.readD();
final long cost = packet.readQ();
int id = packet.readD();
long cost = packet.readQ();
if (cost < 0)
{
_items = null;
_manufactureRecipes = null;
return false;
}
_items[i] = new L2ManufactureItem(id, cost);
_manufactureRecipes.put(id, cost);
}
return true;
}
@ -79,13 +80,26 @@ public final class RequestRecipeShopListSet implements IClientIncomingPacket
return;
}
if (_items == null)
if (_manufactureRecipes == null)
{
player.sendPacket(SystemMessageId.ITEMS_ARE_NOT_AVAILABLE_FOR_A_PRIVATE_STORE_OR_PRIVATE_WORKSHOP);
player.setPrivateStoreType(PrivateStoreType.NONE);
player.broadcastUserInfo();
return;
}
if (player.isCastingNow())
{
player.sendPacket(SystemMessageId.A_PRIVATE_STORE_MAY_NOT_BE_OPENED_WHILE_USING_A_SKILL);
return;
}
if (player.isCrafting())
{
player.sendPacket(SystemMessageId.CURRENTLY_CRAFTING_AN_ITEM_PLEASE_WAIT);
return;
}
if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player) || player.isInDuel())
{
client.sendPacket(SystemMessageId.WHILE_YOU_ARE_ENGAGED_IN_COMBAT_YOU_CANNOT_OPERATE_A_PRIVATE_STORE_OR_PRIVATE_WORKSHOP);
@ -100,29 +114,36 @@ public final class RequestRecipeShopListSet implements IClientIncomingPacket
return;
}
final List<L2RecipeList> dwarfRecipes = Arrays.asList(player.getDwarvenRecipeBook());
final List<L2RecipeList> commonRecipes = Arrays.asList(player.getCommonRecipeBook());
player.getManufactureItems().clear();
for (L2ManufactureItem i : _items)
for (Entry<Integer, Long> item : _manufactureRecipes.entrySet())
{
final L2RecipeList list = RecipeData.getInstance().getRecipeList(i.getRecipeId());
if (!dwarfRecipes.contains(list) && !commonRecipes.contains(list))
final int recipeId = item.getKey();
final long recipeCost = item.getValue();
final RecipeHolder recipe = RecipeData.getInstance().getRecipe(recipeId);
if (recipe == null)
{
player.sendPacket(SystemMessageId.THE_RECIPE_IS_INCORRECT);
return;
}
if (ItemTable.getInstance().getTemplate(recipe.getItemId()).isQuestItem())
{
player.sendPacket(SystemMessageId.QUEST_RECIPES_CAN_NOT_BE_REGISTERED);
return;
}
if (!player.hasRecipeList(recipe.getId()))
{
Util.handleIllegalPlayerAction(player, "Warning!! Player " + player.getName() + " of account " + player.getAccountName() + " tried to set recipe which he dont have.", Config.DEFAULT_PUNISH);
return;
}
if (i.getCost() > MAX_ADENA)
if (recipeCost > MAX_ADENA)
{
Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " tried to set price more than " + MAX_ADENA + " adena in Private Manufacture.", Config.DEFAULT_PUNISH);
Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " tried to set price of " + recipeCost + " adena in Private Manufacture.", Config.DEFAULT_PUNISH);
return;
}
player.getManufactureItems().put(i.getRecipeId(), i);
}
player.setManufactureItems(_manufactureRecipes);
player.setStoreName(!player.hasManufactureShop() ? "" : player.getStoreName());
player.setPrivateStoreType(PrivateStoreType.MANUFACTURE);
player.sitDown();

View File

@ -17,10 +17,13 @@
package com.l2jmobius.gameserver.network.clientpackets;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.RecipeShopItemInfo;
/**
@ -49,12 +52,25 @@ public final class RequestRecipeShopMakeInfo implements IClientIncomingPacket
return;
}
final L2PcInstance shop = L2World.getInstance().getPlayer(_playerObjectId);
if ((shop == null) || (shop.getPrivateStoreType() != PrivateStoreType.MANUFACTURE))
final L2PcInstance manufacturer = L2World.getInstance().getPlayer(_playerObjectId);
if ((manufacturer == null) || (manufacturer.getPrivateStoreType() != PrivateStoreType.MANUFACTURE))
{
return;
}
client.sendPacket(new RecipeShopItemInfo(shop, _recipeId));
final RecipeHolder recipe = RecipeData.getInstance().getRecipe(_recipeId);
if (recipe == null)
{
player.sendPacket(SystemMessageId.THE_RECIPE_IS_INCORRECT);
return;
}
final Long manufactureRecipeCost = manufacturer.getManufactureItems().get(_recipeId);
if (manufactureRecipeCost == null)
{
return;
}
client.sendPacket(new RecipeShopItemInfo(manufacturer, _recipeId, manufactureRecipeCost, recipe.getMaxOffering()));
}
}

View File

@ -16,30 +16,53 @@
*/
package com.l2jmobius.gameserver.network.clientpackets;
import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.RecipeController;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.stats.Stats;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.RecipeShopItemInfo;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Util;
/**
* @author Administrator
* It appears you are able to successfully create from manufacture store while casting, while in manufacture store and within 250 range. So basic checks <br>
* from your own recipe list crafting are skipped. With the exception of trading, if you request trade, it is cancelled, if you are already trading, you get message.
* @author Nik
*/
public final class RequestRecipeShopMakeItem implements IClientIncomingPacket
{
private int _id;
private int _objectId;
private int _recipeId;
@SuppressWarnings("unused")
private long _unknown;
private long _manufacturePrice;
private ItemHolder[] _offeredItems;
@Override
public boolean read(L2GameClient client, PacketReader packet)
{
_id = packet.readD();
_objectId = packet.readD();
_recipeId = packet.readD();
_unknown = packet.readQ();
_manufacturePrice = packet.readQ();
final int offeringsCount = packet.readD();
if (offeringsCount > 0)
{
_offeredItems = new ItemHolder[offeringsCount];
for (int i = 0; i < offeringsCount; i++)
{
final int objectId = packet.readD();
final long count = packet.readQ();
_offeredItems[i] = new ItemHolder(objectId, count);
}
}
return true;
}
@ -52,41 +75,197 @@ public final class RequestRecipeShopMakeItem implements IClientIncomingPacket
return;
}
if (!Config.IS_CRAFTING_ENABLED)
{
activeChar.sendMessage("Item creation is currently disabled.");
return;
}
if (!client.getFloodProtectors().getManufacture().tryPerformAction("RecipeShopMake"))
{
return;
}
final L2PcInstance manufacturer = L2World.getInstance().getPlayer(_id);
final L2PcInstance manufacturer = L2World.getInstance().getPlayer(_objectId);
if (manufacturer == null)
{
return;
}
if (manufacturer.getInstanceWorld() != activeChar.getInstanceWorld())
if ((manufacturer.getInstanceWorld() != activeChar.getInstanceWorld()) || (activeChar.calculateDistance(manufacturer, false, false) > 250))
{
return;
}
if (activeChar.getPrivateStoreType() != PrivateStoreType.NONE)
{
activeChar.sendMessage("You cannot create items while trading.");
return;
}
if (manufacturer.getPrivateStoreType() != PrivateStoreType.MANUFACTURE)
{
// activeChar.sendMessage("You cannot create items while trading.");
return;
}
if (activeChar.isInCraftMode() || manufacturer.isInCraftMode())
if (activeChar.isProcessingTransaction() || manufacturer.isProcessingTransaction())
{
activeChar.sendMessage("You are currently in Craft Mode.");
activeChar.sendPacket(SystemMessageId.ITEM_CREATION_IS_NOT_POSSIBLE_WHILE_ENGAGED_IN_A_TRADE);
return;
}
if (Util.checkIfInRange(150, activeChar, manufacturer, true))
// TODO: Check if its a retail-like check.
if (activeChar.isAlikeDead() || manufacturer.isAlikeDead())
{
RecipeController.getInstance().requestManufactureItem(manufacturer, _recipeId, activeChar);
return;
}
// On retail if player is requesting trade, it is instantly canceled.
activeChar.cancelActiveTrade();
final RecipeHolder recipe = RecipeData.getInstance().getRecipe(_recipeId);
if (recipe == null)
{
activeChar.sendPacket(SystemMessageId.THE_RECIPE_IS_INCORRECT);
return;
}
if (!manufacturer.hasRecipeList(recipe.getId()))
{
Util.handleIllegalPlayerAction(activeChar, "Warning!! Character " + activeChar.getName() + " of account " + activeChar.getAccountName() + " sent a false recipe id.", Config.DEFAULT_PUNISH);
return;
}
final Long manufactureRecipeCost = manufacturer.getManufactureItems().get(_recipeId);
if (manufactureRecipeCost == null)
{
return;
}
// Check if the price is the same as requested price.
if (_manufacturePrice != manufactureRecipeCost)
{
return;
}
// Check if player can pay.
if (activeChar.getAdena() < manufactureRecipeCost)
{
activeChar.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
return;
}
// Check if stats or ingredients are met.
if (!recipe.checkNecessaryStats(activeChar, manufacturer, true) || !recipe.checkNecessaryIngredients(activeChar, true))
{
return;
}
// Check if all offerings are legit.
if ((_offeredItems != null) && (recipe.getMaxOffering() > 0) && (recipe.getMaxOfferingBonus() > 0))
{
for (ItemHolder offer : _offeredItems)
{
final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(offer.getId());
if ((item == null) || (item.getCount() < offer.getCount()) || !item.isDestroyable())
{
return;
}
}
}
if (manufacturer.isCrafting())
{
activeChar.sendPacket(SystemMessageId.CURRENTLY_CRAFTING_AN_ITEM_PLEASE_WAIT);
return;
}
manufacturer.setIsCrafting(true);
// First you must pay for the manufacturing service of the other player.
if (manufactureRecipeCost > 0)
{
// Attempt to pay the required manufacturing price by the manufacturer.
L2ItemInstance paidAdena = activeChar.transferItem("PayManufacture", activeChar.getInventory().getAdenaInstance().getObjectId(), manufactureRecipeCost, manufacturer.getInventory(), manufacturer);
if (paidAdena == null)
{
activeChar.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
return;
}
}
// Take offerings to increase chance
double offeringBonus = 0;
if ((_offeredItems != null) && (recipe.getMaxOffering() > 0) && (recipe.getMaxOfferingBonus() > 0))
{
long offeredAdenaWorth = 0;
for (ItemHolder offer : _offeredItems)
{
final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(offer.getId());
if (activeChar.destroyItem("CraftOffering", item, offer.getCount(), manufacturer, true))
{
offeredAdenaWorth += (item.getItem().getReferencePrice() * offer.getCount());
}
}
offeringBonus = Math.min((offeredAdenaWorth / recipe.getMaxOffering()) * recipe.getMaxOfferingBonus(), recipe.getMaxOfferingBonus());
}
final boolean success = activeChar.tryLuck() || ((recipe.getSuccessRate() + offeringBonus) > Rnd.get(100));
final boolean craftingCritical = success && (activeChar.getStat().getValue(Stats.CRAFTING_CRITICAL) > Rnd.get(100));
final ItemHolder craftedItem = recipe.doCraft(activeChar, manufacturer, success, craftingCritical, true);
if (success)
{
if (craftingCritical)
{
activeChar.sendPacket(SystemMessageId.CRAFTING_CRITICAL);
}
if (craftedItem.getCount() > 1)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S3_S2_S_HAVE_BEEN_CREATED_FOR_C1_AT_THE_PRICE_OF_S4_ADENA);
sm.addString(activeChar.getName());
sm.addInt((int) craftedItem.getCount());
sm.addItemName(craftedItem.getId());
sm.addLong(manufactureRecipeCost);
manufacturer.sendPacket(sm);
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_CREATED_S3_S2_S_AT_THE_PRICE_OF_S4_ADENA);
sm.addString(manufacturer.getName());
sm.addInt((int) craftedItem.getCount());
sm.addItemName(craftedItem.getId());
sm.addLong(manufactureRecipeCost);
activeChar.sendPacket(sm);
}
else
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S2_HAS_BEEN_CREATED_FOR_C1_AFTER_THE_PAYMENT_OF_S3_ADENA_WAS_RECEIVED);
sm.addString(activeChar.getName());
sm.addItemName(craftedItem.getId());
sm.addLong(manufactureRecipeCost);
manufacturer.sendPacket(sm);
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_CREATED_S2_AFTER_RECEIVING_S3_ADENA);
sm.addString(manufacturer.getName());
sm.addItemName(craftedItem.getId());
sm.addLong(manufactureRecipeCost);
activeChar.sendPacket(sm);
}
}
else
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_FAILED_TO_CREATE_S2_FOR_C1_AT_THE_PRICE_OF_S3_ADENA);
sm.addString(activeChar.getName());
sm.addItemName(craftedItem.getId());
sm.addLong(manufactureRecipeCost);
manufacturer.sendPacket(sm);
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_HAS_FAILED_TO_CREATE_S2_AT_THE_PRICE_OF_S3_ADENA);
sm.addString(manufacturer.getName());
sm.addItemName(craftedItem.getId());
sm.addLong(manufactureRecipeCost);
activeChar.sendPacket(sm);
}
// Show manufacturing window.
activeChar.sendPacket(new RecipeShopItemInfo(manufacturer, recipe.getId(), success, _manufacturePrice, recipe.getMaxOffering()));
manufacturer.setIsCrafting(false);
}
}

View File

@ -19,9 +19,12 @@ package com.l2jmobius.gameserver.network.clientpackets;
import com.l2jmobius.commons.network.PacketReader;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.L2GameClient;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
import com.l2jmobius.gameserver.network.serverpackets.RecipeShopManageList;
import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
public final class RequestRecipeShopManageList implements IClientIncomingPacket
{
@ -40,6 +43,38 @@ public final class RequestRecipeShopManageList implements IClientIncomingPacket
return;
}
if (player.getCommonRecipeBook().isEmpty() && player.getDwarvenRecipeBook().isEmpty())
{
player.sendPacket(SystemMessageId.NO_RECIPES_HAVE_BEEN_REGISTERED);
return;
}
if (player.isCastingNow())
{
player.sendPacket(SystemMessageId.A_PRIVATE_STORE_MAY_NOT_BE_OPENED_WHILE_USING_A_SKILL);
return;
}
if (player.isCrafting())
{
player.sendPacket(SystemMessageId.CURRENTLY_CRAFTING_AN_ITEM_PLEASE_WAIT);
return;
}
if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player) || player.isInDuel())
{
client.sendPacket(SystemMessageId.WHILE_YOU_ARE_ENGAGED_IN_COMBAT_YOU_CANNOT_OPERATE_A_PRIVATE_STORE_OR_PRIVATE_WORKSHOP);
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (player.isInsideZone(ZoneId.NO_STORE))
{
client.sendPacket(SystemMessageId.YOU_CANNOT_OPEN_A_PRIVATE_WORKSHOP_HERE);
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
// Player shouldn't be able to set stores if he/she is alike dead (dead or fake death)
if (player.isAlikeDead())
{

View File

@ -42,7 +42,14 @@ public final class RequestRecipeShopManagePrev implements IClientIncomingPacket
{
return;
}
else if (player.isAlikeDead() || (player.getTarget() == null) || !player.getTarget().isPlayer())
if (player.isAlikeDead() || (player.getTarget() == null) || !player.getTarget().isPlayer())
{
client.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (player.calculateDistance(player.getTarget(), false, false) > 250)
{
client.sendPacket(ActionFailed.STATIC_PACKET);
return;

View File

@ -120,7 +120,7 @@ public class RequestAlchemyTryMixCube implements IClientIncomingPacket
return;
}
final int price = itemInstance.getReferencePrice();
final long price = itemInstance.getReferencePrice();
if (itemInstance.getReferencePrice() == 0)
{
player.sendPacket(SystemMessageId.THIS_ITEM_CANNOT_BE_COMBINED);

View File

@ -59,7 +59,7 @@ public class RequestExTryToPutShapeShiftingEnchantSupportItem implements IClient
final ShapeShiftingItemRequest request = player.getRequest(ShapeShiftingItemRequest.class);
if (player.isInStoreMode() || player.isInCraftMode() || player.isProcessingRequest() || player.isProcessingTransaction() || (request == null))
if (player.isInStoreMode() || player.isCrafting() || player.isProcessingRequest() || player.isProcessingTransaction() || (request == null))
{
client.sendPacket(SystemMessageId.YOU_CANNOT_USE_THIS_SYSTEM_DURING_TRADING_PRIVATE_STORE_AND_WORKSHOP_SETUP);
return;

View File

@ -54,7 +54,7 @@ public class RequestExTryToPutShapeShiftingTargetItem implements IClientIncoming
final ShapeShiftingItemRequest request = player.getRequest(ShapeShiftingItemRequest.class);
if (player.isInStoreMode() || player.isInCraftMode() || player.isProcessingRequest() || player.isProcessingTransaction() || (request == null))
if (player.isInStoreMode() || player.isCrafting() || player.isProcessingRequest() || player.isProcessingTransaction() || (request == null))
{
client.sendPacket(ExPutShapeShiftingTargetItemResult.FAILED);
client.sendPacket(SystemMessageId.YOU_CANNOT_USE_THIS_SYSTEM_DURING_TRADING_PRIVATE_STORE_AND_WORKSHOP_SETUP);

View File

@ -62,7 +62,7 @@ public class RequestShapeShiftingItem implements IClientIncomingPacket
final ShapeShiftingItemRequest request = player.getRequest(ShapeShiftingItemRequest.class);
if (player.isInStoreMode() || player.isInCraftMode() || player.isProcessingRequest() || player.isProcessingTransaction() || (request == null))
if (player.isInStoreMode() || player.isCrafting() || player.isProcessingRequest() || player.isProcessingTransaction() || (request == null))
{
client.sendPacket(ExShapeShiftingResult.CLOSE);
client.sendPacket(SystemMessageId.YOU_CANNOT_USE_THIS_SYSTEM_DURING_TRADING_PRIVATE_STORE_AND_WORKSHOP_SETUP);

View File

@ -77,7 +77,7 @@ public class ExShowCropSetting implements IClientOutgoingPacket
packet.writeD(s.getCropLimit()); // next sale limit
packet.writeD(0); // ???
packet.writeD(s.getCropMinPrice()); // min crop price
packet.writeD(s.getCropMaxPrice()); // max crop price
packet.writeD((int) s.getCropMaxPrice()); // max crop price
// Current period
if (_current.containsKey(s.getCropId()))
{

View File

@ -48,8 +48,8 @@ public final class ExShowManorDefaultInfo implements IClientOutgoingPacket
{
packet.writeD(crop.getCropId()); // crop Id
packet.writeD(crop.getLevel()); // level
packet.writeD(crop.getSeedReferencePrice()); // seed price
packet.writeD(crop.getCropReferencePrice()); // crop price
packet.writeD((int) crop.getSeedReferencePrice()); // seed price
packet.writeD((int) crop.getCropReferencePrice()); // crop price
packet.writeC(1); // Reward 1 type
packet.writeD(crop.getReward(1)); // Reward 1 itemId
packet.writeC(1); // Reward 2 type

View File

@ -75,9 +75,9 @@ public class ExShowSeedSetting implements IClientOutgoingPacket
packet.writeC(1);
packet.writeD(s.getReward(2)); // reward 2 id
packet.writeD(s.getSeedLimit()); // next sale limit
packet.writeD(s.getSeedReferencePrice()); // price for castle to produce 1
packet.writeD(s.getSeedMinPrice()); // min seed price
packet.writeD(s.getSeedMaxPrice()); // max seed price
packet.writeD((int) s.getSeedReferencePrice()); // price for castle to produce 1
packet.writeD((int) s.getSeedMinPrice()); // min seed price
packet.writeD((int) s.getSeedMaxPrice()); // max seed price
// Current period
if (_current.containsKey(s.getSeedId()))
{

View File

@ -137,7 +137,7 @@ public class GMViewCharacterInfo implements IClientOutgoingPacket
packet.writeD(_activeChar.getAllyId()); // ally id
packet.writeC(_activeChar.getMountType().ordinal()); // mount type
packet.writeC(_activeChar.getPrivateStoreType().getId());
packet.writeC(_activeChar.hasDwarvenCraft() ? 1 : 0);
packet.writeC(_activeChar.getCreateItemLevel() > 0 ? 1 : 0);
packet.writeD(_activeChar.getPkKills());
packet.writeD(_activeChar.getPvpKills());

View File

@ -16,25 +16,24 @@
*/
package com.l2jmobius.gameserver.network.serverpackets;
import java.util.Collection;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.network.OutgoingPackets;
public class RecipeBookItemList implements IClientOutgoingPacket
{
private L2RecipeList[] _recipes;
private final Collection<RecipeHolder> _recipes;
private final boolean _isDwarvenCraft;
private final int _maxMp;
public RecipeBookItemList(boolean isDwarvenCraft, int maxMp)
public RecipeBookItemList(L2PcInstance player, boolean isDwarvenCraft)
{
_isDwarvenCraft = isDwarvenCraft;
_maxMp = maxMp;
}
public void addRecipes(L2RecipeList[] recipeBook)
{
_recipes = recipeBook;
_maxMp = player.getMaxMp();
_recipes = (isDwarvenCraft ? player.getDwarvenRecipeBook() : player.getCommonRecipeBook());
}
@Override
@ -51,11 +50,12 @@ public class RecipeBookItemList implements IClientOutgoingPacket
}
else
{
packet.writeD(_recipes.length); // number of items in recipe book
for (int i = 0; i < _recipes.length; i++)
packet.writeD(_recipes.size()); // number of items in recipe book
int i = 1;
for (RecipeHolder recipe : _recipes)
{
packet.writeD(_recipes[i].getId());
packet.writeD(i + 1);
packet.writeD(recipe.getId());
packet.writeD(i++);
}
}
return true;

View File

@ -18,34 +18,53 @@ package com.l2jmobius.gameserver.network.serverpackets;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.network.OutgoingPackets;
public class RecipeItemMakeInfo implements IClientOutgoingPacket
{
private final int _id;
private final L2PcInstance _activeChar;
private final boolean _success;
private final Boolean _success;
private final long _offeringMaximumAdena;
public RecipeItemMakeInfo(int id, L2PcInstance player, boolean success, long offeringMaximumAdena)
{
_id = id;
_activeChar = player;
_success = success;
_offeringMaximumAdena = offeringMaximumAdena;
}
public RecipeItemMakeInfo(int id, L2PcInstance player, boolean success)
{
_id = id;
_activeChar = player;
_success = success;
_offeringMaximumAdena = 0;
}
public RecipeItemMakeInfo(int id, L2PcInstance player, long offeringMaximumAdena)
{
_id = id;
_activeChar = player;
_success = null;
_offeringMaximumAdena = offeringMaximumAdena;
}
public RecipeItemMakeInfo(int id, L2PcInstance player)
{
_id = id;
_activeChar = player;
_success = true;
_success = null;
_offeringMaximumAdena = 0;
}
@Override
public boolean write(PacketWriter packet)
{
final L2RecipeList recipe = RecipeData.getInstance().getRecipeList(_id);
final RecipeHolder recipe = RecipeData.getInstance().getRecipe(_id);
if (recipe != null)
{
OutgoingPackets.RECIPE_ITEM_MAKE_INFO.writeId(packet);
@ -53,9 +72,9 @@ public class RecipeItemMakeInfo implements IClientOutgoingPacket
packet.writeD(recipe.isDwarvenRecipe() ? 0 : 1); // 0 = Dwarven - 1 = Common
packet.writeD((int) _activeChar.getCurrentMp());
packet.writeD(_activeChar.getMaxMp());
packet.writeD(_success ? 1 : 0); // item creation success/failed
packet.writeC(0x00);
packet.writeQ(0x00);
packet.writeD(_success == null ? -1 : (_success ? 1 : 0)); // item creation none/success/failed
packet.writeC(_offeringMaximumAdena > 0 ? 1 : 0); // Show offering window.
packet.writeQ(_offeringMaximumAdena); // Adena worth of items for maximum offering.
return true;
}
_log.info("Character: " + _activeChar + ": Requested unexisting recipe with id = " + _id);

View File

@ -22,13 +22,28 @@ import com.l2jmobius.gameserver.network.OutgoingPackets;
public class RecipeShopItemInfo implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final L2PcInstance _manufacturer;
private final int _recipeId;
private final Boolean _success;
private final long _manufacturePrice;
private final long _offeringMaximumAdena;
public RecipeShopItemInfo(L2PcInstance player, int recipeId)
public RecipeShopItemInfo(L2PcInstance manufacturer, int recipeId, boolean success, long manufacturePrice, long offeringMaximumAdena)
{
_player = player;
_manufacturer = manufacturer;
_recipeId = recipeId;
_success = success;
_manufacturePrice = manufacturePrice;
_offeringMaximumAdena = offeringMaximumAdena;
}
public RecipeShopItemInfo(L2PcInstance manufacturer, int recipeId, long manufacturePrice, long offeringMaximumAdena)
{
_manufacturer = manufacturer;
_recipeId = recipeId;
_success = null;
_manufacturePrice = manufacturePrice;
_offeringMaximumAdena = offeringMaximumAdena;
}
@Override
@ -36,14 +51,14 @@ public class RecipeShopItemInfo implements IClientOutgoingPacket
{
OutgoingPackets.RECIPE_SHOP_ITEM_INFO.writeId(packet);
packet.writeD(_player.getObjectId());
packet.writeD(_manufacturer.getObjectId());
packet.writeD(_recipeId);
packet.writeD((int) _player.getCurrentMp());
packet.writeD(_player.getMaxMp());
packet.writeD(0xffffffff);
packet.writeQ(0x00);
packet.writeC(0x00); // Trigger offering window if 1
packet.writeQ(0x00);
packet.writeD((int) _manufacturer.getCurrentMp());
packet.writeD(_manufacturer.getMaxMp());
packet.writeD(_success == null ? -1 : (_success ? 1 : 0)); // item creation none/success/failed
packet.writeQ(_manufacturePrice);
packet.writeC(_offeringMaximumAdena > 0 ? 1 : 0); // Trigger offering window if 1
packet.writeQ(_offeringMaximumAdena);
return true;
}
}

View File

@ -16,44 +16,39 @@
*/
package com.l2jmobius.gameserver.network.serverpackets;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.L2ManufactureItem;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.data.xml.impl.RecipeData;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.RecipeHolder;
import com.l2jmobius.gameserver.network.OutgoingPackets;
public class RecipeShopManageList implements IClientOutgoingPacket
{
private final L2PcInstance _seller;
private final boolean _isDwarven;
private L2RecipeList[] _recipes;
private final Collection<RecipeHolder> _recipes;
private List<Entry<Integer, Long>> _manufacture;
public RecipeShopManageList(L2PcInstance seller, boolean isDwarven)
{
_seller = seller;
_isDwarven = isDwarven;
if (_isDwarven && _seller.hasDwarvenCraft())
{
_recipes = _seller.getDwarvenRecipeBook();
}
else
{
_recipes = _seller.getCommonRecipeBook();
}
_recipes = (isDwarven && (_seller.getCreateItemLevel() > 0)) ? _seller.getDwarvenRecipeBook() : _seller.getCommonRecipeBook();
if (_seller.hasManufactureShop())
{
final Iterator<L2ManufactureItem> it = _seller.getManufactureItems().values().iterator();
L2ManufactureItem item;
while (it.hasNext())
_manufacture = new ArrayList<>();
for (Entry<Integer, Long> item : _seller.getManufactureItems().entrySet())
{
item = it.next();
if ((item.isDwarven() != _isDwarven) || !seller.hasRecipeList(item.getRecipeId()))
final RecipeHolder recipe = RecipeData.getInstance().getRecipe(item.getKey());
if (((recipe != null) && (recipe.isDwarvenRecipe() == _isDwarven)) && seller.hasRecipeList(recipe.getId()))
{
it.remove();
_manufacture.add(item);
}
}
}
@ -68,34 +63,34 @@ public class RecipeShopManageList implements IClientOutgoingPacket
packet.writeD((int) _seller.getAdena());
packet.writeD(_isDwarven ? 0x00 : 0x01);
if (_recipes == null)
if ((_recipes == null) || _recipes.isEmpty())
{
packet.writeD(0);
}
else
{
packet.writeD(_recipes.length); // number of items in recipe book
packet.writeD(_recipes.size());// number of items in recipe book
for (int i = 0; i < _recipes.length; i++)
int i = 1;
for (RecipeHolder recipe : _recipes)
{
final L2RecipeList temp = _recipes[i];
packet.writeD(temp.getId());
packet.writeD(i + 1);
packet.writeD(recipe.getId());
packet.writeD(i++);
}
}
if (!_seller.hasManufactureShop())
if ((_manufacture == null) || _manufacture.isEmpty())
{
packet.writeD(0x00);
}
else
{
packet.writeD(_seller.getManufactureItems().size());
for (L2ManufactureItem item : _seller.getManufactureItems().values())
packet.writeD(_manufacture.size());
for (Entry<Integer, Long> item : _manufacture)
{
packet.writeD(item.getRecipeId());
packet.writeD(0x00);
packet.writeQ(item.getCost());
packet.writeD(item.getKey());
packet.writeD(0x00); // CanCraft?
packet.writeQ(item.getValue());
}
}
return true;

View File

@ -16,8 +16,9 @@
*/
package com.l2jmobius.gameserver.network.serverpackets;
import java.util.Map.Entry;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.L2ManufactureItem;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.OutgoingPackets;
@ -47,11 +48,11 @@ public class RecipeShopSellList implements IClientOutgoingPacket
else
{
packet.writeD(_manufacturer.getManufactureItems().size());
for (L2ManufactureItem temp : _manufacturer.getManufactureItems().values())
for (Entry<Integer, Long> item : _manufacturer.getManufactureItems().entrySet())
{
packet.writeD(temp.getRecipeId());
packet.writeD(0x00); // unknown
packet.writeQ(temp.getCost());
packet.writeD(item.getKey());
packet.writeD(0x00); // CanCreate?
packet.writeQ(item.getValue());
}
}
return true;

View File

@ -76,7 +76,7 @@ public class SellList implements IClientOutgoingPacket
for (L2ItemInstance item : _sellList)
{
int price = item.getItem().getReferencePrice() / 2;
long price = item.getItem().getReferencePrice() / 2;
if (_merchant != null)
{
price -= (price * _merchant.getTotalTaxRate(TaxType.SELL));

View File

@ -23,6 +23,7 @@ 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.items.L2Item;
import com.l2jmobius.gameserver.model.items.type.CrystalType;
import com.l2jmobius.gameserver.network.OutgoingPackets;
public class ShopPreviewList implements IClientOutgoingPacket
@ -30,14 +31,14 @@ public class ShopPreviewList implements IClientOutgoingPacket
private final int _listId;
private final Collection<Product> _list;
private final long _money;
private int _expertise;
private CrystalType _expertise;
public ShopPreviewList(L2BuyList list, long currentMoney, int expertiseIndex)
public ShopPreviewList(L2BuyList list, long currentMoney, CrystalType expertise)
{
_listId = list.getListId();
_list = list.getProducts();
_money = currentMoney;
_expertise = expertiseIndex;
_expertise = expertise;
}
public ShopPreviewList(Collection<Product> lst, int listId, long currentMoney)
@ -59,7 +60,7 @@ public class ShopPreviewList implements IClientOutgoingPacket
int newlength = 0;
for (Product product : _list)
{
if ((product.getItem().getCrystalType().getId() <= _expertise) && product.getItem().isEquipable())
if (!product.getItem().getCrystalType().isGreater(_expertise) && product.getItem().isEquipable())
{
newlength++;
}
@ -68,7 +69,7 @@ public class ShopPreviewList implements IClientOutgoingPacket
for (Product product : _list)
{
if ((product.getItem().getCrystalType().getId() <= _expertise) && product.getItem().isEquipable())
if (!product.getItem().getCrystalType().isGreater(_expertise) && product.getItem().isEquipable())
{
packet.writeD(product.getItemId());
packet.writeH(product.getItem().getType2()); // item type2

View File

@ -20,6 +20,7 @@ import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.data.xml.impl.ExperienceData;
import com.l2jmobius.gameserver.enums.AttributeType;
import com.l2jmobius.gameserver.enums.ItemGrade;
import com.l2jmobius.gameserver.enums.UserInfoType;
import com.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import com.l2jmobius.gameserver.model.L2Clan;
@ -205,7 +206,7 @@ public class UserInfo extends AbstractMaskPacket<UserInfoType>
packet.writeH(6);
packet.writeC(_activeChar.getMountType().ordinal());
packet.writeC(_activeChar.getPrivateStoreType().getId());
packet.writeC(_activeChar.hasDwarvenCraft() || (_activeChar.getSkillLevel(248) > 0) ? 1 : 0);
packet.writeC(_activeChar.getCrystallizeGrade() != ItemGrade.NONE ? 1 : 0);
packet.writeC(_activeChar.getAbilityPoints() - _activeChar.getAbilityPointsUsed());
}