· 5 years ago · May 06, 2020, 09:24 PM
1### Eclipse Workspace Patch 1.0
2#P aCis_gold
3Index: java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java
4===================================================================
5--- java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java (revision 2)
6+++ java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java (working copy)
7@@ -5526,16 +5526,6 @@
8 player._classIndex = subClass.getClassIndex();
9 }
10 }
11- if (player.getClassIndex() == 0 && activeClassId != player.getBaseClass())
12- {
13- // Subclass in use but doesn't exist in DB -
14- // a possible restart-while-modifysubclass cheat has been attempted.
15- // Switching to use base class
16- player.setClassId(player.getBaseClass());
17- _log.warning("Player " + player.getName() + " reverted to base class. Possibly has tried a relogin exploit while subclassing.");
18- }
19- else
20- player._activeClass = activeClassId;
21
22 player.setApprentice(rset.getInt("apprentice"));
23 player.setSponsor(rset.getInt("sponsor"));
24Index: java/net/sf/l2j/gameserver/network/clientpackets/RequestAcquireSkillInfo.java
25===================================================================
26--- java/net/sf/l2j/gameserver/network/clientpackets/RequestAcquireSkillInfo.java (revision 2)
27+++ java/net/sf/l2j/gameserver/network/clientpackets/RequestAcquireSkillInfo.java (working copy)
28@@ -17,8 +17,8 @@
29 import net.sf.l2j.Config;
30 import net.sf.l2j.gameserver.datatables.SkillTable;
31 import net.sf.l2j.gameserver.datatables.SkillTreeTable;
32-import net.sf.l2j.gameserver.datatables.SpellbookTable;
33 import net.sf.l2j.gameserver.model.L2PledgeSkillLearn;
34+import net.sf.l2j.gameserver.model.L2RebirthSkillLearn;
35 import net.sf.l2j.gameserver.model.L2Skill;
36 import net.sf.l2j.gameserver.model.L2SkillLearn;
37 import net.sf.l2j.gameserver.model.actor.L2Npc;
38@@ -62,7 +62,7 @@
39
40 switch (_skillType)
41 {
42- // General skills
43+ // Rebirth skills.
44 case 0:
45 int skillLvl = activeChar.getSkillLevel(_skillId);
46 if (skillLvl >= _skillLevel)
47@@ -74,14 +74,13 @@
48 if (!trainer.getTemplate().canTeach(activeChar.getSkillLearningClassId()))
49 return;
50
51- for (L2SkillLearn sl : SkillTreeTable.getInstance().getAvailableSkills(activeChar, activeChar.getSkillLearningClassId()))
52+ for (L2RebirthSkillLearn rsl : SkillTreeTable.getInstance().getAvailableRebirthSkills(activeChar, activeChar.getSkillLearningClassId()))
53 {
54- if (sl.getId() == _skillId && sl.getLevel() == _skillLevel)
55+ if (rsl.getId() == _skillId && rsl.getLevel() == _skillLevel)
56 {
57- AcquireSkillInfo asi = new AcquireSkillInfo(_skillId, _skillLevel, sl.getSpCost(), 0);
58- int spellbookItemId = SpellbookTable.getInstance().getBookForSkill(_skillId, _skillLevel);
59- if (spellbookItemId != 0)
60- asi.addRequirement(99, spellbookItemId, 1, 50);
61+ AcquireSkillInfo asi = new AcquireSkillInfo(_skillId, _skillLevel, rsl.getCostSp(), 0);
62+ if (Config.LIFE_CRYSTAL_NEEDED && rsl.getItemId() != 0)
63+ asi.addRequirement(1, rsl.getItemId(), 1, 0);
64 sendPacket(asi);
65 break;
66 }
67Index: java/net/sf/l2j/gameserver/model/L2RebirthSkillLearn.java
68===================================================================
69--- java/net/sf/l2j/gameserver/model/L2RebirthSkillLearn.java (revision 0)
70+++ java/net/sf/l2j/gameserver/model/L2RebirthSkillLearn.java (revision 0)
71@@ -0,0 +1,55 @@
72+/*
73+ * This program is free software: you can redistribute it and/or modify it under
74+ * the terms of the GNU General Public License as published by the Free Software
75+ * Foundation, either version 3 of the License, or (at your option) any later
76+ * version.
77+ *
78+ * This program is distributed in the hope that it will be useful, but WITHOUT
79+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
80+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
81+ * details.
82+ *
83+ * You should have received a copy of the GNU General Public License along with
84+ * this program. If not, see <http://www.gnu.org/licenses/>.
85+ */
86+package net.sf.l2j.gameserver.model;
87+
88+/**
89+ * @author Trance
90+ * @skype chr.trance
91+ */
92+public final class L2RebirthSkillLearn
93+{
94+ private final int _id;
95+ private final int _level;
96+ private final int _costSp;
97+ private final int _itemId;
98+
99+ public L2RebirthSkillLearn(int id, int lvl, int costSp, int itemId)
100+ {
101+ _id = id;
102+ _level = lvl;
103+ _costSp = costSp;
104+ _itemId = itemId;
105+ }
106+
107+ public int getId()
108+ {
109+ return _id;
110+ }
111+
112+ public int getLevel()
113+ {
114+ return _level;
115+ }
116+
117+ public int getCostSp()
118+ {
119+ return _costSp;
120+ }
121+
122+ public int getItemId()
123+ {
124+ return _itemId;
125+ }
126+}
127\ No newline at end of file
128Index: java/net/sf/l2j/gameserver/model/actor/instance/L2NpcInstance.java
129===================================================================
130--- java/net/sf/l2j/gameserver/model/actor/instance/L2NpcInstance.java (revision 2)
131+++ java/net/sf/l2j/gameserver/model/actor/instance/L2NpcInstance.java (working copy)
132@@ -22,8 +22,8 @@
133 import net.sf.l2j.gameserver.model.L2Effect;
134 import net.sf.l2j.gameserver.model.L2EnchantSkillData;
135 import net.sf.l2j.gameserver.model.L2EnchantSkillLearn;
136+import net.sf.l2j.gameserver.model.L2RebirthSkillLearn;
137 import net.sf.l2j.gameserver.model.L2Skill;
138-import net.sf.l2j.gameserver.model.L2SkillLearn;
139 import net.sf.l2j.gameserver.model.actor.L2Npc;
140 import net.sf.l2j.gameserver.model.actor.status.FolkStatus;
141 import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
142@@ -97,13 +97,13 @@
143 AcquireSkillList asl = new AcquireSkillList(AcquireSkillList.SkillType.Usual);
144 boolean empty = true;
145
146- for (L2SkillLearn sl : SkillTreeTable.getInstance().getAvailableSkills(player, classId))
147+ for (L2RebirthSkillLearn rsl : SkillTreeTable.getInstance().getAvailableRebirthSkills(player, classId))
148 {
149- L2Skill sk = SkillTable.getInstance().getInfo(sl.getId(), sl.getLevel());
150+ L2Skill sk = SkillTable.getInstance().getInfo(rsl.getId(), rsl.getLevel());
151 if (sk == null)
152 continue;
153
154- asl.addSkill(sl.getId(), sl.getLevel(), sl.getLevel(), sl.getSpCost(), 0);
155+ asl.addSkill(rsl.getId(), rsl.getLevel(), rsl.getLevel(), rsl.getCostSp(), 0);
156 empty = false;
157 }
158
159Index: dist/tools/database_installer.bat
160===================================================================
161--- dist/tools/database_installer.bat (revision 2)
162+++ dist/tools/database_installer.bat (working copy)
163@@ -70,6 +70,7 @@
164 %mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_hennas.sql
165 %mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_macroses.sql
166 %mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_mail.sql
167+%mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_rebirths.sql
168 %mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_quests.sql
169 %mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_raid_points.sql
170 %mysqlPath% -h %gshost% -u %gsuser% --password=%gspass% -D %gsdb% < ../sql/character_recipebook.sql
171Index: java/net/sf/l2j/gameserver/datatables/SkillTreeTable.java
172===================================================================
173--- java/net/sf/l2j/gameserver/datatables/SkillTreeTable.java (revision 2)
174+++ java/net/sf/l2j/gameserver/datatables/SkillTreeTable.java (working copy)
175@@ -26,6 +26,7 @@
176 import net.sf.l2j.gameserver.model.L2EnchantSkillData;
177 import net.sf.l2j.gameserver.model.L2EnchantSkillLearn;
178 import net.sf.l2j.gameserver.model.L2PledgeSkillLearn;
179+import net.sf.l2j.gameserver.model.L2RebirthSkillLearn;
180 import net.sf.l2j.gameserver.model.L2Skill;
181 import net.sf.l2j.gameserver.model.L2SkillLearn;
182 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
183@@ -46,6 +47,7 @@
184 private List<L2PledgeSkillLearn> _pledgeSkillTrees;
185 private Map<Integer, L2EnchantSkillData> _enchantSkillData;
186 private List<L2EnchantSkillLearn> _enchantSkillTrees;
187+ private List<L2RebirthSkillLearn> _rebirthSkillTrees;
188
189 public static SkillTreeTable getInstance()
190 {
191@@ -207,10 +209,43 @@
192 _log.severe("PledgeTable: Error while loading pledge skills: " + e);
193 }
194
195+ // Rebirth skills tree
196+ try
197+ {
198+ _rebirthSkillTrees = new ArrayList<>();
199+
200+ File f = new File("./data/xml/skillstrees/rebirth_skills_tree.xml");
201+ Document doc = XMLDocumentFactory.getInstance().loadDocument(f);
202+
203+ for (Node list = doc.getFirstChild().getFirstChild(); list != null; list = list.getNextSibling())
204+ {
205+ if ("skill".equalsIgnoreCase(list.getNodeName()))
206+ {
207+ NamedNodeMap skillAttr = list.getAttributes();
208+
209+ int skillId = Integer.parseInt(skillAttr.getNamedItem("id").getNodeValue());
210+ int skillLvl = Integer.parseInt(skillAttr.getNamedItem("lvl").getNodeValue());
211+ int costSp = Integer.valueOf(skillAttr.getNamedItem("sp").getNodeValue());
212+ int itemId = 0;
213+
214+ Node att = skillAttr.getNamedItem("itemId");
215+ if (att != null)
216+ itemId = Integer.valueOf(att.getNodeValue());
217+
218+ _rebirthSkillTrees.add(new L2RebirthSkillLearn(skillId, skillLvl, costSp, itemId));
219+ }
220+ }
221+ }
222+ catch (Exception e)
223+ {
224+ _log.severe("RebirthTable: Error while loading rebirth skills: " + e);
225+ }
226+
227 _log.config("FishingSkillTreeTable: Loaded " + _fishingSkillTrees.size() + " general skills.");
228 _log.config("DwarvenCraftSkillTreeTable: Loaded " + _expandDwarvenCraftSkillTrees.size() + " dwarven skills.");
229 _log.config("EnchantSkillTreeTable: Loaded " + _enchantSkillData.size() + " enchant types and " + _enchantSkillTrees.size() + " enchant skills.");
230 _log.config("PledgeSkillTreeTable: Loaded " + _pledgeSkillTrees.size() + " pledge skills.");
231+ _log.config("RebirthSkillTreeTable: Loaded " + _rebirthSkillTrees.size() + " rebirth skills.");
232 }
233
234 /**
235@@ -509,6 +544,39 @@
236 return result;
237 }
238
239+ /**
240+ * @param cha L2PcInstance, player whom skills are compared.
241+ * @param classId
242+ * @return list of available rebirth skills for L2PcInstance.
243+ */
244+ public List<L2RebirthSkillLearn> getAvailableRebirthSkills(L2PcInstance cha, ClassId classId)
245+ {
246+ List<L2RebirthSkillLearn> result = new ArrayList<>();
247+
248+ L2Skill[] chaSkills = cha.getAllSkills();
249+
250+ for (L2RebirthSkillLearn rsl : _rebirthSkillTrees)
251+ {
252+ boolean found = false;
253+
254+ for (L2Skill s : chaSkills)
255+ {
256+ if (s.getId() == rsl.getId())
257+ {
258+ if (s.getLevel() == rsl.getLevel() - 1)
259+ result.add(rsl);
260+
261+ found = true;
262+ break;
263+ }
264+ }
265+
266+ if (!found && rsl.getLevel() == 1)
267+ result.add(rsl);
268+ }
269+ return result;
270+ }
271+
272 public int getMinSkillLevel(int skillId, int skillLvl)
273 {
274 int skillHashCode = SkillTable.getSkillHashCode(skillId, skillLvl);
275Index: dist/tools/database_installer.sh
276===================================================================
277--- dist/tools/database_installer.sh (revision 2)
278+++ dist/tools/database_installer.sh (working copy)
279@@ -91,6 +91,7 @@
280 $MYG < ../sql/character_hennas.sql &> /dev/null
281 $MYG < ../sql/character_macroses.sql &> /dev/null
282 $MYG < ../sql/character_mail.sql &> /dev/null
283+$MYG < ../sql/character_rebirths.sql &> /dev/null
284 $MYG < ../sql/character_quests.sql &> /dev/null
285 $MYG < ../sql/character_raid_points.sql &> /dev/null
286 $MYG < ../sql/character_recipebook.sql &> /dev/null
287Index: dist/data/xml/skillstrees/rebirth_skills_tree.xml
288===================================================================
289--- dist/data/xml/skillstrees/rebirth_skills_tree.xml (revision 0)
290+++ dist/data/xml/skillstrees/rebirth_skills_tree.xml (revision 0)
291@@ -0,0 +1,39 @@
292+<?xml version='1.0' encoding='utf-8'?>
293+<list>
294+ <skill id="549" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Guidance -->
295+ <skill id="549" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Guidance -->
296+ <skill id="549" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Guidance -->
297+ <skill id="550" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Haste -->
298+ <skill id="550" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Haste -->
299+ <skill id="550" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Haste -->
300+ <skill id="551" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Health -->
301+ <skill id="551" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Health -->
302+ <skill id="551" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Health -->
303+ <skill id="552" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Mana -->
304+ <skill id="552" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Mana -->
305+ <skill id="552" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Mana -->
306+ <skill id="553" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Wind Walk -->
307+ <skill id="553" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Wind Walk -->
308+ <skill id="553" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Wind Walk -->
309+ <skill id="554" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Focus -->
310+ <skill id="554" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Focus -->
311+ <skill id="554" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Focus -->
312+ <skill id="555" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Might -->
313+ <skill id="555" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Might -->
314+ <skill id="555" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Might -->
315+ <skill id="556" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Empower -->
316+ <skill id="556" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Empower -->
317+ <skill id="556" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Empower -->
318+ <skill id="557" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Shield -->
319+ <skill id="557" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Shield -->
320+ <skill id="557" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Shield -->
321+ <skill id="558" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Magic Barrier -->
322+ <skill id="558" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Magic Barrier -->
323+ <skill id="558" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Magic Barrier -->
324+ <skill id="559" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Agility -->
325+ <skill id="559" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Agility -->
326+ <skill id="559" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Agility -->
327+ <skill id="560" lvl="1" sp="100" itemId="2822"/> <!-- Rebirth Acumen -->
328+ <skill id="560" lvl="2" sp="100" itemId="2822"/> <!-- Rebirth Acumen -->
329+ <skill id="560" lvl="3" sp="100" itemId="2822"/> <!-- Rebirth Acumen -->
330+</list>
331\ No newline at end of file
332Index: dist/sql/character_rebirths.sql
333===================================================================
334--- dist/sql/character_rebirths.sql (revision 0)
335+++ dist/sql/character_rebirths.sql (revision 0)
336@@ -0,0 +1,5 @@
337+CREATE TABLE IF NOT EXISTS `character_rebirths` (
338+ `playerId` int(20) NOT NULL,
339+ `rebirthCount` int(2) NOT NULL,
340+ PRIMARY KEY (`playerId`)
341+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
342\ No newline at end of file
343Index: java/net/sf/l2j/gameserver/network/clientpackets/RequestAcquireSkill.java
344===================================================================
345--- java/net/sf/l2j/gameserver/network/clientpackets/RequestAcquireSkill.java (revision 2)
346+++ java/net/sf/l2j/gameserver/network/clientpackets/RequestAcquireSkill.java (working copy)
347@@ -17,8 +17,8 @@
348 import net.sf.l2j.Config;
349 import net.sf.l2j.gameserver.datatables.SkillTable;
350 import net.sf.l2j.gameserver.datatables.SkillTreeTable;
351-import net.sf.l2j.gameserver.datatables.SpellbookTable;
352 import net.sf.l2j.gameserver.model.L2PledgeSkillLearn;
353+import net.sf.l2j.gameserver.model.L2RebirthSkillLearn;
354 import net.sf.l2j.gameserver.model.L2ShortCut;
355 import net.sf.l2j.gameserver.model.L2Skill;
356 import net.sf.l2j.gameserver.model.L2SkillLearn;
357@@ -80,7 +80,7 @@
358 // Types.
359 switch (_skillType)
360 {
361- case 0: // General skills.
362+ case 0: // Rebirth skills.
363 // Player already has such skill with same or higher level.
364 int skillLvl = activeChar.getSkillLevel(_skillId);
365 if (skillLvl >= _skillLevel)
366@@ -90,16 +90,17 @@
367 if (Math.max(skillLvl, 0) + 1 != _skillLevel)
368 return;
369
370- int spCost = 0;
371+ int spCost = 0, idItem = 0;
372
373 // Find skill information.
374- for (L2SkillLearn sl : SkillTreeTable.getInstance().getAvailableSkills(activeChar, activeChar.getSkillLearningClassId()))
375+ for (L2RebirthSkillLearn rsl : SkillTreeTable.getInstance().getAvailableRebirthSkills(activeChar, activeChar.getSkillLearningClassId()))
376 {
377 // Skill found.
378- if (sl.getId() == _skillId && sl.getLevel() == _skillLevel)
379+ if (rsl.getId() == _skillId && rsl.getLevel() == _skillLevel)
380 {
381 exists = true;
382- spCost = sl.getSpCost();
383+ idItem = rsl.getItemId();
384+ spCost = rsl.getCostSp();
385 break;
386 }
387 }
388@@ -116,11 +117,10 @@
389 return;
390 }
391
392- // Get spellbook and try to consume it.
393- int spbId = SpellbookTable.getInstance().getBookForSkill(_skillId, _skillLevel);
394- if (spbId > 0)
395+ // Get item and try to consume it.
396+ if (idItem > 0)
397 {
398- if (!activeChar.destroyItemByItemId("SkillLearn", spbId, 1, trainer, true))
399+ if (!activeChar.destroyItemByItemId("SkillLearn", idItem, 1, trainer, false))
400 {
401 activeChar.sendPacket(SystemMessageId.ITEM_MISSING_TO_LEARN_SKILL);
402 L2NpcInstance.showSkillList(activeChar, trainer, activeChar.getSkillLearningClassId());
403Index: java/net/sf/l2j/gameserver/model/actor/L2Character.java
404===================================================================
405--- java/net/sf/l2j/gameserver/model/actor/L2Character.java (revision 2)
406+++ java/net/sf/l2j/gameserver/model/actor/L2Character.java (working copy)
407@@ -4435,6 +4435,10 @@
408 if (skill == null)
409 return null;
410
411+ // Skip the rebirth skills.
412+ if (skill.getId() >= 549 && skill.getId() <= 560)
413+ return null;
414+
415 return removeSkill(skill.getId(), true);
416 }
417
418Index: java/net/sf/l2j/gameserver/model/actor/instance/L2RebirthInstance.java
419===================================================================
420--- java/net/sf/l2j/gameserver/model/actor/instance/L2RebirthInstance.java (revision 0)
421+++ java/net/sf/l2j/gameserver/model/actor/instance/L2RebirthInstance.java (revision 0)
422@@ -0,0 +1,302 @@
423+/*
424+ * This program is free software: you can redistribute it and/or modify it under
425+ * the terms of the GNU General Public License as published by the Free Software
426+ * Foundation, either version 3 of the License, or (at your option) any later
427+ * version.
428+ *
429+ * This program is distributed in the hope that it will be useful, but WITHOUT
430+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
431+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
432+ * details.
433+ *
434+ * You should have received a copy of the GNU General Public License along with
435+ * this program. If not, see <http://www.gnu.org/licenses/>.
436+ */
437+package net.sf.l2j.gameserver.model.actor.instance;
438+
439+import java.sql.Connection;
440+import java.sql.PreparedStatement;
441+import java.sql.ResultSet;
442+import java.util.HashMap;
443+
444+import net.sf.l2j.Config;
445+import net.sf.l2j.L2DatabaseFactory;
446+import net.sf.l2j.gameserver.model.base.Experience;
447+import net.sf.l2j.gameserver.model.item.instance.ItemInstance;
448+import net.sf.l2j.gameserver.model.L2Skill;
449+import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
450+import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
451+import net.sf.l2j.gameserver.network.SystemMessageId;
452+import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
453+import net.sf.l2j.gameserver.network.serverpackets.StatusUpdate;
454+import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
455+
456+/**
457+ * Rebirth Manager
458+ * @author Trance
459+ * @skype chr.trance
460+ */
461+public final class L2RebirthInstance extends L2NpcInstance
462+{
463+ private static HashMap<Integer, Integer> _rebirthInfo = new HashMap<>();
464+
465+ public L2RebirthInstance(int objectId, NpcTemplate template)
466+ {
467+ super(objectId, template);
468+ }
469+
470+ @Override
471+ public void onBypassFeedback(L2PcInstance player, String command)
472+ {
473+ if (command.startsWith("performRebirth"))
474+ {
475+ // Maximum rebirth count. Return the player's current Rebirth Level.
476+ int currBirth = getRebirthLevel(player);
477+ if (currBirth >= Config.REBIRTH_MAX)
478+ {
479+ NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
480+ html.setFile("data/html/gold/rebirth-max.htm");
481+
482+ player.sendPacket(html);
483+ return;
484+ }
485+
486+ // Level requirement for a rebirth.
487+ if (player.getLevel() < Config.REBIRTH_MIN_LEVEL)
488+ {
489+ NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
490+ html.setFile("data/html/gold/rebirth-level.htm");
491+
492+ player.sendPacket(html);
493+ return;
494+ }
495+
496+ int itemId = 0, itemCount = 0, loopBirth = 0;
497+ for (String readItems : Config.REBIRTH_ITEMS)
498+ {
499+ String[] currItem = readItems.split(",");
500+ if (loopBirth == currBirth)
501+ {
502+ itemId = Integer.parseInt(currItem[0]);
503+ itemCount = Integer.parseInt(currItem[1]);
504+ break;
505+ }
506+ loopBirth++;
507+ }
508+
509+ // Rewards the player with an item.
510+ rebirthItemReward(player, itemId, itemCount);
511+
512+ // Check and see if its the player's first rebirth calling.
513+ boolean firstBirth = currBirth == 0;
514+
515+ // Player meets requirements and starts Rebirth process.
516+ grantRebirth(player, (currBirth + 1), firstBirth);
517+ }
518+ else
519+ super.onBypassFeedback(player, command);
520+ }
521+
522+ @Override
523+ public void showChatWindow(L2PcInstance player)
524+ {
525+ NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
526+ html.setFile("data/html/gold/rebirth.htm");
527+ html.replace("%objectId%", String.valueOf(getObjectId()));
528+ html.replace("%level%", + Config.REBIRTH_RETURN_TO_LEVEL);
529+
530+ player.sendPacket(html);
531+ }
532+
533+ /**
534+ * Physically rewards player and resets status to nothing.
535+ *
536+ * @param player the player
537+ * @param newBirthCount the new birth count
538+ * @param firstBirth the first birth
539+ */
540+ public void grantRebirth(L2PcInstance player, int newBirthCount, boolean firstBirth)
541+ {
542+ try
543+ {
544+ // Delevel.
545+ player.removeExpAndSp(player.getExp() - Experience.LEVEL[Config.REBIRTH_RETURN_TO_LEVEL], 0);
546+
547+ // Back to the first class.
548+ player.setClassId(player.getClassId().getFirstClass().getId());
549+
550+ // Send the Server->Client packet StatusUpdate with current HP, MP and CP to this L2PcInstance
551+ player.broadcastStatusUpdate();
552+
553+ // Broadcast informations from a user to himself and his knownlist.
554+ player.broadcastUserInfo();
555+
556+ // Remove the player's current skills.
557+ for (L2Skill skill : player.getAllSkills())
558+ player.removeSkill(skill);
559+
560+ // Give all available skills to the player.
561+ player.giveAvailableSkills();
562+
563+ // Update L2PcInstance stats in the characters table of the database.
564+ player.store();
565+
566+ if (firstBirth)
567+ // Stores the player's information in the DB.
568+ storePlayerBirth(player);
569+ else
570+ // Updates the player's information in the DB.
571+ updatePlayerBirth(player, newBirthCount);
572+
573+ // Displays a congratulation window to the player.
574+ NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
575+ html.setFile("data/html/gold/rebirth-successfully.htm");
576+ html.replace("%level%", + Config.REBIRTH_RETURN_TO_LEVEL);
577+
578+ player.sendPacket(html);
579+ }
580+ catch (Exception e)
581+ {
582+ e.printStackTrace();
583+ }
584+ }
585+
586+ /**
587+ * Rewards the player with an item.
588+ *
589+ * @param player the player
590+ * @param itemId : Identifier of the item.
591+ * @param itemCount : Quantity of items to add.
592+ */
593+ public static void rebirthItemReward(L2PcInstance player, int itemId, int itemCount)
594+ {
595+ // Incorrect amount.
596+ if (itemCount <= 0)
597+ return;
598+
599+ final ItemInstance item = player.getInventory().addItem("Quest", itemId, itemCount, player, player);
600+ if (item == null)
601+ return;
602+
603+ // Send message to the client.
604+ if (itemId == 57)
605+ {
606+ SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.EARNED_S1_ADENA);
607+ smsg.addItemNumber(itemCount);
608+ player.sendPacket(smsg);
609+ }
610+ else
611+ {
612+ if (itemCount > 1)
613+ {
614+ SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S);
615+ smsg.addItemName(itemId);
616+ smsg.addItemNumber(itemCount);
617+ player.sendPacket(smsg);
618+ }
619+ else
620+ {
621+ SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.EARNED_ITEM_S1);
622+ smsg.addItemName(itemId);
623+ player.sendPacket(smsg);
624+ }
625+ }
626+
627+ // Send status update packet.
628+ StatusUpdate su = new StatusUpdate(player);
629+ su.addAttribute(StatusUpdate.CUR_LOAD, player.getCurrentLoad());
630+ player.sendPacket(su);
631+ }
632+
633+ /**
634+ * Return the player's current Rebirth Level.
635+ *
636+ * @param player the player
637+ * @return the rebirth level
638+ */
639+ public static int getRebirthLevel(L2PcInstance player)
640+ {
641+ int playerId = player.getObjectId();
642+ if (_rebirthInfo.get(playerId) == null)
643+ loadRebirthInfo(player);
644+
645+ return _rebirthInfo.get(playerId);
646+ }
647+
648+ /**
649+ * Database caller to retrieve player's current Rebirth Level.
650+ *
651+ * @param player the player
652+ */
653+ public static void loadRebirthInfo(L2PcInstance player)
654+ {
655+ int playerId = player.getObjectId(), rebirthCount = 0;
656+
657+ try (Connection con = L2DatabaseFactory.getInstance().getConnection())
658+ {
659+ ResultSet rset;
660+ PreparedStatement statement = con.prepareStatement("SELECT * FROM `character_rebirths` WHERE playerId = ?");
661+ statement.setInt(1, playerId);
662+ rset = statement.executeQuery();
663+
664+ while (rset.next())
665+ {
666+ rebirthCount = rset.getInt("rebirthCount");
667+ }
668+
669+ rset.close();
670+ statement.close();
671+ }
672+ catch (Exception e)
673+ {
674+ e.printStackTrace();
675+ }
676+ _rebirthInfo.put(playerId, rebirthCount);
677+ }
678+
679+ /**
680+ * Stores the player's information in the DB.
681+ *
682+ * @param player the player
683+ */
684+ public static void storePlayerBirth(L2PcInstance player)
685+ {
686+ try (Connection con = L2DatabaseFactory.getInstance().getConnection())
687+ {
688+ PreparedStatement statement = con.prepareStatement("INSERT INTO `character_rebirths` (playerId,rebirthCount) VALUES (?,1)");
689+ statement.setInt(1, player.getObjectId());
690+ statement.execute();
691+
692+ _rebirthInfo.put(player.getObjectId(), 1);
693+ }
694+ catch (Exception e)
695+ {
696+ e.printStackTrace();
697+ }
698+ }
699+
700+ /**
701+ * Updates the player's information in the DB.
702+ *
703+ * @param player the player
704+ * @param newRebirthCount the new rebirth count
705+ */
706+ public static void updatePlayerBirth(L2PcInstance player, int newRebirthCount)
707+ {
708+ int playerId = player.getObjectId();
709+
710+ try (Connection con = L2DatabaseFactory.getInstance().getConnection())
711+ {
712+ PreparedStatement statement = con.prepareStatement("UPDATE `character_rebirths` SET rebirthCount = ? WHERE playerId = ?");
713+ statement.setInt(1, newRebirthCount);
714+ statement.setInt(2, playerId);
715+ statement.execute();
716+
717+ _rebirthInfo.put(playerId, newRebirthCount);
718+ }
719+ catch (Exception e)
720+ {
721+ e.printStackTrace();
722+ }
723+ }
724+}
725\ No newline at end of file
726Index: java/net/sf/l2j/Config.java
727===================================================================
728--- java/net/sf/l2j/Config.java (revision 2)
729+++ java/net/sf/l2j/Config.java (working copy)
730@@ -49,6 +49,7 @@
731 public static final String LOGIN_CONFIGURATION_FILE = "./config/loginserver.properties";
732 public static final String NPCS_FILE = "./config/npcs.properties";
733 public static final String PLAYERS_FILE = "./config/players.properties";
734+ public static final String GOLD_FILE = "./config/gold.properties";
735 public static final String SERVER_FILE = "./config/server.properties";
736 public static final String SIEGE_FILE = "./config/siege.properties";
737
738@@ -496,6 +497,16 @@
739 public static int BUFFS_MAX_AMOUNT;
740
741 // --------------------------------------------------
742+ // Gold
743+ // --------------------------------------------------
744+
745+ /** Rebirth Manager */
746+ public static int REBIRTH_MIN_LEVEL;
747+ public static int REBIRTH_MAX;
748+ public static int REBIRTH_RETURN_TO_LEVEL;
749+ public static String[] REBIRTH_ITEMS;
750+
751+ // --------------------------------------------------
752 // Server
753 // --------------------------------------------------
754
755@@ -1082,6 +1093,14 @@
756 BUFFS_MAX_AMOUNT = players.getProperty("MaxBuffsAmount", 20);
757 STORE_SKILL_COOLTIME = players.getProperty("StoreSkillCooltime", true);
758
759+ // gold
760+ ExProperties gold = load(GOLD_FILE);
761+
762+ REBIRTH_MIN_LEVEL = gold.getProperty("RebirthMinLevel", 78);
763+ REBIRTH_MAX = gold.getProperty("RebirthMaxAllowed", 3);
764+ REBIRTH_RETURN_TO_LEVEL = gold.getProperty("RebirthReturnToLevel", 1);
765+ REBIRTH_ITEMS = gold.getProperty("RebirthItems", "").split(";");
766+
767 // server
768 ExProperties server = load(SERVER_FILE);
769
770Index: java/net/sf/l2j/gameserver/model/base/ClassId.java
771===================================================================
772--- java/net/sf/l2j/gameserver/model/base/ClassId.java (revision 2)
773+++ java/net/sf/l2j/gameserver/model/base/ClassId.java (working copy)
774@@ -249,4 +249,15 @@
775 {
776 return _parent;
777 }
778+
779+ /**
780+ * @return to the first class
781+ */
782+ public final ClassId getFirstClass()
783+ {
784+ if (_parent == null)
785+ return this;
786+
787+ return _parent.getFirstClass();
788+ }
789 }
790\ No newline at end of file