· 10 years ago · Aug 24, 2016, 01:44 AM
1diff --git a/l2junity-gameserver/dist/game/data/xsd/enchantSkillGroups.xsd b/l2junity-gameserver/dist/game/data/xsd/enchantSkillGroups.xsd
2index 2f7ff23..46302de 100644
3--- a/l2junity-gameserver/dist/game/data/xsd/enchantSkillGroups.xsd
4+++ b/l2junity-gameserver/dist/game/data/xsd/enchantSkillGroups.xsd
5@@ -203,6 +203,70 @@
6 </xs:restriction>
7 </xs:simpleType>
8 </xs:attribute>
9+ <xs:attribute name="chance100" use="optional">
10+ <xs:simpleType>
11+ <xs:restriction base="xs:integer">
12+ <xs:minInclusive value="0" />
13+ <xs:maxInclusive value="100" />
14+ </xs:restriction>
15+ </xs:simpleType>
16+ </xs:attribute>
17+ <xs:attribute name="chance101" use="optional">
18+ <xs:simpleType>
19+ <xs:restriction base="xs:integer">
20+ <xs:minInclusive value="0" />
21+ <xs:maxInclusive value="100" />
22+ </xs:restriction>
23+ </xs:simpleType>
24+ </xs:attribute>
25+ <xs:attribute name="chance102" use="optional">
26+ <xs:simpleType>
27+ <xs:restriction base="xs:integer">
28+ <xs:minInclusive value="0" />
29+ <xs:maxInclusive value="100" />
30+ </xs:restriction>
31+ </xs:simpleType>
32+ </xs:attribute>
33+ <xs:attribute name="chance103" use="optional">
34+ <xs:simpleType>
35+ <xs:restriction base="xs:integer">
36+ <xs:minInclusive value="0" />
37+ <xs:maxInclusive value="100" />
38+ </xs:restriction>
39+ </xs:simpleType>
40+ </xs:attribute>
41+ <xs:attribute name="chance104" use="optional">
42+ <xs:simpleType>
43+ <xs:restriction base="xs:integer">
44+ <xs:minInclusive value="0" />
45+ <xs:maxInclusive value="100" />
46+ </xs:restriction>
47+ </xs:simpleType>
48+ </xs:attribute>
49+ <xs:attribute name="chance105" use="optional">
50+ <xs:simpleType>
51+ <xs:restriction base="xs:integer">
52+ <xs:minInclusive value="0" />
53+ <xs:maxInclusive value="100" />
54+ </xs:restriction>
55+ </xs:simpleType>
56+ </xs:attribute>
57+ <xs:attribute name="chance106" use="optional">
58+ <xs:simpleType>
59+ <xs:restriction base="xs:integer">
60+ <xs:minInclusive value="0" />
61+ <xs:maxInclusive value="100" />
62+ </xs:restriction>
63+ </xs:simpleType>
64+ </xs:attribute>
65+ <xs:attribute name="chance107" use="optional">
66+ <xs:simpleType>
67+ <xs:restriction base="xs:integer">
68+ <xs:minInclusive value="0" />
69+ <xs:maxInclusive value="100" />
70+ </xs:restriction>
71+ </xs:simpleType>
72+ </xs:attribute>
73 <xs:attribute name="exp" type="xs:nonNegativeInteger" use="optional" />
74 <xs:attribute name="level" use="required">
75 <xs:simpleType>
76diff --git a/l2junity-gameserver/dist/sql/game/character_shortcuts.sql b/l2junity-gameserver/dist/sql/game/character_shortcuts.sql
77index c57e137..37dd5b0 100644
78--- a/l2junity-gameserver/dist/sql/game/character_shortcuts.sql
79+++ b/l2junity-gameserver/dist/sql/game/character_shortcuts.sql
80@@ -8,4 +8,5 @@ CREATE TABLE IF NOT EXISTS `character_shortcuts` (
81 `class_index` int(1) NOT NULL DEFAULT '0',
82 PRIMARY KEY (`charId`,`slot`,`page`,`class_index`),
83 KEY `shortcut_id` (`shortcut_id`)
84-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
85\ No newline at end of file
86+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
87+ALTER TABLE `character_shortcuts` MODIFY COLUMN `level` INT(4);
88\ No newline at end of file
89diff --git a/l2junity-gameserver/dist/sql/game/character_skills.sql b/l2junity-gameserver/dist/sql/game/character_skills.sql
90index c7532d9..7086d72 100644
91--- a/l2junity-gameserver/dist/sql/game/character_skills.sql
92+++ b/l2junity-gameserver/dist/sql/game/character_skills.sql
93@@ -4,4 +4,5 @@ CREATE TABLE IF NOT EXISTS `character_skills` (
94 `skill_level` INT(3) NOT NULL DEFAULT 1,
95 `class_index` INT(1) NOT NULL DEFAULT 0,
96 PRIMARY KEY (`charId`,`skill_id`,`class_index`)
97-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
98\ No newline at end of file
99+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
100+ALTER TABLE `character_skills` MODIFY COLUMN `skill_level` INT(4);
101\ No newline at end of file
102diff --git a/l2junity-gameserver/dist/sql/game/character_skills_save.sql b/l2junity-gameserver/dist/sql/game/character_skills_save.sql
103index 7b1692e..871e6b5 100644
104--- a/l2junity-gameserver/dist/sql/game/character_skills_save.sql
105+++ b/l2junity-gameserver/dist/sql/game/character_skills_save.sql
106@@ -9,4 +9,5 @@ CREATE TABLE IF NOT EXISTS `character_skills_save` (
107 `class_index` INT(1) NOT NULL DEFAULT 0,
108 `buff_index` INT(2) NOT NULL DEFAULT 0,
109 PRIMARY KEY (`charId`,`skill_id`,`skill_level`,`class_index`)
110-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
111\ No newline at end of file
112+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
113+ALTER TABLE `character_skills_save` MODIFY COLUMN `skill_level` INT(4);
114\ No newline at end of file
115diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/data/xml/impl/EnchantSkillGroupsData.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/data/xml/impl/EnchantSkillGroupsData.java
116index 5f54f1b..0596e78 100644
117--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/data/xml/impl/EnchantSkillGroupsData.java
118+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/data/xml/impl/EnchantSkillGroupsData.java
119@@ -48,6 +48,22 @@ public class EnchantSkillGroupsData implements IGameXmlReader
120 public static final int CHANGE_ENCHANT_BOOK = 9626;
121 public static final int UNTRAIN_ENCHANT_BOOK = 9625;
122
123+ public static final int NORMAL_ENCHANT_BOOK_GIANT = 30297;
124+ public static final int SAFE_ENCHANT_BOOK_GIANT = 30298;
125+ public static final int CHANGE_ENCHANT_BOOK_GIANT = 30299;
126+ public static final int UNTRAIN_ENCHANT_BOOK_GIANT = 30300;
127+ public static final int IMMORTAL_SCROLL_GIANT = 37044;
128+
129+ public static final int NORMAL_ENCHANT_BOOK_GIANT_C1 = 46150;
130+ public static final int SAFE_ENCHANT_BOOK_GIANT_C1 = 46151;
131+ public static final int CHANGE_ENCHANT_BOOK_GIANT_C1 = 46152;
132+ public static final int IMMORTAL_SCROLL_GIANT_C1 = 46153;
133+
134+ public static final int NORMAL_ENCHANT_BOOK_GIANT_C2 = 46154;
135+ public static final int SAFE_ENCHANT_BOOK_GIANT_C2 = 46155;
136+ public static final int CHANGE_ENCHANT_BOOK_GIANT_C2 = 46156;
137+ public static final int IMMORTAL_SCROLL_GIANT_C2 = 46157;
138+
139 private final Map<Integer, EnchantSkillGroup> _enchantSkillGroups = new HashMap<>();
140 private final Map<Integer, EnchantSkillLearn> _enchantSkillTrees = new HashMap<>();
141
142diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/model/EnchantSkillLearn.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/model/EnchantSkillLearn.java
143index 8066d90..a4bbf16 100644
144--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/model/EnchantSkillLearn.java
145+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/model/EnchantSkillLearn.java
146@@ -59,17 +59,17 @@ public final class EnchantSkillLearn
147
148 public static int getEnchantRoute(int level)
149 {
150- return (int) Math.floor(level / 100);
151+ return (int) Math.floor(level / 1000);
152 }
153
154 public static int getEnchantIndex(int level)
155 {
156- return (level % 100) - 1;
157+ return (level % 1000) - 1;
158 }
159
160 public static int getEnchantType(int level)
161 {
162- return ((level - 1) / 100) - 1;
163+ return ((level - 1) / 1000) - 1;
164 }
165
166 public EnchantSkillGroup getFirstRouteGroup()
167@@ -84,7 +84,7 @@ public final class EnchantSkillLearn
168
169 public int getMinSkillLevel(int level)
170 {
171- if ((level % 100) == 1)
172+ if ((level % 1000) == 1)
173 {
174 return _baseLvl;
175 }
176diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestAcquireSkill.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestAcquireSkill.java
177index 31b7f3e..9971e7e 100644
178--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestAcquireSkill.java
179+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestAcquireSkill.java
180@@ -105,7 +105,7 @@ public final class RequestAcquireSkill implements IClientIncomingPacket
181 return;
182 }
183
184- if ((_level < 1) || (_level > 1000) || (_id < 1) || (_id > 32000))
185+ if ((_level < 1) || (_level > 10000) || (_id < 1) || (_id > 32000))
186 {
187 Util.handleIllegalPlayerAction(activeChar, "Wrong Packet Data in Aquired Skill", Config.DEFAULT_PUNISH);
188 _log.warn("Recived Wrong Packet Data in Aquired Skill - id: " + _id + " level: " + _level + " for " + activeChar);
189diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestDispel.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestDispel.java
190index 4ba11d8..c3e4874 100644
191--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestDispel.java
192+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestDispel.java
193@@ -35,13 +35,22 @@ public class RequestDispel implements IClientIncomingPacket
194 private int _objectId;
195 private int _skillId;
196 private int _skillLevel;
197+ private int _fullLevel;
198
199 @Override
200 public boolean read(L2GameClient client, PacketReader packet)
201 {
202 _objectId = packet.readD();
203 _skillId = packet.readD();
204- _skillLevel = packet.readD();
205+ _fullLevel = packet.readD();
206+ if (_fullLevel < 100)
207+ {
208+ _skillLevel = _fullLevel;
209+ }
210+ else
211+ {
212+ _skillLevel = _fullLevel >> 16;
213+ }
214 return true;
215 }
216
217diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkill.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkill.java
218index 264fcb9..947e31a 100644
219--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkill.java
220+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkill.java
221@@ -47,14 +47,25 @@ public final class RequestExEnchantSkill implements IClientIncomingPacket
222 {
223 private static final Logger _logEnchant = LoggerFactory.getLogger("enchant.skills");
224
225+ private int _type;
226 private int _skillId;
227 private int _skillLvl;
228+ private int _fullLvl;
229
230 @Override
231 public boolean read(L2GameClient client, PacketReader packet)
232 {
233+ _type = packet.readD();
234 _skillId = packet.readD();
235- _skillLvl = packet.readD();
236+ _fullLvl = packet.readD();
237+ if (_fullLvl < 100)
238+ {
239+ _skillLvl = _fullLvl;
240+ }
241+ else
242+ {
243+ _skillLvl = _fullLvl >> 16;
244+ }
245 return true;
246 }
247
248@@ -107,63 +118,399 @@ public final class RequestExEnchantSkill implements IClientIncomingPacket
249 {
250 return;
251 }
252- final EnchantSkillHolder esd = s.getEnchantSkillHolder(_skillLvl);
253- final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
254- if (beforeEnchantSkillLevel != s.getMinSkillLevel(_skillLvl))
255- {
256- return;
257- }
258-
259- final int costMultiplier = Config.NORMAL_ENCHANT_COST_MULTIPLIER;
260- final int requiredSp = esd.getSpCost() * costMultiplier;
261- if (player.getSp() >= requiredSp)
262+ final int _group = ((_skillLvl % 100) - 1) / 10;
263+ if (_type == 0) // enchant
264 {
265- // only first lvl requires book
266- final boolean usesBook = (_skillLvl % 100) == 1; // 101, 201, 301 ...
267- final int reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK;
268- final ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
269-
270- if (Config.ES_SP_BOOK_NEEDED && usesBook && (spb == null)) // Haven't spellbook
271+ final EnchantSkillHolder esd = s.getEnchantSkillHolder(_skillLvl);
272+ final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
273+ if (beforeEnchantSkillLevel != s.getMinSkillLevel(_skillLvl))
274 {
275- client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
276 return;
277 }
278
279- final int requiredAdena = (esd.getAdenaCost() * costMultiplier);
280- if (player.getInventory().getAdena() < requiredAdena)
281+ final int costMultiplier = Config.NORMAL_ENCHANT_COST_MULTIPLIER;
282+ final int requiredSp = esd.getSpCost() * costMultiplier;
283+ if (player.getSp() >= requiredSp)
284+ {
285+ final int reqItemId;
286+ if (player.getClassId().level() == 3)
287+ {
288+ reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK;
289+ }
290+ else
291+ {
292+ if (_group == 0)
293+ {
294+ reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_GIANT;
295+ }
296+ else if (_group == 1)
297+ {
298+ reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_GIANT_C1;
299+ }
300+ else
301+ {
302+ reqItemId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_GIANT_C2;
303+ }
304+ }
305+ final ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
306+
307+ if (Config.ES_SP_BOOK_NEEDED && (spb == null)) // Haven't spellbook
308+ {
309+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
310+ return;
311+ }
312+
313+ final int requiredAdena = (esd.getAdenaCost() * costMultiplier);
314+ if (player.getInventory().getAdena() < requiredAdena)
315+ {
316+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
317+ return;
318+ }
319+
320+ boolean check = player.getStat().removeExpAndSp(0, requiredSp, false);
321+ if (Config.ES_SP_BOOK_NEEDED)
322+ {
323+ check &= player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
324+ }
325+
326+ check &= player.destroyItemByItemId("Consume", Inventory.ADENA_ID, requiredAdena, player, true);
327+ if (!check)
328+ {
329+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
330+ return;
331+ }
332+
333+ // ok. Destroy ONE copy of the book
334+ final int rate = esd.getRate(player);
335+ if (Rnd.get(100) <= rate)
336+ {
337+ if (Config.LOG_SKILL_ENCHANTS)
338+ {
339+ if (skill.getLevel() > 100)
340+ {
341+ if (spb != null)
342+ {
343+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
344+ }
345+ else
346+ {
347+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), rate);
348+ }
349+ }
350+ else
351+ {
352+ if (spb != null)
353+ {
354+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
355+ }
356+ else
357+ {
358+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), rate);
359+ }
360+ }
361+ }
362+
363+ player.addSkill(skill, true);
364+ client.sendPacket(ExEnchantSkillResult.valueOf(true));
365+
366+ final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SKILL_ENCHANT_WAS_SUCCESSFUL_S1_HAS_BEEN_ENCHANTED);
367+ sm.addSkillName(_skillId);
368+ client.sendPacket(sm);
369+
370+ if (Config.DEBUG)
371+ {
372+ _log.debug("Learned skill ID: " + _skillId + " Level: " + _skillLvl + " for " + requiredSp + " SP, " + requiredAdena + " Adena.");
373+ }
374+ }
375+ else
376+ {
377+ if (player.getClassId().level() == 3)
378+ {
379+ player.addSkill(SkillData.getInstance().getSkill(_skillId, s.getBaseLevel()), true);
380+ }
381+ else
382+ {
383+ final int _clvl = ((((_skillLvl % 100) - 1) / 10) * 10) + ((_skillLvl / 1000) * 1000);
384+ player.addSkill(SkillData.getInstance().getSkill(_skillId, _clvl), true);
385+ }
386+ client.sendPacket(SystemMessageId.SKILL_ENCHANT_FAILED_THE_SKILL_WILL_BE_INITIALIZED);
387+ client.sendPacket(ExEnchantSkillResult.valueOf(false));
388+
389+ if (Config.LOG_SKILL_ENCHANTS)
390+ {
391+ if (skill.getLevel() > 100)
392+ {
393+ if (spb != null)
394+ {
395+ _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
396+ }
397+ else
398+ {
399+ _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), rate);
400+ }
401+ }
402+ else
403+ {
404+ if (spb != null)
405+ {
406+ _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
407+ }
408+ else
409+ {
410+ _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), rate);
411+ }
412+ }
413+ }
414+ }
415+
416+ client.sendPacket(new UserInfo(player));
417+ player.sendSkillList();
418+ final int afterEnchantSkillLevel = player.getSkillLevel(_skillId);
419+ client.sendPacket(new ExEnchantSkillInfo(_skillId, afterEnchantSkillLevel));
420+ client.sendPacket(new ExEnchantSkillInfoDetail(0, _skillId, afterEnchantSkillLevel + 1, player));
421+ player.updateShortCuts(_skillId, afterEnchantSkillLevel);
422+ }
423+ else
424+ {
425+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_SP_TO_ENCHANT_THAT_SKILL);
426+ }
427+ }
428+ else if (_type == 1) // safe enchant
429+ {
430+ final EnchantSkillHolder esd = s.getEnchantSkillHolder(_skillLvl);
431+ final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
432+ if (beforeEnchantSkillLevel != s.getMinSkillLevel(_skillLvl))
433 {
434- client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
435 return;
436 }
437
438- boolean check = player.getStat().removeExpAndSp(0, requiredSp, false);
439- if (Config.ES_SP_BOOK_NEEDED && usesBook)
440+ final int costMultiplier = Config.SAFE_ENCHANT_COST_MULTIPLIER;
441+ final int requiredSp = esd.getSpCost() * costMultiplier;
442+ if (player.getSp() >= requiredSp)
443 {
444- check &= player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
445+ final int reqItemId;
446+ if (player.getClassId().level() == 3)
447+ {
448+ reqItemId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK;
449+ }
450+ else
451+ {
452+ if (_group == 0)
453+ {
454+ reqItemId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_GIANT;
455+ }
456+ else if (_group == 1)
457+ {
458+ reqItemId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_GIANT_C1;
459+ }
460+ else
461+ {
462+ reqItemId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_GIANT_C2;
463+ }
464+ }
465+ final ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
466+
467+ if (Config.ES_SP_BOOK_NEEDED && (spb == null)) // Haven't spellbook
468+ {
469+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
470+ return;
471+ }
472+
473+ final int requiredAdena = (esd.getAdenaCost() * costMultiplier);
474+ if (player.getInventory().getAdena() < requiredAdena)
475+ {
476+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
477+ return;
478+ }
479+
480+ boolean check = player.getStat().removeExpAndSp(0, requiredSp, false);
481+ if (Config.ES_SP_BOOK_NEEDED)
482+ {
483+ check &= player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
484+ }
485+
486+ check &= player.destroyItemByItemId("Consume", Inventory.ADENA_ID, requiredAdena, player, true);
487+ if (!check)
488+ {
489+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
490+ return;
491+ }
492+
493+ final int rate = esd.getRate(player);
494+ if (Rnd.get(100) <= rate)
495+ {
496+ if (Config.LOG_SKILL_ENCHANTS)
497+ {
498+ if (skill.getLevel() > 100)
499+ {
500+ if (spb != null)
501+ {
502+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
503+ }
504+ else
505+ {
506+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), rate);
507+ }
508+ }
509+ else
510+ {
511+ if (spb != null)
512+ {
513+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
514+ }
515+ else
516+ {
517+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), rate);
518+ }
519+ }
520+ }
521+
522+ player.addSkill(skill, true);
523+ client.sendPacket(ExEnchantSkillResult.valueOf(true));
524+
525+ final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SKILL_ENCHANT_WAS_SUCCESSFUL_S1_HAS_BEEN_ENCHANTED);
526+ sm.addSkillName(_skillId);
527+ client.sendPacket(sm);
528+
529+ if (Config.DEBUG)
530+ {
531+ _log.debug("Learned skill ID: " + _skillId + " Level: " + _skillLvl + " for " + requiredSp + " SP, " + requiredAdena + " Adena.");
532+ }
533+ }
534+ else
535+ {
536+ client.sendPacket(SystemMessageId.SKILL_ENCHANT_FAILED_THE_SKILL_WILL_BE_INITIALIZED);
537+ client.sendPacket(ExEnchantSkillResult.valueOf(false));
538+
539+ if (Config.LOG_SKILL_ENCHANTS)
540+ {
541+ if (skill.getLevel() > 100)
542+ {
543+ if (spb != null)
544+ {
545+ _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
546+ }
547+ else
548+ {
549+ _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), rate);
550+ }
551+ }
552+ else
553+ {
554+ if (spb != null)
555+ {
556+ _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
557+ }
558+ else
559+ {
560+ _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), rate);
561+ }
562+ }
563+ }
564+ }
565+
566+ client.sendPacket(new UserInfo(player));
567+ player.sendSkillList();
568+ final int afterEnchantSkillLevel = player.getSkillLevel(_skillId);
569+ client.sendPacket(new ExEnchantSkillInfo(_skillId, afterEnchantSkillLevel));
570+ client.sendPacket(new ExEnchantSkillInfoDetail(1, _skillId, afterEnchantSkillLevel + 1, player));
571+ player.updateShortCuts(_skillId, afterEnchantSkillLevel);
572+ }
573+ else
574+ {
575+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_SP_TO_ENCHANT_THAT_SKILL);
576+ }
577+ }
578+ else if (_type == 2) // untrain
579+ {
580+ return;
581+ }
582+ if (_type == 3) // change route
583+ {
584+ final EnchantSkillHolder esd = s.getEnchantSkillHolder(_skillLvl);
585+ final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
586+ if (beforeEnchantSkillLevel <= 1000)
587+ {
588+ return;
589 }
590
591- check &= player.destroyItemByItemId("Consume", Inventory.ADENA_ID, requiredAdena, player, true);
592- if (!check)
593+ if ((beforeEnchantSkillLevel % 1000) != (_skillLvl % 1000))
594 {
595- client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
596 return;
597 }
598
599- // ok. Destroy ONE copy of the book
600- final int rate = esd.getRate(player);
601- if (Rnd.get(100) <= rate)
602+ final int requiredSp = esd.getSpCost();
603+ if (player.getSp() >= requiredSp)
604 {
605+ final int reqItemId;
606+ if (player.getClassId().level() == 3)
607+ {
608+ reqItemId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK;
609+ }
610+ else
611+ {
612+ if (_group == 0)
613+ {
614+ reqItemId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_GIANT;
615+ }
616+ else if (_group == 1)
617+ {
618+ reqItemId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_GIANT_C1;
619+ }
620+ else
621+ {
622+ reqItemId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_GIANT_C2;
623+ }
624+ }
625+ final ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
626+
627+ if (Config.ES_SP_BOOK_NEEDED && (spb == null)) // Haven't spellbook
628+ {
629+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
630+ return;
631+ }
632+
633+ final int requiredAdena = esd.getAdenaCost();
634+ if (player.getInventory().getAdena() < requiredAdena)
635+ {
636+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
637+ return;
638+ }
639+
640+ boolean check = player.getStat().removeExpAndSp(0, requiredSp, false);
641+ if (Config.ES_SP_BOOK_NEEDED)
642+ {
643+ check &= player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
644+ }
645+
646+ check &= player.destroyItemByItemId("Consume", Inventory.ADENA_ID, requiredAdena, player, true);
647+ if (!check)
648+ {
649+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
650+ return;
651+ }
652+
653+ final int rate = Rnd.get(4);
654+ if (rate >= (beforeEnchantSkillLevel % 1000))
655+ {
656+ _skillLvl = s.getBaseLevel();
657+ }
658+ else
659+ {
660+ _skillLvl -= rate;
661+ }
662+
663 if (Config.LOG_SKILL_ENCHANTS)
664 {
665 if (skill.getLevel() > 100)
666 {
667 if (spb != null)
668 {
669- _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 100, skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
670+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
671 }
672 else
673 {
674- _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 100, skill.getName(), skill.getId(), rate);
675+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), rate);
676 }
677 }
678 else
679@@ -179,61 +526,130 @@ public final class RequestExEnchantSkill implements IClientIncomingPacket
680 }
681 }
682
683- player.addSkill(skill, true);
684+ player.addSkill(SkillData.getInstance().getSkill(_skillId, _skillLvl), true);
685 client.sendPacket(ExEnchantSkillResult.valueOf(true));
686
687- final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SKILL_ENCHANT_WAS_SUCCESSFUL_S1_HAS_BEEN_ENCHANTED);
688- sm.addSkillName(_skillId);
689- client.sendPacket(sm);
690+ if (rate == 0)
691+ {
692+ final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.ENCHANT_SKILL_ROUTE_CHANGE_WAS_SUCCESSFUL_LV_OF_ENCHANT_SKILL_S1_WILL_REMAIN);
693+ sm.addSkillName(_skillId);
694+ client.sendPacket(sm);
695+ }
696+ else
697+ {
698+ final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.ENCHANT_SKILL_ROUTE_CHANGE_WAS_SUCCESSFUL_LV_OF_ENCHANT_SKILL_S1_HAS_BEEN_DECREASED_BY_S2);
699+ sm.addSkillName(_skillId);
700+
701+ if (_skillLvl > 1000)
702+ {
703+ sm.addInt(_skillLvl % 1000);
704+ }
705+ else
706+ {
707+ sm.addInt(0);
708+ }
709+ client.sendPacket(sm);
710+ }
711
712 if (Config.DEBUG)
713 {
714 _log.debug("Learned skill ID: " + _skillId + " Level: " + _skillLvl + " for " + requiredSp + " SP, " + requiredAdena + " Adena.");
715 }
716+
717+ client.sendPacket(new UserInfo(player));
718+ player.sendSkillList();
719+ final int afterEnchantSkillLevel = player.getSkillLevel(_skillId);
720+ client.sendPacket(new ExEnchantSkillInfo(_skillId, afterEnchantSkillLevel));
721+ client.sendPacket(new ExEnchantSkillInfoDetail(3, _skillId, afterEnchantSkillLevel, player));
722+ player.updateShortCuts(_skillId, afterEnchantSkillLevel);
723 }
724 else
725 {
726- player.addSkill(SkillData.getInstance().getSkill(_skillId, s.getBaseLevel()), true);
727- client.sendPacket(SystemMessageId.SKILL_ENCHANT_FAILED_THE_SKILL_WILL_BE_INITIALIZED);
728- client.sendPacket(ExEnchantSkillResult.valueOf(false));
729-
730- if (Config.LOG_SKILL_ENCHANTS)
731+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_SP_TO_ENCHANT_THAT_SKILL);
732+ }
733+ }
734+ else if (_type == 4) // 100% enchant
735+ {
736+ final int beforeEnchantSkillLevel = player.getSkillLevel(_skillId);
737+ if (beforeEnchantSkillLevel != s.getMinSkillLevel(_skillLvl))
738+ {
739+ return;
740+ }
741+
742+ final int reqItemId;
743+ if (player.getClassId().level() == 3)
744+ {
745+ reqItemId = EnchantSkillGroupsData.IMMORTAL_SCROLL_GIANT;
746+ }
747+ else
748+ {
749+ if (_group == 0)
750 {
751- if (skill.getLevel() > 100)
752+ reqItemId = EnchantSkillGroupsData.IMMORTAL_SCROLL_GIANT;
753+ }
754+ else if (_group == 1)
755+ {
756+ reqItemId = EnchantSkillGroupsData.IMMORTAL_SCROLL_GIANT_C1;
757+ }
758+ else
759+ {
760+ reqItemId = EnchantSkillGroupsData.IMMORTAL_SCROLL_GIANT_C2;
761+ }
762+ }
763+ final ItemInstance spb = player.getInventory().getItemByItemId(reqItemId);
764+
765+ if (Config.ES_SP_BOOK_NEEDED && (spb == null)) // Haven't spellbook
766+ {
767+ client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ALL_OF_THE_ITEMS_NEEDED_TO_ENCHANT_THAT_SKILL);
768+ return;
769+ }
770+
771+ player.destroyItem("Consume", spb.getObjectId(), 1, player, true);
772+
773+ if (Config.LOG_SKILL_ENCHANTS)
774+ {
775+ if (skill.getLevel() > 100)
776+ {
777+ if (spb != null)
778 {
779- if (spb != null)
780- {
781- _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 100, skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
782- }
783- else
784- {
785- _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 100, skill.getName(), skill.getId(), rate);
786- }
787+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), 100);
788 }
789 else
790 {
791- if (spb != null)
792- {
793- _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), rate);
794- }
795- else
796- {
797- _logEnchant.info("Fail, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), rate);
798- }
799+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, +{} {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getLevel() % 1000, skill.getName(), skill.getId(), 100);
800+ }
801+ }
802+ else
803+ {
804+ if (spb != null)
805+ {
806+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), spb.getName(), spb.getCount(), spb.getObjectId(), 100);
807+ }
808+ else
809+ {
810+ _logEnchant.info("Success, Character:{} [{}] Account:{} IP:{}, {}({}), {}({}) [{}], {}", player.getName(), player.getObjectId(), player.getAccountName(), player.getIPAddress(), skill.getName(), skill.getId(), 100);
811 }
812 }
813 }
814
815+ player.addSkill(skill, true);
816+ client.sendPacket(ExEnchantSkillResult.valueOf(true));
817+
818+ final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.SKILL_ENCHANT_WAS_SUCCESSFUL_S1_HAS_BEEN_ENCHANTED);
819+ sm.addSkillName(_skillId);
820+ client.sendPacket(sm);
821+
822+ if (Config.DEBUG)
823+ {
824+ _log.debug("Learned skill ID: " + _skillId + " Level: " + _skillLvl + " for " + 0 + " SP, " + 0 + " Adena.");
825+ }
826+
827 client.sendPacket(new UserInfo(player));
828 player.sendSkillList();
829 final int afterEnchantSkillLevel = player.getSkillLevel(_skillId);
830 client.sendPacket(new ExEnchantSkillInfo(_skillId, afterEnchantSkillLevel));
831- client.sendPacket(new ExEnchantSkillInfoDetail(0, _skillId, afterEnchantSkillLevel + 1, player));
832+ client.sendPacket(new ExEnchantSkillInfoDetail(1, _skillId, afterEnchantSkillLevel + 1, player));
833 player.updateShortCuts(_skillId, afterEnchantSkillLevel);
834 }
835- else
836- {
837- client.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_SP_TO_ENCHANT_THAT_SKILL);
838- }
839 }
840 }
841diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkillInfo.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkillInfo.java
842index 0f9152b..d76aadb 100644
843--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkillInfo.java
844+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkillInfo.java
845@@ -34,12 +34,21 @@ public final class RequestExEnchantSkillInfo implements IClientIncomingPacket
846 {
847 private int _skillId;
848 private int _skillLvl;
849+ private int _fullLvl;
850
851 @Override
852 public boolean read(L2GameClient client, PacketReader packet)
853 {
854 _skillId = packet.readD();
855- _skillLvl = packet.readD();
856+ _fullLvl = packet.readD();
857+ if (_fullLvl < 100)
858+ {
859+ _skillLvl = _fullLvl;
860+ }
861+ else
862+ {
863+ _skillLvl = _fullLvl >> 16;
864+ }
865 return true;
866 }
867
868diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkillInfoDetail.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkillInfoDetail.java
869index 339bd0c..406aba4 100644
870--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkillInfoDetail.java
871+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestExEnchantSkillInfoDetail.java
872@@ -34,13 +34,22 @@ public final class RequestExEnchantSkillInfoDetail implements IClientIncomingPac
873 private int _type;
874 private int _skillId;
875 private int _skillLvl;
876+ private int _fullLvl;
877
878 @Override
879 public boolean read(L2GameClient client, PacketReader packet)
880 {
881 _type = packet.readD();
882 _skillId = packet.readD();
883- _skillLvl = packet.readD();
884+ _fullLvl = packet.readD();
885+ if (_fullLvl < 100)
886+ {
887+ _skillLvl = _fullLvl;
888+ }
889+ else
890+ {
891+ _skillLvl = _fullLvl >> 16;
892+ }
893 return true;
894 }
895
896@@ -67,7 +76,7 @@ public final class RequestExEnchantSkillInfoDetail implements IClientIncomingPac
897 }
898 else if (_type == 2)
899 {
900- reqSkillLvl = _skillLvl + 1; // untrain
901+ return;
902 }
903 else if (_type == 3)
904 {
905@@ -83,7 +92,7 @@ public final class RequestExEnchantSkillInfoDetail implements IClientIncomingPac
906 }
907
908 // if reqlvl is 100,200,.. check base skill lvl enchant
909- if ((reqSkillLvl % 100) == 0)
910+ if ((reqSkillLvl % 1000) == 0)
911 {
912 EnchantSkillLearn esl = EnchantSkillGroupsData.getInstance().getSkillEnchantmentBySkillId(_skillId);
913 if (esl != null)
914@@ -103,7 +112,7 @@ public final class RequestExEnchantSkillInfoDetail implements IClientIncomingPac
915 else if (playerSkillLvl != reqSkillLvl)
916 {
917 // change route is different skill lvl but same enchant
918- if ((_type == 3) && ((playerSkillLvl % 100) != (_skillLvl % 100)))
919+ if ((_type == 3) && ((playerSkillLvl % 1000) != (_skillLvl % 1000)))
920 {
921 return;
922 }
923diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestShortCutReg.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestShortCutReg.java
924index f0e2f89..803bfaf 100644
925--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestShortCutReg.java
926+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/recv/RequestShortCutReg.java
927@@ -42,8 +42,11 @@ public final class RequestShortCutReg implements IClientIncomingPacket
928 _slot = slot % 12;
929 _page = slot / 12;
930 _id = packet.readD();
931- _lvl = packet.readH();
932- packet.readH(); // Sublevel
933+ _lvl = packet.readD();
934+ if ((typeId == 2) && (_lvl > 10000))
935+ {
936+ _lvl = _lvl >> 16;
937+ }
938 _characterType = packet.readD();
939 return true;
940 }
941diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AbnormalStatusUpdate.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AbnormalStatusUpdate.java
942index 4a1cf02..ed9c804 100644
943--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AbnormalStatusUpdate.java
944+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AbnormalStatusUpdate.java
945@@ -21,6 +21,7 @@ package org.l2junity.gameserver.network.client.send;
946 import java.util.ArrayList;
947 import java.util.List;
948
949+import org.l2junity.gameserver.data.xml.impl.SkillData;
950 import org.l2junity.gameserver.model.skills.BuffInfo;
951 import org.l2junity.gameserver.model.skills.Skill;
952 import org.l2junity.gameserver.network.client.OutgoingPackets;
953@@ -58,8 +59,8 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
954 if ((info != null) && info.isInUse())
955 {
956 packet.writeD(info.getSkill().getDisplayId());
957- packet.writeH(info.getSkill().getDisplayLevel());
958- packet.writeH(0x00); // Sub level
959+ packet.writeH(info.getSkill().getDisplayLevel() < 100 ? info.getSkill().getDisplayLevel() : SkillData.getInstance().getMaxLevel(info.getSkill().getDisplayId()));
960+ packet.writeH(info.getSkill().getDisplayLevel() < 100 ? 0 : info.getSkill().getDisplayLevel());
961 packet.writeD(info.getSkill().getAbnormalType().getClientId());
962 writeOptionalD(packet, info.getSkill().isAura() ? -1 : info.getTime());
963 }
964@@ -69,8 +70,8 @@ public class AbnormalStatusUpdate implements IClientOutgoingPacket
965 if (skill != null)
966 {
967 packet.writeD(skill.getDisplayId());
968- packet.writeH(skill.getDisplayLevel());
969- packet.writeH(0x00); // Sub level
970+ packet.writeH(skill.getDisplayLevel() < 100 ? skill.getDisplayLevel() : SkillData.getInstance().getMaxLevel(skill.getDisplayId()));
971+ packet.writeH(skill.getDisplayLevel() < 100 ? 0 : skill.getDisplayLevel());
972 packet.writeD(skill.getAbnormalType().getClientId());
973 packet.writeH(-1);
974 }
975diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AbstractMessagePacket.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AbstractMessagePacket.java
976index c66c5d3..2ba6ab8 100644
977--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AbstractMessagePacket.java
978+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AbstractMessagePacket.java
979@@ -21,6 +21,7 @@ package org.l2junity.gameserver.network.client.send;
980 import java.io.PrintStream;
981 import java.util.Arrays;
982
983+import org.l2junity.gameserver.data.xml.impl.SkillData;
984 import org.l2junity.gameserver.datatables.ItemTable;
985 import org.l2junity.gameserver.model.actor.Creature;
986 import org.l2junity.gameserver.model.actor.Npc;
987@@ -439,8 +440,21 @@ public abstract class AbstractMessagePacket<T extends AbstractMessagePacket<?>>
988 {
989 final int[] array = param.getIntArrayValue();
990 packet.writeD(array[0]); // skill id
991- packet.writeH(array[1]); // skill level
992- packet.writeH(0x00); // skill sub level
993+ if (array[1] < 100)
994+ {
995+ packet.writeH(array[1]);
996+ packet.writeH(0);
997+ }
998+ else if (array[1] > 10000)
999+ {
1000+ packet.writeH((short) array[1]);
1001+ packet.writeH(array[1] >> 16);
1002+ }
1003+ else
1004+ {
1005+ packet.writeH(SkillData.getInstance().getMaxLevel(array[0]));
1006+ packet.writeH(array[1]);
1007+ }
1008 break;
1009 }
1010
1011@@ -509,6 +523,7 @@ public abstract class AbstractMessagePacket<T extends AbstractMessagePacket<?>>
1012 final int[] array = param.getIntArrayValue();
1013 out.println(array[0]); // SkillId
1014 out.println(array[1]); // SkillLevel
1015+ out.println(array[2]); // skill sub level
1016 break;
1017 }
1018
1019diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AcquireSkillInfo.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AcquireSkillInfo.java
1020index ddd07cd..5797a3e 100644
1021--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AcquireSkillInfo.java
1022+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AcquireSkillInfo.java
1023@@ -128,6 +128,7 @@ public class AcquireSkillInfo implements IClientOutgoingPacket
1024 packet.writeQ(temp.count);
1025 packet.writeD(temp.unk);
1026 }
1027+ packet.writeD(0);
1028 return true;
1029 }
1030 }
1031diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AcquireSkillList.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AcquireSkillList.java
1032index d6c5f64..eba6bcc 100644
1033--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AcquireSkillList.java
1034+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/AcquireSkillList.java
1035@@ -22,6 +22,7 @@ import java.util.List;
1036 import java.util.Objects;
1037 import java.util.stream.Collectors;
1038
1039+import org.l2junity.gameserver.data.xml.impl.SkillData;
1040 import org.l2junity.gameserver.data.xml.impl.SkillTreesData;
1041 import org.l2junity.gameserver.model.SkillLearn;
1042 import org.l2junity.gameserver.model.actor.instance.PlayerInstance;
1043@@ -71,7 +72,8 @@ public class AcquireSkillList implements IClientOutgoingPacket
1044 for (Skill skillRemove : skillRem)
1045 {
1046 packet.writeD(skillRemove.getId());
1047- packet.writeD(skillRemove.getLevel());
1048+ packet.writeH(skillRemove.getLevel() < 100 ? skillRemove.getLevel() : SkillData.getInstance().getMaxLevel(skillRemove.getId()));
1049+ packet.writeH(skillRemove.getLevel() < 100 ? 0 : skillRemove.getLevel());
1050 }
1051 }
1052 return true;
1053diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExAbnormalStatusUpdateFromTarget.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExAbnormalStatusUpdateFromTarget.java
1054index d7a1f65..38476bf 100644
1055--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExAbnormalStatusUpdateFromTarget.java
1056+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExAbnormalStatusUpdateFromTarget.java
1057@@ -21,6 +21,7 @@ package org.l2junity.gameserver.network.client.send;
1058 import java.util.ArrayList;
1059 import java.util.List;
1060
1061+import org.l2junity.gameserver.data.xml.impl.SkillData;
1062 import org.l2junity.gameserver.model.actor.Creature;
1063 import org.l2junity.gameserver.model.skills.BuffInfo;
1064 import org.l2junity.gameserver.model.skills.Skill;
1065@@ -36,7 +37,7 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
1066 {
1067 protected int _skillId;
1068 protected int _level;
1069- protected int _subLevel;
1070+ protected int _maxlevel;
1071 protected int _abnormalType;
1072 protected int _duration;
1073 protected int _caster;
1074@@ -53,6 +54,7 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
1075
1076 _skillId = skill.getDisplayId();
1077 _level = skill.getDisplayLevel();
1078+ _maxlevel = SkillData.getInstance().getMaxLevel(_skillId);
1079 _abnormalType = skill.getAbnormalType().getClientId();
1080 _duration = skill.isAura() ? -1 : info.getTime();
1081 _caster = casterId;
1082@@ -90,8 +92,8 @@ public class ExAbnormalStatusUpdateFromTarget implements IClientOutgoingPacket
1083 for (Effect info : _effects)
1084 {
1085 packet.writeD(info._skillId);
1086- packet.writeH(info._level);
1087- packet.writeH(info._subLevel);
1088+ packet.writeH(info._level < 100 ? info._level : info._maxlevel);
1089+ packet.writeH(info._level < 100 ? 0 : info._level);
1090 packet.writeH(info._abnormalType);
1091 writeOptionalD(packet, info._duration);
1092 packet.writeD(info._caster);
1093diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExEnchantSkillInfo.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExEnchantSkillInfo.java
1094index b122b9e..ef04907 100644
1095--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExEnchantSkillInfo.java
1096+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExEnchantSkillInfo.java
1097@@ -22,6 +22,7 @@ import java.util.LinkedList;
1098 import java.util.List;
1099
1100 import org.l2junity.gameserver.data.xml.impl.EnchantSkillGroupsData;
1101+import org.l2junity.gameserver.data.xml.impl.SkillData;
1102 import org.l2junity.gameserver.model.EnchantSkillGroup.EnchantSkillHolder;
1103 import org.l2junity.gameserver.model.EnchantSkillLearn;
1104 import org.l2junity.gameserver.network.client.OutgoingPackets;
1105@@ -33,19 +34,21 @@ public final class ExEnchantSkillInfo implements IClientOutgoingPacket
1106
1107 private final int _id;
1108 private final int _lvl;
1109+ private final int _maxlvl;
1110 private boolean _maxEnchanted = false;
1111
1112 public ExEnchantSkillInfo(int id, int lvl)
1113 {
1114 _id = id;
1115 _lvl = lvl;
1116+ _maxlvl = SkillData.getInstance().getMaxLevel(_id);
1117
1118 EnchantSkillLearn enchantLearn = EnchantSkillGroupsData.getInstance().getSkillEnchantmentBySkillId(_id);
1119 // do we have this skill?
1120 if (enchantLearn != null)
1121 {
1122 // skill already enchanted?
1123- if (_lvl > 100)
1124+ if (_lvl > 1000)
1125 {
1126 _maxEnchanted = enchantLearn.isMaxEnchant(_lvl);
1127
1128@@ -53,22 +56,22 @@ public final class ExEnchantSkillInfo implements IClientOutgoingPacket
1129 EnchantSkillHolder esd = enchantLearn.getEnchantSkillHolder(_lvl);
1130
1131 // if it exists add it
1132- if (esd != null)
1133+ if ((esd != null) && !_maxEnchanted)
1134 {
1135- _routes.add(_lvl); // current enchant add firts
1136+ _routes.add(_lvl + 1); // current enchant add firts
1137 }
1138
1139- int skillLvL = (_lvl % 100);
1140+ int skillLvL = (_lvl % 1000);
1141
1142 for (int route : enchantLearn.getAllRoutes())
1143 {
1144- if (((route * 100) + skillLvL) == _lvl)
1145+ if (((route * 1000) + skillLvL) == _lvl)
1146 {
1147 continue;
1148 }
1149 // add other levels of all routes - same lvl as enchanted
1150 // lvl
1151- _routes.add((route * 100) + skillLvL);
1152+ _routes.add((route * 1000) + skillLvL);
1153 }
1154
1155 }
1156@@ -78,7 +81,7 @@ public final class ExEnchantSkillInfo implements IClientOutgoingPacket
1157 for (int route : enchantLearn.getAllRoutes())
1158 {
1159 // add first level (+1) of all routes
1160- _routes.add((route * 100) + 1);
1161+ _routes.add((route * 1000) + 1);
1162 }
1163 }
1164 }
1165@@ -90,11 +93,16 @@ public final class ExEnchantSkillInfo implements IClientOutgoingPacket
1166 OutgoingPackets.EX_ENCHANT_SKILL_INFO.writeId(packet);
1167
1168 packet.writeD(_id);
1169- packet.writeD(_lvl);
1170+ packet.writeH(_lvl < 100 ? _lvl : _maxlvl);
1171+ packet.writeH(_lvl < 100 ? 0 : _lvl);
1172 packet.writeD(_maxEnchanted ? 0 : 1);
1173- packet.writeD(_lvl > 100 ? 1 : 0); // enchanted?
1174+ packet.writeD(_lvl > 1000 ? 1 : 0); // enchanted?
1175 packet.writeD(_routes.size());
1176- _routes.forEach(packet::writeD);
1177+ for (int _level : _routes)
1178+ {
1179+ packet.writeH(_maxlvl);
1180+ packet.writeH(_level);
1181+ }
1182 return true;
1183 }
1184 }
1185diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExEnchantSkillInfoDetail.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExEnchantSkillInfoDetail.java
1186index b55760c..324d5e6 100644
1187--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExEnchantSkillInfoDetail.java
1188+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ExEnchantSkillInfoDetail.java
1189@@ -20,6 +20,7 @@ package org.l2junity.gameserver.network.client.send;
1190
1191 import org.l2junity.Config;
1192 import org.l2junity.gameserver.data.xml.impl.EnchantSkillGroupsData;
1193+import org.l2junity.gameserver.data.xml.impl.SkillData;
1194 import org.l2junity.gameserver.model.EnchantSkillGroup.EnchantSkillHolder;
1195 import org.l2junity.gameserver.model.EnchantSkillLearn;
1196 import org.l2junity.gameserver.model.actor.instance.PlayerInstance;
1197@@ -36,6 +37,7 @@ public class ExEnchantSkillInfoDetail implements IClientOutgoingPacket
1198 private static final int TYPE_SAFE_ENCHANT = 1;
1199 private static final int TYPE_UNTRAIN_ENCHANT = 2;
1200 private static final int TYPE_CHANGE_ENCHANT = 3;
1201+ private static final int TYPE_IMMORTAL_ENCHANT = 4;
1202
1203 private int bookId = 0;
1204 private int reqCount = 0;
1205@@ -43,6 +45,7 @@ public class ExEnchantSkillInfoDetail implements IClientOutgoingPacket
1206 private final int _type;
1207 private final int _skillid;
1208 private final int _skilllvl;
1209+ private final int _maxlvl;
1210 private final int _chance;
1211 private int _sp;
1212 private final int _adenacount;
1213@@ -55,7 +58,7 @@ public class ExEnchantSkillInfoDetail implements IClientOutgoingPacket
1214 // do we have this skill?
1215 if (enchantLearn != null)
1216 {
1217- if (skilllvl > 100)
1218+ if (skilllvl > 1000)
1219 {
1220 esd = enchantLearn.getEnchantSkillHolder(skilllvl);
1221 }
1222@@ -88,27 +91,111 @@ public class ExEnchantSkillInfoDetail implements IClientOutgoingPacket
1223 _type = type;
1224 _skillid = skillid;
1225 _skilllvl = skilllvl;
1226+ _maxlvl = SkillData.getInstance().getMaxLevel(skillid);
1227+ final int _group = ((_skilllvl % 100) - 1) / 10;
1228
1229 switch (type)
1230 {
1231 case TYPE_NORMAL_ENCHANT:
1232- bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK;
1233- reqCount = (((_skilllvl % 100) > 1) ? 0 : 1);
1234+ {
1235+ if (ply.getClassId().level() < 4)
1236+ {
1237+ bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK;
1238+ }
1239+ else
1240+ {
1241+ if (_group == 0)
1242+ {
1243+ bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_GIANT;
1244+ }
1245+ else if (_group == 1)
1246+ {
1247+ bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_GIANT_C1;
1248+ }
1249+ else
1250+ {
1251+ bookId = EnchantSkillGroupsData.NORMAL_ENCHANT_BOOK_GIANT_C2;
1252+ }
1253+ }
1254+ reqCount = 1;
1255 break;
1256+ }
1257 case TYPE_SAFE_ENCHANT:
1258- bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK;
1259+ {
1260+ if (ply.getClassId().level() < 4)
1261+ {
1262+ bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK;
1263+ }
1264+ else
1265+ {
1266+ if (_group == 0)
1267+ {
1268+ bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_GIANT;
1269+ }
1270+ else if (_group == 1)
1271+ {
1272+ bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_GIANT_C1;
1273+ }
1274+ else
1275+ {
1276+ bookId = EnchantSkillGroupsData.SAFE_ENCHANT_BOOK_GIANT_C2;
1277+ }
1278+ }
1279 reqCount = 1;
1280 break;
1281- case TYPE_UNTRAIN_ENCHANT:
1282- bookId = EnchantSkillGroupsData.UNTRAIN_ENCHANT_BOOK;
1283+ }
1284+ case TYPE_CHANGE_ENCHANT:
1285+ {
1286+ if (ply.getClassId().level() < 4)
1287+ {
1288+ bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK;
1289+ }
1290+ else
1291+ {
1292+ if (_group == 0)
1293+ {
1294+ bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_GIANT;
1295+ }
1296+ else if (_group == 1)
1297+ {
1298+ bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_GIANT_C1;
1299+ }
1300+ else
1301+ {
1302+ bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK_GIANT_C2;
1303+ }
1304+ }
1305 reqCount = 1;
1306 break;
1307- case TYPE_CHANGE_ENCHANT:
1308- bookId = EnchantSkillGroupsData.CHANGE_ENCHANT_BOOK;
1309+ }
1310+ case TYPE_IMMORTAL_ENCHANT:
1311+ {
1312+ if (ply.getClassId().level() < 4)
1313+ {
1314+ bookId = EnchantSkillGroupsData.IMMORTAL_SCROLL_GIANT;
1315+ }
1316+ else
1317+ {
1318+ if (_group == 0)
1319+ {
1320+ bookId = EnchantSkillGroupsData.IMMORTAL_SCROLL_GIANT;
1321+ }
1322+ else if (_group == 1)
1323+ {
1324+ bookId = EnchantSkillGroupsData.IMMORTAL_SCROLL_GIANT_C1;
1325+ }
1326+ else
1327+ {
1328+ bookId = EnchantSkillGroupsData.IMMORTAL_SCROLL_GIANT_C2;
1329+ }
1330+ }
1331 reqCount = 1;
1332 break;
1333+ }
1334 default:
1335+ {
1336 return;
1337+ }
1338 }
1339
1340 if ((type != TYPE_SAFE_ENCHANT) && !Config.ES_SP_BOOK_NEEDED)
1341@@ -124,7 +211,8 @@ public class ExEnchantSkillInfoDetail implements IClientOutgoingPacket
1342
1343 packet.writeD(_type);
1344 packet.writeD(_skillid);
1345- packet.writeD(_skilllvl);
1346+ packet.writeH(_maxlvl);
1347+ packet.writeH(_skilllvl);
1348 packet.writeQ(_sp * multi); // sp
1349 packet.writeD(_chance); // exp
1350 packet.writeD(0x02); // items count?
1351diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/MagicSkillLaunched.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/MagicSkillLaunched.java
1352index 849d4a8..654acea 100644
1353--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/MagicSkillLaunched.java
1354+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/MagicSkillLaunched.java
1355@@ -22,6 +22,7 @@ import java.util.Arrays;
1356 import java.util.Collection;
1357 import java.util.Collections;
1358
1359+import org.l2junity.gameserver.data.xml.impl.SkillData;
1360 import org.l2junity.gameserver.model.WorldObject;
1361 import org.l2junity.gameserver.model.actor.Creature;
1362 import org.l2junity.gameserver.model.skills.SkillCastingType;
1363@@ -37,6 +38,7 @@ public class MagicSkillLaunched implements IClientOutgoingPacket
1364 private final int _charObjId;
1365 private final int _skillId;
1366 private final int _skillLevel;
1367+ private final int _maxLevel;
1368 private final SkillCastingType _castingType;
1369 private final Collection<WorldObject> _targets;
1370
1371@@ -45,6 +47,7 @@ public class MagicSkillLaunched implements IClientOutgoingPacket
1372 _charObjId = cha.getObjectId();
1373 _skillId = skillId;
1374 _skillLevel = skillLevel;
1375+ _maxLevel = SkillData.getInstance().getMaxLevel(_skillId);
1376 _castingType = castingType;
1377
1378 if (targets == null)
1379@@ -73,7 +76,8 @@ public class MagicSkillLaunched implements IClientOutgoingPacket
1380 packet.writeD(_castingType.getClientBarId()); // MagicSkillUse castingType
1381 packet.writeD(_charObjId);
1382 packet.writeD(_skillId);
1383- packet.writeD(_skillLevel);
1384+ packet.writeH(_skillLevel < 100 ? _skillLevel : _maxLevel);
1385+ packet.writeH(_skillLevel < 100 ? 0 : _skillLevel);
1386 packet.writeD(_targets.size());
1387 for (WorldObject target : _targets)
1388 {
1389diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/MagicSkillUse.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/MagicSkillUse.java
1390index 3cfebc2..517872b 100644
1391--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/MagicSkillUse.java
1392+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/MagicSkillUse.java
1393@@ -22,6 +22,7 @@ import java.util.Arrays;
1394 import java.util.Collections;
1395 import java.util.List;
1396
1397+import org.l2junity.gameserver.data.xml.impl.SkillData;
1398 import org.l2junity.gameserver.model.Location;
1399 import org.l2junity.gameserver.model.WorldObject;
1400 import org.l2junity.gameserver.model.actor.Creature;
1401@@ -39,6 +40,7 @@ public final class MagicSkillUse implements IClientOutgoingPacket
1402 {
1403 private final int _skillId;
1404 private final int _skillLevel;
1405+ private final int _maxLevel;
1406 private final int _hitTime;
1407 private final int _reuseGroup;
1408 private final int _reuseDelay;
1409@@ -55,6 +57,7 @@ public final class MagicSkillUse implements IClientOutgoingPacket
1410 _target = target;
1411 _skillId = skillId;
1412 _skillLevel = skillLevel;
1413+ _maxLevel = SkillData.getInstance().getMaxLevel(_skillId);
1414 _hitTime = hitTime;
1415 _reuseGroup = reuseGroup;
1416 _reuseDelay = reuseDelay;
1417@@ -90,7 +93,8 @@ public final class MagicSkillUse implements IClientOutgoingPacket
1418 packet.writeD(_castingType.getClientBarId()); // Casting bar type: 0 - default, 1 - default up, 2 - blue, 3 - green, 4 - red.
1419 packet.writeD(_activeChar.getObjectId());
1420 packet.writeD(_target.getObjectId());
1421- packet.writeD(_skillId);
1422+ packet.writeH(_skillLevel < 100 ? _skillLevel : _maxLevel);
1423+ packet.writeH(_skillLevel < 100 ? 0 : _skillLevel);
1424 packet.writeD(_skillLevel);
1425 packet.writeD(_hitTime);
1426 packet.writeD(_reuseGroup);
1427diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/PartySpelled.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/PartySpelled.java
1428index 05abb31..5d0413d 100644
1429--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/PartySpelled.java
1430+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/PartySpelled.java
1431@@ -21,6 +21,7 @@ package org.l2junity.gameserver.network.client.send;
1432 import java.util.ArrayList;
1433 import java.util.List;
1434
1435+import org.l2junity.gameserver.data.xml.impl.SkillData;
1436 import org.l2junity.gameserver.model.actor.Creature;
1437 import org.l2junity.gameserver.model.skills.BuffInfo;
1438 import org.l2junity.gameserver.model.skills.Skill;
1439@@ -61,8 +62,8 @@ public class PartySpelled implements IClientOutgoingPacket
1440 if ((info != null) && info.isInUse())
1441 {
1442 packet.writeD(info.getSkill().getDisplayId());
1443- packet.writeH(info.getSkill().getDisplayLevel());
1444- packet.writeH(0x00); // Sub level
1445+ packet.writeH(info.getSkill().getDisplayLevel() < 100 ? info.getSkill().getDisplayLevel() : SkillData.getInstance().getMaxLevel(info.getSkill().getDisplayId()));
1446+ packet.writeH(info.getSkill().getDisplayLevel() < 100 ? 0 : info.getSkill().getDisplayLevel());
1447 packet.writeD(info.getSkill().getAbnormalType().getClientId());
1448 writeOptionalD(packet, info.getTime());
1449 }
1450@@ -72,8 +73,8 @@ public class PartySpelled implements IClientOutgoingPacket
1451 if (skill != null)
1452 {
1453 packet.writeD(skill.getDisplayId());
1454- packet.writeH(skill.getDisplayLevel());
1455- packet.writeH(0x00); // Sub level
1456+ packet.writeH(skill.getDisplayLevel() < 100 ? skill.getDisplayLevel() : SkillData.getInstance().getMaxLevel(skill.getDisplayId()));
1457+ packet.writeH(skill.getDisplayLevel() < 100 ? 0 : skill.getDisplayLevel());
1458 packet.writeD(skill.getAbnormalType().getClientId());
1459 packet.writeH(-1);
1460 }
1461diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ShortCutInit.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ShortCutInit.java
1462index 16c8c74..afa11f0 100644
1463--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ShortCutInit.java
1464+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ShortCutInit.java
1465@@ -18,6 +18,7 @@
1466 */
1467 package org.l2junity.gameserver.network.client.send;
1468
1469+import org.l2junity.gameserver.data.xml.impl.SkillData;
1470 import org.l2junity.gameserver.model.Shortcut;
1471 import org.l2junity.gameserver.model.actor.instance.PlayerInstance;
1472 import org.l2junity.gameserver.network.client.OutgoingPackets;
1473@@ -64,7 +65,8 @@ public final class ShortCutInit implements IClientOutgoingPacket
1474 case SKILL:
1475 {
1476 packet.writeD(sc.getId());
1477- packet.writeD(sc.getLevel());
1478+ packet.writeH(((sc.getLevel() < 100) || (sc.getLevel() > 10000)) ? sc.getLevel() : SkillData.getInstance().getMaxLevel(sc.getId()));
1479+ packet.writeH(((sc.getLevel() < 100) || (sc.getLevel() > 10000)) ? 0 : sc.getLevel());
1480 packet.writeD(sc.getSharedReuseGroup());
1481 packet.writeC(0x00); // C5
1482 packet.writeD(0x01); // C6
1483diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ShortCutRegister.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ShortCutRegister.java
1484index 38cb5f8..d7d434e 100644
1485--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ShortCutRegister.java
1486+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/ShortCutRegister.java
1487@@ -18,6 +18,7 @@
1488 */
1489 package org.l2junity.gameserver.network.client.send;
1490
1491+import org.l2junity.gameserver.data.xml.impl.SkillData;
1492 import org.l2junity.gameserver.model.Shortcut;
1493 import org.l2junity.gameserver.network.client.OutgoingPackets;
1494 import org.l2junity.network.PacketWriter;
1495@@ -51,15 +52,15 @@ public final class ShortCutRegister implements IClientOutgoingPacket
1496 packet.writeD(_shortcut.getSharedReuseGroup());
1497 packet.writeD(0x00); // unknown
1498 packet.writeD(0x00); // unknown
1499- packet.writeD(0x00); // item augment id
1500+ packet.writeQ(0x00); // item augment id
1501 packet.writeD(0x00); // TODO: Find me, item visual id ?
1502 break;
1503 }
1504 case SKILL:
1505 {
1506 packet.writeD(_shortcut.getId());
1507- packet.writeH(_shortcut.getLevel());
1508- packet.writeH(0x00); // Sub level
1509+ packet.writeH(((_shortcut.getLevel() < 100) || (_shortcut.getLevel() > 10000)) ? _shortcut.getLevel() : SkillData.getInstance().getMaxLevel(_shortcut.getId()));
1510+ packet.writeH(((_shortcut.getLevel() < 100) || (_shortcut.getLevel() > 10000)) ? 0 : _shortcut.getLevel());
1511 packet.writeD(_shortcut.getSharedReuseGroup());
1512 packet.writeC(0x00); // C5
1513 packet.writeD(_shortcut.getCharacterType());
1514diff --git a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/SkillList.java b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/SkillList.java
1515index b506c06..4fbe611 100644
1516--- a/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/SkillList.java
1517+++ b/l2junity-gameserver/src/main/java/org/l2junity/gameserver/network/client/send/SkillList.java
1518@@ -70,7 +70,8 @@ public final class SkillList implements IClientOutgoingPacket
1519 for (Skill temp : _skills)
1520 {
1521 packet.writeD(temp.passive ? 1 : 0);
1522- packet.writeD(temp.level);
1523+ packet.writeH(temp.level < 100 ? temp.level : SkillData.getInstance().getMaxLevel(temp.id));
1524+ packet.writeH(temp.level < 100 ? 0 : temp.level);
1525 packet.writeD(temp.id);
1526 packet.writeD(temp.reuseDelayGroup); // GOD ReuseDelayShareGroupID
1527 packet.writeC(temp.disabled ? 1 : 0); // iSkillDisabled