Skill enchant related work in progress.

This commit is contained in:
MobiusDev
2016-06-19 21:37:49 +00:00
parent bf739d2ca1
commit b56363ba31
14 changed files with 1200 additions and 271 deletions

View File

@ -25,6 +25,7 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.L2EnchantSkillGroup;
import com.l2jmobius.gameserver.model.L2EnchantSkillGroup.EnchantSkillHolder;
@ -41,10 +42,26 @@ public class EnchantSkillGroupsData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(EnchantSkillGroupsData.class.getName());
public static final int NORMAL_ENCHANT_BOOK = 6622;
public static final int SAFE_ENCHANT_BOOK = 9627;
public static final int CHANGE_ENCHANT_BOOK = 9626;
public static final int UNTRAIN_ENCHANT_BOOK = 9625;
public static final int NORMAL_ENCHANT_COST_MULTIPLIER = Config.NORMAL_ENCHANT_COST_MULTIPLIER;
public static final int SAFE_ENCHANT_COST_MULTIPLIER = Config.SAFE_ENCHANT_COST_MULTIPLIER;
public static final int NORMAL_ENCHANT_BOOK_OLD = 6622;
public static final int SAFE_ENCHANT_BOOK_OLD = 9627;
public static final int CHANGE_ENCHANT_BOOK_OLD = 9626;
public static final int UNTRAIN_ENCHANT_BOOK_OLD = 9625;
public static final int NORMAL_ENCHANT_BOOK = 30297;
public static final int SAFE_ENCHANT_BOOK = 30298;
public static final int CHANGE_ENCHANT_BOOK = 30299;
public static final int UNTRAIN_ENCHANT_BOOK = 30300;
public static final int IMMORTAL_SCROLL = 37044;
public static final int NORMAL_ENCHANT_BOOK_V2 = 46150;
public static final int SAFE_ENCHANT_BOOK_V2 = 46151;
public static final int CHANGE_ENCHANT_BOOK_V2 = 46152;
public static final int IMMORTAL_SCROLL_V2 = 46153;
public static final int NORMAL_ENCHANT_BOOK_V3 = 46154;
public static final int SAFE_ENCHANT_BOOK_V3 = 46155;
public static final int CHANGE_ENCHANT_BOOK_V3 = 46156;
public static final int IMMORTAL_SCROLL_V3 = 46157;
private final Map<Integer, L2EnchantSkillGroup> _enchantSkillGroups = new HashMap<>();
private final Map<Integer, L2EnchantSkillLearn> _enchantSkillTrees = new HashMap<>();

View File

@ -56,20 +56,10 @@ public class SkillData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(SkillData.class.getName());
private static final Set<String> BLOCK_ITEM_VALUE_ELEMENTS = new HashSet<>();
private static final Set<String> BLOCK_ITEM_ELEMENTS = new HashSet<>();
private final Map<Integer, Skill> _skills = new HashMap<>();
private final Map<Integer, Integer> _skillsMaxLevel = new HashMap<>();
private final Set<Integer> _enchantable = new HashSet<>();
static
{
BLOCK_ITEM_VALUE_ELEMENTS.add("item");
BLOCK_ITEM_VALUE_ELEMENTS.add("value");
BLOCK_ITEM_ELEMENTS.add("item");
}
private class NamedParamInfo
{
private final String _name;
@ -150,7 +140,7 @@ public class SkillData implements IGameXmlReader
*/
public static int getSkillHashCode(int skillId, int skillLevel)
{
return (skillId * 1021) + skillLevel;
return (skillId * 1031) + skillLevel;
}
public Skill getSkill(int skillId, int level)
@ -423,7 +413,10 @@ public class SkillData implements IGameXmlReader
_skills.put(getSkillHashCode(skill), skill);
_skillsMaxLevel.merge(skill.getId(), skill.getLevel(), Integer::max);
// TODO: add enchantable
if ((skill.getLevel() > 99) && !_enchantable.contains(skill.getId()))
{
_enchantable.add(skill.getId());
}
});
});
}

View File

@ -240,25 +240,37 @@ public final class SkillTreesData implements IGameXmlReader
switch (b.getNodeName())
{
case "item":
{
skillLearn.addRequiredItem(new ItemHolder(parseInteger(attrs, "id"), parseInteger(attrs, "count")));
break;
}
case "preRequisiteSkill":
{
skillLearn.addPreReqSkill(new SkillHolder(parseInteger(attrs, "id"), parseInteger(attrs, "lvl")));
break;
}
case "race":
{
skillLearn.addRace(Race.valueOf(b.getTextContent()));
break;
}
case "residenceId":
{
skillLearn.addResidenceId(Integer.valueOf(b.getTextContent()));
break;
}
case "socialClass":
{
skillLearn.setSocialClass(Enum.valueOf(SocialClass.class, b.getTextContent()));
break;
}
case "removeSkill":
{
final int removeSkillId = parseInteger(attrs, "id");
skillLearn.addRemoveSkills(removeSkillId);
_removeSkillCache.computeIfAbsent(classId, k -> new HashSet<>()).add(removeSkillId);
break;
}
}
}

View File

@ -16,6 +16,8 @@
*/
package com.l2jmobius.gameserver.network.clientpackets;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import com.l2jmobius.Config;
@ -45,14 +47,26 @@ public final class RequestExEnchantSkill implements IClientIncomingPacket
{
private static final Logger _logEnchant = Logger.getLogger("enchant.skills");
private int _type; // enchant type: 0 - normal, 1 - safe, 2 - untrain, 3 - change route, 4 - 100%
private int _skillId;
private int _skillLvl;
private int _fullLvl;
@Override
public boolean read(L2GameClient client, PacketReader packet)
{
_type = packet.readD();
_skillId = packet.readD();
_skillLvl = packet.readD();
_fullLvl = packet.readD();
if (_fullLvl < 100)
{
_skillLvl = _fullLvl;
}
else
{
_skillLvl = _fullLvl >> 16;
}
return true;
}
@ -72,19 +86,19 @@ public final class RequestExEnchantSkill implements IClientIncomingPacket
if (player.getClassId().level() < 3) // requires to have 3rd class quest completed
{
client.sendPacket(SystemMessageId.YOU_CANNOT_USE_THE_SKILL_ENHANCING_FUNCTION_IN_THIS_CLASS_YOU_CAN_USE_CORRESPONDING_FUNCTION_WHEN_COMPLETING_THE_THIRD_CLASS_CHANGE);
player.sendPacket(SystemMessageId.YOU_CANNOT_USE_THE_SKILL_ENHANCING_FUNCTION_IN_THIS_CLASS_YOU_CAN_USE_CORRESPONDING_FUNCTION_WHEN_COMPLETING_THE_THIRD_CLASS_CHANGE);
return;
}
if (player.getLevel() < 76)
{
client.sendPacket(SystemMessageId.YOU_CANNOT_USE_THE_SKILL_ENHANCING_FUNCTION_ON_THIS_LEVEL_YOU_CAN_USE_THE_CORRESPONDING_FUNCTION_ON_LEVELS_HIGHER_THAN_LV_76);
player.sendPacket(SystemMessageId.YOU_CANNOT_USE_THE_SKILL_ENHANCING_FUNCTION_ON_THIS_LEVEL_YOU_CAN_USE_THE_CORRESPONDING_FUNCTION_ON_LEVELS_HIGHER_THAN_LV_76);
return;
}
if (!player.isAllowedToEnchantSkills())
{
client.sendPacket(SystemMessageId.YOU_CANNOT_USE_THE_SKILL_ENHANCING_FUNCTION_IN_THIS_STATE_YOU_CAN_ENHANCE_SKILLS_WHEN_NOT_IN_BATTLE_AND_CANNOT_USE_THE_FUNCTION_WHILE_TRANSFORMED_IN_BATTLE_ON_A_MOUNT_OR_WHILE_THE_SKILL_IS_ON_COOLDOWN);
player.sendPacket(SystemMessageId.YOU_CANNOT_USE_THE_SKILL_ENHANCING_FUNCTION_IN_THIS_STATE_YOU_CAN_ENHANCE_SKILLS_WHEN_NOT_IN_BATTLE_AND_CANNOT_USE_THE_FUNCTION_WHILE_TRANSFORMED_IN_BATTLE_ON_A_MOUNT_OR_WHILE_THE_SKILL_IS_ON_COOLDOWN);
return;
}
@ -105,133 +119,452 @@ public final class RequestExEnchantSkill implements IClientIncomingPacket
{
return;
}
final EnchantSkillHolder esd = s.getEnchantSkillHolder(_skillLvl);
final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
if (beforeEnchantSkillLevel != s.getMinSkillLevel(_skillLvl))
final int _elvl = ((_skillLvl % 100) - 1) / 10;
if (_type == 0) // enchant
{
return;
}
final int costMultiplier = Config.NORMAL_ENCHANT_COST_MULTIPLIER;
final int requiredSp = esd.getSpCost() * costMultiplier;
if (player.getSp() >= requiredSp)
{
// only first lvl requires book
final boolean usesBook = (_skillLvl % 100) == 1; // 101, 201, 301 ...
final int reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK;
final L2ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
if (Config.ES_SP_BOOK_NEEDED && usesBook && (spb == null)) // Haven't spellbook
final EnchantSkillHolder esd = s.getEnchantSkillHolder(_skillLvl);
final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
if (beforeEnchantSkillLevel != s.getMinSkillLevel(_skillLvl))
{
client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
final int requiredAdena = (esd.getAdenaCost() * costMultiplier);
if (player.getInventory().getAdena() < requiredAdena)
final int costMultiplier = EnchantSkillGroupsData.NORMAL_ENCHANT_COST_MULTIPLIER;
final int requiredSp = esd.getSpCost() * costMultiplier;
if (player.getSp() >= requiredSp)
{
client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
boolean check = player.getStat().removeExpAndSp(0, requiredSp, false);
if (Config.ES_SP_BOOK_NEEDED && usesBook)
{
check &= player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
}
check &= player.destroyItemByItemId("Consume", Inventory.ADENA_ID, requiredAdena, player, true);
if (!check)
{
client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
// ok. Destroy ONE copy of the book
final int rate = esd.getRate(player);
if (Rnd.get(100) <= rate)
{
if (Config.LOG_SKILL_ENCHANTS)
final boolean usesBook = true;
final int reqItemId;
if (player.getClassId().level() == 3)
{
if (skill.getLevel() > 100)
reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_OLD;
}
else if (_elvl == 0)
{
reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK;
}
else if (_elvl == 1)
{
reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_V2;
}
else
{
reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_V3;
}
final L2ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
if (Config.ES_SP_BOOK_NEEDED && usesBook && (spb == null))
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
final int requiredAdena = esd.getAdenaCost() * costMultiplier;
if (player.getInventory().getAdena() < requiredAdena)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
boolean check = player.getStat().removeExpAndSp(0, requiredSp, false);
if (Config.ES_SP_BOOK_NEEDED && usesBook)
{
check &= player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
}
check &= player.destroyItemByItemId("Consume", Inventory.ADENA_ID, requiredAdena, player, true);
if (!check)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
// ok. Destroy ONE copy of the book
final int rate = esd.getRate(player);
if (Rnd.get(100) <= rate)
{
if (Config.LOG_SKILL_ENCHANTS)
{
if (spb != null)
final LogRecord record = new LogRecord(Level.INFO, "Success");
record.setParameters(new Object[]
{
_logEnchant.info("Success, Character:" + player.getName() + " [" + player.getObjectId() + "] Account:" + player.getAccountName() + " IP:" + player.getIPAddress() + ", +" + (skill.getLevel() % 100) + " " + skill.getName() + "(" + skill.getId() + "), " + spb.getName() + "(" + spb.getCount() + ") [" + spb.getObjectId() + "], " + rate);
}
else
{
_logEnchant.info("Success, Character:" + player.getName() + " [" + player.getObjectId() + "] Account:" + player.getAccountName() + " IP:" + player.getIPAddress() + ", +" + (skill.getLevel() % 100) + " " + skill.getName() + "(" + skill.getId() + "), " + rate);
}
player,
skill,
spb,
rate
});
record.setLoggerName("skill");
_logEnchant.log(record);
}
player.addSkill(skill, true);
player.sendPacket(ExEnchantSkillResult.valueOf(true));
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SKILL_ENCHANT_WAS_SUCCESSFUL_S1_HAS_BEEN_ENCHANTED);
sm.addSkillName(_skillId);
player.sendPacket(sm);
if (Config.DEBUG)
{
_log.fine("Learned skill ID: " + _skillId + " Level: " + _skillLvl + " for " + requiredSp + " SP, " + requiredAdena + " Adena.");
}
}
else
{
if (player.getClassId().level() == 3)
{
player.addSkill(SkillData.getInstance().getSkill(_skillId, s.getBaseLevel()), true);
}
else
{
if (spb != null)
final int _clvl = ((((_skillLvl % 100) - 1) / 10) * 10) + ((_skillLvl / 1000) * 1000);
player.addSkill(SkillData.getInstance().getSkill(_skillId, _clvl), true);
}
player.sendPacket(SystemMessageId.SKILL_ENCHANT_FAILED_THE_SKILL_WILL_BE_INITIALIZED);
player.sendPacket(ExEnchantSkillResult.valueOf(false));
if (Config.LOG_SKILL_ENCHANTS)
{
final LogRecord record = new LogRecord(Level.INFO, "Fail");
record.setParameters(new Object[]
{
_logEnchant.info("Success, Character:" + player.getName() + " [" + player.getObjectId() + "] Account:" + player.getAccountName() + " IP:" + player.getIPAddress() + ", " + skill.getName() + "(" + skill.getId() + "), " + spb.getName() + "(" + spb.getCount() + ") [" + spb.getObjectId() + "], " + rate);
}
else
{
_logEnchant.info("Success, Character:" + player.getName() + " [" + player.getObjectId() + "] Account:" + player.getAccountName() + " IP:" + player.getIPAddress() + ", " + skill.getName() + "(" + skill.getId() + "), " + rate);
}
player,
skill,
spb,
rate
});
record.setLoggerName("skill");
_logEnchant.log(record);
}
}
player.addSkill(skill, true);
client.sendPacket(ExEnchantSkillResult.valueOf(true));
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SKILL_ENCHANT_WAS_SUCCESSFUL_S1_HAS_BEEN_ENCHANTED);
sm.addSkillName(_skillId);
client.sendPacket(sm);
if (Config.DEBUG)
{
_log.finer("Learned skill ID: " + _skillId + " Level: " + _skillLvl + " for " + requiredSp + " SP, " + requiredAdena + " Adena.");
}
player.sendPacket(new UserInfo(player));
player.sendSkillList();
final int afterEnchantSkillLevel = player.getSkillLevel(_skillId);
player.sendPacket(new ExEnchantSkillInfo(_skillId, afterEnchantSkillLevel));
player.sendPacket(new ExEnchantSkillInfoDetail(0, _skillId, afterEnchantSkillLevel + 1, player));
player.updateShortCuts(_skillId, afterEnchantSkillLevel);
}
else
{
player.addSkill(SkillData.getInstance().getSkill(_skillId, s.getBaseLevel()), true);
client.sendPacket(SystemMessageId.SKILL_ENCHANT_FAILED_THE_SKILL_WILL_BE_INITIALIZED);
client.sendPacket(ExEnchantSkillResult.valueOf(false));
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_SP_TO_ENCHANT_THAT_SKILL);
}
}
else if (_type == 1) // safe enchant
{
final int costMultiplier = EnchantSkillGroupsData.SAFE_ENCHANT_COST_MULTIPLIER;
final int reqItemId;
if (player.getClassId().level() == 3)
{
reqItemId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_OLD;
}
else if (_elvl == 0)
{
reqItemId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK;
}
else if (_elvl == 1)
{
reqItemId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_V2;
}
else
{
reqItemId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_V3;
}
final EnchantSkillHolder esd = s.getEnchantSkillHolder(_skillLvl);
final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
if (beforeEnchantSkillLevel != s.getMinSkillLevel(_skillLvl))
{
return;
}
final int requiredSp = esd.getSpCost() * costMultiplier;
final int requireditems = esd.getAdenaCost() * costMultiplier;
final int rate = esd.getRate(player);
if (player.getSp() >= requiredSp)
{
final L2ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
if (spb == null)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
if (player.getInventory().getAdena() < requireditems)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
boolean check = player.getStat().removeExpAndSp(0, requiredSp, false);
check &= player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
check &= player.destroyItemByItemId("Consume", Inventory.ADENA_ID, requireditems, player, true);
if (!check)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
if (Rnd.get(100) <= rate)
{
if (Config.LOG_SKILL_ENCHANTS)
{
final LogRecord record = new LogRecord(Level.INFO, "Safe Success");
record.setParameters(new Object[]
{
player,
skill,
spb,
rate
});
record.setLoggerName("skill");
_logEnchant.log(record);
}
player.addSkill(skill, true);
if (Config.DEBUG)
{
_log.fine("Learned skill ID: " + _skillId + " Level: " + _skillLvl + " for " + requiredSp + " SP, " + requireditems + " Adena.");
}
player.sendPacket(ExEnchantSkillResult.valueOf(true));
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SKILL_ENCHANT_WAS_SUCCESSFUL_S1_HAS_BEEN_ENCHANTED);
sm.addSkillName(_skillId);
player.sendPacket(sm);
}
else
{
if (Config.LOG_SKILL_ENCHANTS)
{
final LogRecord record = new LogRecord(Level.INFO, "Safe Fail");
record.setParameters(new Object[]
{
player,
skill,
spb,
rate
});
record.setLoggerName("skill");
_logEnchant.log(record);
}
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SKILL_ENCHANT_FAILED_THE_SKILL_WILL_BE_INITIALIZED);
player.sendPacket(sm);
player.sendPacket(ExEnchantSkillResult.valueOf(false));
}
player.sendPacket(new UserInfo(player));
player.sendSkillList();
final int afterEnchantSkillLevel = player.getSkillLevel(_skillId);
player.sendPacket(new ExEnchantSkillInfo(_skillId, afterEnchantSkillLevel));
player.sendPacket(new ExEnchantSkillInfoDetail(1, _skillId, afterEnchantSkillLevel + 1, player));
player.updateShortCuts(_skillId, afterEnchantSkillLevel);
}
else
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_SP_TO_ENCHANT_THAT_SKILL));
}
}
else if (_type == 2) // untrain
{
return;
}
else if (_type == 3) // change route
{
final int reqItemId;
if (player.getClassId().level() == 3)
{
reqItemId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_OLD;
}
else if (_elvl == 0)
{
reqItemId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK;
}
else if (_elvl == 1)
{
reqItemId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_V2;
}
else
{
reqItemId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_V3;
}
final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
if (beforeEnchantSkillLevel <= 1000)
{
return;
}
final int currentEnchantLevel = beforeEnchantSkillLevel % 1000;
if (currentEnchantLevel != (_skillLvl % 1000))
{
return;
}
final EnchantSkillHolder esd = s.getEnchantSkillHolder(_skillLvl);
final int requiredSp = esd.getSpCost();
final int requireditems = esd.getAdenaCost();
if (player.getSp() >= requiredSp)
{
final L2ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
if (Config.ES_SP_BOOK_NEEDED && (spb == null))
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_SKILL_ROUTE_CHANGE);
return;
}
if (player.getInventory().getAdena() < requireditems)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
boolean check = player.getStat().removeExpAndSp(0, requiredSp, false);
if (Config.ES_SP_BOOK_NEEDED)
{
check &= player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
}
check &= player.destroyItemByItemId("Consume", Inventory.ADENA_ID, requireditems, player, true);
if (!check)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
final int levelPenalty = Rnd.get(Math.min(4, currentEnchantLevel));
_skillLvl -= levelPenalty;
if ((_skillLvl % 1000) == 0)
{
_skillLvl = s.getBaseLevel();
}
if (Config.LOG_SKILL_ENCHANTS)
{
if (skill.getLevel() > 100)
final LogRecord record = new LogRecord(Level.INFO, "Route Change");
record.setParameters(new Object[]
{
if (spb != null)
{
_logEnchant.info("Fail, Character:" + player.getName() + " [" + player.getObjectId() + "] Account:" + player.getAccountName() + " IP:" + player.getIPAddress() + ", +" + (skill.getLevel() % 100) + " " + skill.getName() + "(" + skill.getId() + "), " + spb.getName() + "(" + spb.getCount() + ") [" + spb.getObjectId() + "], " + rate);
}
else
{
_logEnchant.info("Fail, Character:" + player.getName() + " [" + player.getObjectId() + "] Account:" + player.getAccountName() + " IP:" + player.getIPAddress() + ", +" + (skill.getLevel() % 100) + " " + skill.getName() + "(" + skill.getId() + "), " + rate);
}
player,
skill,
spb
});
record.setLoggerName("skill");
_logEnchant.log(record);
}
player.addSkill(SkillData.getInstance().getSkill(_skillId, _skillLvl), true);
player.sendPacket(ExEnchantSkillResult.valueOf(true));
if (Config.DEBUG)
{
_log.fine("Learned skill ID: " + _skillId + " Level: " + _skillLvl + " for " + requiredSp + " SP, " + requireditems + " Adena.");
}
player.sendPacket(new UserInfo(player));
final SystemMessage sm;
if (levelPenalty == 0)
{
sm = SystemMessage.getSystemMessage(SystemMessageId.ENCHANT_SKILL_ROUTE_CHANGE_WAS_SUCCESSFUL_LV_OF_ENCHANT_SKILL_S1_WILL_REMAIN);
sm.addSkillName(_skillId);
}
else
{
sm = SystemMessage.getSystemMessage(SystemMessageId.ENCHANT_SKILL_ROUTE_CHANGE_WAS_SUCCESSFUL_LV_OF_ENCHANT_SKILL_S1_HAS_BEEN_DECREASED_BY_S2);
sm.addSkillName(_skillId);
if (_skillLvl > 1000)
{
sm.addInt(_skillLvl % 1000);
}
else
{
if (spb != null)
{
_logEnchant.info("Fail, Character:" + player.getName() + " [" + player.getObjectId() + "] Account:" + player.getAccountName() + " IP:" + player.getIPAddress() + ", " + skill.getName() + "(" + skill.getId() + "), " + spb.getName() + "(" + spb.getCount() + ") [" + spb.getObjectId() + "], " + rate);
}
else
{
_logEnchant.info("Fail, Character:" + player.getName() + " [" + player.getObjectId() + "] Account:" + player.getAccountName() + " IP:" + player.getIPAddress() + ", " + skill.getName() + "(" + skill.getId() + "), " + rate);
}
sm.addInt(0);
}
}
player.sendPacket(sm);
player.sendSkillList();
final int afterEnchantSkillLevel = player.getSkillLevel(_skillId);
player.sendPacket(new ExEnchantSkillInfo(_skillId, afterEnchantSkillLevel));
player.sendPacket(new ExEnchantSkillInfoDetail(3, _skillId, afterEnchantSkillLevel, player));
player.updateShortCuts(_skillId, afterEnchantSkillLevel);
}
else
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_SP_TO_ENCHANT_THAT_SKILL));
}
}
else if (_type == 4) // 100% enchant
{
final int reqItemId;
if (player.getClassId().level() == 3)
{
reqItemId = EnchantSkillGroupsData.IMMORTAL_SCROLL;
}
else if (_elvl == 0)
{
reqItemId = EnchantSkillGroupsData.IMMORTAL_SCROLL;
}
else if (_elvl == 1)
{
reqItemId = EnchantSkillGroupsData.IMMORTAL_SCROLL_V2;
}
else
{
reqItemId = EnchantSkillGroupsData.IMMORTAL_SCROLL_V3;
}
final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
if (beforeEnchantSkillLevel != s.getMinSkillLevel(_skillLvl))
{
return;
}
client.sendPacket(new UserInfo(player));
final L2ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
if (spb == null)
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
return;
}
player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
if (Config.LOG_SKILL_ENCHANTS)
{
final LogRecord record = new LogRecord(Level.INFO, "100% Success");
record.setParameters(new Object[]
{
player,
skill,
spb,
100
});
record.setLoggerName("skill");
_logEnchant.log(record);
}
player.addSkill(skill, true);
if (Config.DEBUG)
{
_log.fine("Learned skill ID: " + _skillId + " Level: " + _skillLvl + ".");
}
player.sendPacket(ExEnchantSkillResult.valueOf(true));
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SKILL_ENCHANT_WAS_SUCCESSFUL_S1_HAS_BEEN_ENCHANTED);
sm.addSkillName(_skillId);
player.sendPacket(sm);
player.sendPacket(new UserInfo(player));
player.sendSkillList();
final int afterEnchantSkillLevel = player.getSkillLevel(_skillId);
client.sendPacket(new ExEnchantSkillInfo(_skillId, afterEnchantSkillLevel));
client.sendPacket(new ExEnchantSkillInfoDetail(0, _skillId, afterEnchantSkillLevel + 1, player));
player.sendPacket(new ExEnchantSkillInfo(_skillId, afterEnchantSkillLevel));
player.sendPacket(new ExEnchantSkillInfoDetail(1, _skillId, afterEnchantSkillLevel + 1, player));
player.updateShortCuts(_skillId, afterEnchantSkillLevel);
}
else
{
client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_SP_TO_ENCHANT_THAT_SKILL);
}
}
}

View File

@ -32,12 +32,21 @@ public final class RequestExEnchantSkillInfo implements IClientIncomingPacket
{
private int _skillId;
private int _skillLvl;
private int _fullLvl;
@Override
public boolean read(L2GameClient client, PacketReader packet)
{
_skillId = packet.readD();
_skillLvl = packet.readD();
_fullLvl = packet.readD();
if (_fullLvl < 100)
{
_skillLvl = _fullLvl;
}
else
{
_skillLvl = _fullLvl >> 16;
}
return true;
}
@ -78,6 +87,6 @@ public final class RequestExEnchantSkillInfo implements IClientIncomingPacket
return;
}
client.sendPacket(new ExEnchantSkillInfo(_skillId, _skillLvl));
activeChar.sendPacket(new ExEnchantSkillInfo(_skillId, _skillLvl));
}
}

View File

@ -32,13 +32,22 @@ public final class RequestExEnchantSkillInfoDetail implements IClientIncomingPac
private int _type;
private int _skillId;
private int _skillLvl;
private int _fullLvl;
@Override
public boolean read(L2GameClient client, PacketReader packet)
{
_type = packet.readD();
_skillId = packet.readD();
_skillLvl = packet.readD();
_fullLvl = packet.readD();
if (_fullLvl < 100)
{
_skillLvl = _fullLvl;
}
else
{
_skillLvl = _fullLvl >> 16;
}
return true;
}
@ -65,7 +74,7 @@ public final class RequestExEnchantSkillInfoDetail implements IClientIncomingPac
}
else if (_type == 2)
{
reqSkillLvl = _skillLvl + 1; // untrain
return;
}
else if (_type == 3)
{
@ -81,7 +90,7 @@ public final class RequestExEnchantSkillInfoDetail implements IClientIncomingPac
}
// if reqlvl is 100,200,.. check base skill lvl enchant
if ((reqSkillLvl % 100) == 0)
if ((reqSkillLvl % 1000) == 0)
{
final L2EnchantSkillLearn esl = EnchantSkillGroupsData.getInstance().getSkillEnchantmentBySkillId(_skillId);
if (esl != null)
@ -101,13 +110,14 @@ public final class RequestExEnchantSkillInfoDetail implements IClientIncomingPac
else if (playerSkillLvl != reqSkillLvl)
{
// change route is different skill lvl but same enchant
if ((_type == 3) && ((playerSkillLvl % 100) != (_skillLvl % 100)))
if ((_type == 3) && ((playerSkillLvl % 1000) != (_skillLvl % 1000)))
{
return;
}
}
// send skill enchantment detail
client.sendPacket(new ExEnchantSkillInfoDetail(_type, _skillId, _skillLvl, activeChar));
final ExEnchantSkillInfoDetail esd = new ExEnchantSkillInfoDetail(_type, _skillId, _skillLvl, activeChar);
activeChar.sendPacket(esd);
}
}

View File

@ -21,6 +21,7 @@ import java.util.List;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.data.xml.impl.EnchantSkillGroupsData;
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
import com.l2jmobius.gameserver.model.L2EnchantSkillGroup.EnchantSkillHolder;
import com.l2jmobius.gameserver.model.L2EnchantSkillLearn;
import com.l2jmobius.gameserver.network.client.OutgoingPackets;
@ -31,19 +32,21 @@ public final class ExEnchantSkillInfo implements IClientOutgoingPacket
private final int _id;
private final int _lvl;
private final int _maxlvl;
private boolean _maxEnchanted = false;
public ExEnchantSkillInfo(int id, int lvl)
{
_id = id;
_lvl = lvl;
_maxlvl = SkillData.getInstance().getMaxLevel(_id);
final L2EnchantSkillLearn enchantLearn = EnchantSkillGroupsData.getInstance().getSkillEnchantmentBySkillId(_id);
// do we have this skill?
if (enchantLearn != null)
{
// skill already enchanted?
if (_lvl > 100)
if (_lvl > 1000)
{
_maxEnchanted = enchantLearn.isMaxEnchant(_lvl);
@ -51,24 +54,19 @@ public final class ExEnchantSkillInfo implements IClientOutgoingPacket
final EnchantSkillHolder esd = enchantLearn.getEnchantSkillHolder(_lvl);
// if it exists add it
if (esd != null)
if ((esd != null) && !_maxEnchanted)
{
_routes.add(_lvl); // current enchant add firts
_routes.add(_lvl + 1); // current enchant add firts
}
final int skillLvL = (_lvl % 100);
for (int route : enchantLearn.getAllRoutes())
{
if (((route * 100) + skillLvL) == _lvl)
if (((route * 1000) + (_lvl % 1000)) == _lvl)
{
continue;
}
// add other levels of all routes - same lvl as enchanted
// lvl
_routes.add((route * 100) + skillLvL);
_routes.add((route * 1000) + (_lvl % 1000));
}
}
else
// not already enchanted
@ -76,7 +74,7 @@ public final class ExEnchantSkillInfo implements IClientOutgoingPacket
for (int route : enchantLearn.getAllRoutes())
{
// add first level (+1) of all routes
_routes.add((route * 100) + 1);
_routes.add((route * 1000) + 1);
}
}
}
@ -88,11 +86,25 @@ public final class ExEnchantSkillInfo implements IClientOutgoingPacket
OutgoingPackets.EX_ENCHANT_SKILL_INFO.writeId(packet);
packet.writeD(_id);
packet.writeD(_lvl);
if (_lvl < 100)
{
packet.writeD(_lvl);
}
else
{
packet.writeH(_maxlvl);
packet.writeH(_lvl);
}
packet.writeD(_maxEnchanted ? 0 : 1);
packet.writeD(_lvl > 100 ? 1 : 0); // enchanted?
packet.writeD(_lvl > 1000 ? 1 : 0); // enchanted?
packet.writeD(_routes.size());
_routes.forEach(packet::writeD);
for (int level : _routes)
{
packet.writeH(_maxlvl);
packet.writeH(level);
}
return true;
}
}

View File

@ -19,6 +19,7 @@ package com.l2jmobius.gameserver.network.serverpackets;
import com.l2jmobius.Config;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.data.xml.impl.EnchantSkillGroupsData;
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
import com.l2jmobius.gameserver.model.L2EnchantSkillGroup.EnchantSkillHolder;
import com.l2jmobius.gameserver.model.L2EnchantSkillLearn;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
@ -34,6 +35,7 @@ public class ExEnchantSkillInfoDetail implements IClientOutgoingPacket
private static final int TYPE_SAFE_ENCHANT = 1;
private static final int TYPE_UNTRAIN_ENCHANT = 2;
private static final int TYPE_CHANGE_ENCHANT = 3;
private static final int TYPE_IMMORTAL_ENCHANT = 4;
private int bookId = 0;
private int reqCount = 0;
@ -41,21 +43,26 @@ public class ExEnchantSkillInfoDetail implements IClientOutgoingPacket
private final int _type;
private final int _skillid;
private final int _skilllvl;
private final int _maxlvl;
private final int _chance;
private int _sp;
private final int _adenacount;
public ExEnchantSkillInfoDetail(int type, int skillid, int skilllvl, L2PcInstance ply)
{
_type = type;
_skillid = skillid;
_skilllvl = skilllvl;
_maxlvl = SkillData.getInstance().getMaxLevel(_skillid);
final L2EnchantSkillLearn enchantLearn = EnchantSkillGroupsData.getInstance().getSkillEnchantmentBySkillId(skillid);
EnchantSkillHolder esd = null;
// do we have this skill?
if (enchantLearn != null)
{
if (skilllvl > 100)
if (_skilllvl > 1000)
{
esd = enchantLearn.getEnchantSkillHolder(skilllvl);
esd = enchantLearn.getEnchantSkillHolder(_skilllvl);
}
else
{
@ -65,48 +72,125 @@ public class ExEnchantSkillInfoDetail implements IClientOutgoingPacket
if (esd == null)
{
throw new IllegalArgumentException("Skill " + skillid + " dont have enchant data for level " + skilllvl);
throw new IllegalArgumentException("Skill " + skillid + " dont have enchant data for level " + _skilllvl);
}
if (type == 0)
{
multi = Config.NORMAL_ENCHANT_COST_MULTIPLIER;
multi = EnchantSkillGroupsData.NORMAL_ENCHANT_COST_MULTIPLIER;
}
else if (type == 1)
{
multi = Config.SAFE_ENCHANT_COST_MULTIPLIER;
multi = EnchantSkillGroupsData.SAFE_ENCHANT_COST_MULTIPLIER;
}
_chance = esd.getRate(ply);
_sp = esd.getSpCost();
if (type == TYPE_UNTRAIN_ENCHANT)
if (type != TYPE_IMMORTAL_ENCHANT)
{
_sp = (int) (0.8 * _sp);
_chance = esd.getRate(ply);
_sp = esd.getSpCost();
if (type == TYPE_UNTRAIN_ENCHANT)
{
_sp = (int) (0.8 * _sp);
}
_adenacount = esd.getAdenaCost() * multi;
}
else
{
_chance = 100;
_sp = 0;
_adenacount = 0;
}
_adenacount = esd.getAdenaCost() * multi;
_type = type;
_skillid = skillid;
_skilllvl = skilllvl;
final int _elvl = ((_skilllvl % 100) - 1) / 10;
switch (type)
{
case TYPE_NORMAL_ENCHANT:
bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK;
reqCount = (((_skilllvl % 100) > 1) ? 0 : 1);
{
if (ply.getClassId().level() < 4)
{
bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_OLD;
}
else if (_elvl == 0)
{
bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK;
}
else if (_elvl == 1)
{
bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_V2;
}
else
{
bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_V3;
}
reqCount = 1;
break;
}
case TYPE_SAFE_ENCHANT:
bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK;
reqCount = 1;
break;
case TYPE_UNTRAIN_ENCHANT:
bookId = EnchantSkillGroupsData.UNTRAIN_ENCHANT_BOOK;
{
if (ply.getClassId().level() < 4)
{
bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_OLD;
}
else if (_elvl == 0)
{
bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK;
}
else if (_elvl == 1)
{
bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_V2;
}
else
{
bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_V3;
}
reqCount = 1;
break;
}
case TYPE_CHANGE_ENCHANT:
bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK;
{
if (ply.getClassId().level() < 4)
{
bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_OLD;
}
else if (_elvl == 0)
{
bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK;
}
else if (_elvl == 1)
{
bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_V2;
}
else
{
bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_V3;
}
reqCount = 1;
break;
}
case TYPE_IMMORTAL_ENCHANT:
{
if (ply.getClassId().level() < 4)
{
bookId = EnchantSkillGroupsData.IMMORTAL_SCROLL;
}
else if (_elvl == 0)
{
bookId = EnchantSkillGroupsData.IMMORTAL_SCROLL;
}
else if (_elvl == 1)
{
bookId = EnchantSkillGroupsData.IMMORTAL_SCROLL_V2;
}
else
{
bookId = EnchantSkillGroupsData.IMMORTAL_SCROLL_V3;
}
reqCount = 1;
break;
}
default:
{
return;
}
}
if ((type != TYPE_SAFE_ENCHANT) && !Config.ES_SP_BOOK_NEEDED)
@ -122,7 +206,8 @@ public class ExEnchantSkillInfoDetail implements IClientOutgoingPacket
packet.writeD(_type);
packet.writeD(_skillid);
packet.writeD(_skilllvl);
packet.writeH(_maxlvl);
packet.writeH(_skilllvl);
packet.writeQ(_sp * multi); // sp
packet.writeD(_chance); // exp
packet.writeD(0x02); // items count?

View File

@ -16,11 +16,10 @@
*/
package com.l2jmobius.gameserver.network.serverpackets;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.List;
import com.l2jmobius.commons.network.PacketWriter;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.client.OutgoingPackets;
public class ExEnchantSkillList implements IClientOutgoingPacket
@ -34,16 +33,29 @@ public class ExEnchantSkillList implements IClientOutgoingPacket
}
private final EnchantSkillType _type;
private final List<Skill> _skills = new LinkedList<>();
private final List<Skill> _skills;
static class Skill
{
public int id;
public int nextLevel;
Skill(int pId, int pNextLevel)
{
id = pId;
nextLevel = pNextLevel;
}
}
public void addSkill(int id, int level)
{
_skills.add(new Skill(id, level));
}
public ExEnchantSkillList(EnchantSkillType type)
{
_type = type;
}
public void addSkill(Skill skill)
{
_skills.add(skill);
_skills = new ArrayList<>();
}
@Override
@ -53,10 +65,10 @@ public class ExEnchantSkillList implements IClientOutgoingPacket
packet.writeD(_type.ordinal());
packet.writeD(_skills.size());
for (Skill skill : _skills)
for (Skill sk : _skills)
{
packet.writeD(skill.getId());
packet.writeD(skill.getLevel());
packet.writeD(sk.id);
packet.writeD(sk.nextLevel);
}
return true;
}