Svein:
+What are you curious to know about spirits?
+I will do my best to tell you everything I know.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-11.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-11.htm
new file mode 100644
index 0000000000..d8420b8987
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-11.htm
@@ -0,0 +1,8 @@
+Svein:
+Are you curious about checking the spirits' status?
+Start by opening the Character Information window.
+(You can open Character Information window with Alt+T.)
+If you click the Spirits button in the lower screen, you can check the spirits' status.
+Is there anything else you're curious about?
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-12.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-12.htm
new file mode 100644
index 0000000000..58e113dc91
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-12.htm
@@ -0,0 +1,15 @@
+Svein:
+Attribute Effect changes damage dealt and taken in battle.
+[Attribute Types]
+Spirits are classified according to 4 attributes of water, fire, wind and earth.
+[Attribute Attack and Growth]
+When you attack monsters, damage increases depending on attribute.
+But when you attack monsters by attribute, damage changes according to the monsters' attribute growth.
+With Growth Effect, a strong attribute gives 20% more damage, while a weak attribute can give no more than 60% damage.
+Relative Growth refers to relativity between attributes, where water is strong than fire and fire is stronger than wind. Also, wind is stronger than earth and earth is stronger than water.
+The attributes ae relatively linked, so you must not be careless with any one attribute.
+[Attribute Defense]
+If you're attacked with an attribute, your attribute defense withstands the attack.
+In this situation, it is important to know who has the higher attribute P. Def.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-13.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-13.htm
new file mode 100644
index 0000000000..f78eb3ad34
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-13.htm
@@ -0,0 +1,14 @@
+Svein:
+To grow spirits, defeat attribute monsters to acquire XP of the dominating attribute.
+Where are attribute monsters, you ask?
+Wind Attack Hunting Ground: Wind Plateau
+Earth Attack Hunting Ground: Wall of Argos
+Water Attack Hunting Ground: Garden of Eva
+Fire Attack Hunting Ground: Fore of the Gods
+And the spirits you can grow at each hunting ground vary, so keep that in mind when selecting.
+Wind Attack Hunting Ground: Obtained Fire Attack XP
+Earth Attack Hunting Ground: Obtained Wind Attack XP
+Water Attack Hunting Ground: Obtained Earth Attack XP
+Fire Attack Hunting Ground: Obtained Water Attack XP
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-14.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-14.htm
new file mode 100644
index 0000000000..97f19c85d9
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-14.htm
@@ -0,0 +1,9 @@
+Svein:
+The spirits have 4 main types of strength.
+Attribute Attack Strength: Increases damage when attacking with spirits' strength
+Attribute Defense Strength: Decrease damage received by spirits' strength.
+Attribute Critical Hit Effect: Increases critical hit effect of attribute.
+Attribute Critical Power: Increases amount of attack strength during critical hit
+Spirits' strength increases when they level up or are invested with attributes.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-15.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-15.htm
new file mode 100644
index 0000000000..47b7d9b834
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-15.htm
@@ -0,0 +1,6 @@
+Svein:
+Characteristics are skill types that raise spirits' strength. Each time a spirit levels up, it gains Characteristic Points and its strength increases when the Characteristic Points are added to each ability.
+When you evolve spirits, the highest possible level for the Characteristic increases, so evolution is essential.
+It is possible to reset at any time, so do not worry and add Characteristics however you see fit.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-16.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-16.htm
new file mode 100644
index 0000000000..3b1d5faeac
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-16.htm
@@ -0,0 +1,8 @@
+Svein:
+Each Spirit can grow up to 10 levels.
+Also, it is possible to evolve spirits that have completed growth.
+When spirits evolve, they increase strength an return to level 1, allowing them to grow them to Level 10 again.
+Don't forget that you need an Evolution Stone to evolve Spirits.
+(To evolve Spirits must reach Level 10 at 100%, so they require the ingredients for evoution from the Evolution Stone.)
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-17.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-17.htm
new file mode 100644
index 0000000000..837c4ab53d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-17.htm
@@ -0,0 +1,5 @@
+Svein:
+When hunting at the Attribute Hunting Ground, you can acquire a Spirit Rough Jewel.
+A Spirits Rough Jewel is the power of a spirit that is hardened like stone. It is possible for spirits to drain this strength and grow. If you acquire a Spirits Rough Jewel, try using it with your spirits. You can give them the Spirits Rough Jewel to the Spirits by clicking the Absorb tab in teh Manage Spirits window.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-18.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-18.htm
new file mode 100644
index 0000000000..b160e6807f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-18.htm
@@ -0,0 +1,9 @@
+Svein:
+You can extract strength from the spirits you have grown.
+The extracted spirits' strength glitters like stars and is called Attribute Fragment.
+You can extract Fire Attribute Fragment from fire spirits and Wind Attribute Fragment from wind spirits.
+You can extract Attribute Fragment by clicking the Extract button in the Manage Spirits window and paying the fee.
+It is possible to enhance various items with Attribute Fragment. If you are interested, plesse como to see me.
+(A spirit whose Attribute Fragment has been extracted returns to Level 1 of its classification, Please keep this in mind when extracting.)
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-19.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-19.htm
new file mode 100644
index 0000000000..c45e6a0f85
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053-19.htm
@@ -0,0 +1,8 @@
+Svein:
+It is possible to change attributes by clicking the Attributes button in the Character Information window.
+P. Atk. attribute is given by selected spirits.
+Do not change attributes too frequently. Spirits also need to be ready to give strength.
+(There is a delay time by schedule for Change Attribute.)
+When attacked by an attribute monster, you attribute defense will kick in, so do not worry.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053.htm
index 6136178c44..b59ad4ec32 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053.htm
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/html/merchant/34053.htm
@@ -1,11 +1,11 @@
-Svein:
-Have you heard of Spirits?
-Honestly, there are not many people who actually know about them.
-Not all Spirits are hostile, as the common opinion goes. Moreover, there are those among them who would like to befriend a mighty warrior, like yourself.
-I can tell you more if you want.
-
-
-
-
-
+Svein:
+Adventurer, have you heard of Spirits?
+There are few who know of the spirits.
+Not all Spirits are hostile, as many believe. There are those who wish to befriend mortals. If you're interested, I can also Help you.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500000.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500000.xml
index 9acb37695a..cbe59d32cc 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500000.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500000.xml
@@ -1,122 +1,122 @@
-
+34053
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500001.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500001.xml
new file mode 100644
index 0000000000..e412d395ae
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500001.xml
@@ -0,0 +1,26 @@
+
+
+
+ 34053
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500002.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500002.xml
new file mode 100644
index 0000000000..ab46d5d66e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500002.xml
@@ -0,0 +1,146 @@
+
+
+
+ 34053
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500003.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500003.xml
new file mode 100644
index 0000000000..625cdffe5d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/multisell/3500003.xml
@@ -0,0 +1,139 @@
+
+
+
+ 34053
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/AttributeMaster.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/AttributeMaster.java
new file mode 100644
index 0000000000..cdfb7b7028
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/AttributeMaster.java
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.others.AttributeMaster;
+
+import java.util.Arrays;
+
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventDispatcher;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnElementalSpiritLearn;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritInfo;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author JoeAlisson
+ */
+public class AttributeMaster extends AbstractNpcAI
+{
+
+ private static final int SVEIN = 34053;
+
+ private AttributeMaster()
+ {
+ addStartNpc(SVEIN);
+ addTalkId(SVEIN);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ if ("learn".equalsIgnoreCase(event))
+ {
+ if ((player.getLevel() < 76) || (player.getClassId().level() < 3))
+ {
+ return "no-3rdClass.htm";
+ }
+
+ if (player.getSpirits() == null)
+ {
+ player.initElementalSpirits();
+ }
+
+ if (Arrays.stream(player.getSpirits()).allMatch(elementalSpirit -> elementalSpirit.getStage() > 0))
+ {
+ return "already.htm";
+ }
+
+ for (ElementalSpirit spirit : player.getSpirits())
+ {
+ if (spirit.getStage() == 0)
+ {
+ spirit.upgrade();
+ }
+ }
+ UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ player.sendPacket(userInfo);
+ player.sendPacket(new ElementalSpiritInfo(player, player.getActiveElementalSpiritType(), (byte) 0x01));
+ EventDispatcher.getInstance().notifyEventAsync(new OnElementalSpiritLearn(player), player);
+ return "learn.htm";
+ }
+ return null;
+ }
+
+ public static AbstractNpcAI provider()
+ {
+ return new AttributeMaster();
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/already.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/already.htm
new file mode 100644
index 0000000000..39a9d2b86f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/already.htm
@@ -0,0 +1,5 @@
+Svein:
+You Already know about spirits!
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/learn.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/learn.htm
new file mode 100644
index 0000000000..a80c1f3919
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/learn.htm
@@ -0,0 +1,7 @@
+Svein:
+You seem to be ready to accept the power spirits!
+I'll introduce the spirits to you...
+From now on you can use power of the spirits.
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/no-3rdClass.htm b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/no-3rdClass.htm
new file mode 100644
index 0000000000..10c99eaf62
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/AttributeMaster/no-3rdClass.htm
@@ -0,0 +1,7 @@
+Svein:
+You are not ready to accept the power spirits,
+I must only give spirits to those who can rule over their power.
+If not, they will be overpowered by the spirits.
+(Only 3rd Class Characters may receive the Spirits).
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/DailyMissionMasterHandler.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/DailyMissionMasterHandler.java
index 96cd13cc26..022066ae75 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/DailyMissionMasterHandler.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/DailyMissionMasterHandler.java
@@ -29,6 +29,7 @@ import handlers.dailymissionhandlers.LoginWeekendDailyMissionHandler;
import handlers.dailymissionhandlers.OlympiadDailyMissionHandler;
import handlers.dailymissionhandlers.QuestDailyMissionHandler;
import handlers.dailymissionhandlers.SiegeDailyMissionHandler;
+import handlers.dailymissionhandlers.SpiritDailyMissionHandler;
/**
* @author UnAfraid
@@ -48,6 +49,7 @@ public class DailyMissionMasterHandler
DailyMissionHandler.getInstance().registerHandler("ceremonyofchaos", CeremonyOfChaosDailyMissionHandler::new);
DailyMissionHandler.getInstance().registerHandler("boss", BossDailyMissionHandler::new);
DailyMissionHandler.getInstance().registerHandler("fishing", FishingDailyMissionHandler::new);
+ DailyMissionHandler.getInstance().registerHandler("spirit", SpiritDailyMissionHandler::new);
LOGGER.info(DailyMissionMasterHandler.class.getSimpleName() + ": Loaded " + DailyMissionHandler.getInstance().size() + " handlers.");
}
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/EffectMasterHandler.java
index 8b9f5e4f7d..227a69590e 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -130,6 +130,8 @@ public final class EffectMasterHandler
EffectHandler.getInstance().registerHandler("DispelBySlotProbability", DispelBySlotProbability::new);
EffectHandler.getInstance().registerHandler("DoubleCast", DoubleCast::new);
EffectHandler.getInstance().registerHandler("DuelistFury", DuelistFury::new);
+ EffectHandler.getInstance().registerHandler("ElementalSpiritAttack", ElementalSpiritAttack::new);
+ EffectHandler.getInstance().registerHandler("ElementalSpiritDefense", ElementalSpiritDefense::new);
EffectHandler.getInstance().registerHandler("EnableCloak", EnableCloak::new);
EffectHandler.getInstance().registerHandler("EnergyAttack", EnergyAttack::new);
EffectHandler.getInstance().registerHandler("EnlargeAbnormalSlot", EnlargeAbnormalSlot::new);
@@ -309,6 +311,7 @@ public final class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Sow", Sow::new);
EffectHandler.getInstance().registerHandler("Speed", Speed::new);
EffectHandler.getInstance().registerHandler("SphericBarrier", SphericBarrier::new);
+ EffectHandler.getInstance().registerHandler("SpiritXpModify", SpiritExpModify::new);
EffectHandler.getInstance().registerHandler("SpModify", SpModify::new);
EffectHandler.getInstance().registerHandler("Spoil", Spoil::new);
EffectHandler.getInstance().registerHandler("StatBonusSkillCritical", StatBonusSkillCritical::new);
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/dailymissionhandlers/SpiritDailyMissionHandler.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/dailymissionhandlers/SpiritDailyMissionHandler.java
new file mode 100644
index 0000000000..1d5f97a24e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/dailymissionhandlers/SpiritDailyMissionHandler.java
@@ -0,0 +1,100 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.dailymissionhandlers;
+
+import java.util.function.Consumer;
+
+import org.l2jmobius.gameserver.enums.DailyMissionStatus;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.handler.AbstractDailyMissionHandler;
+import org.l2jmobius.gameserver.model.DailyMissionDataHolder;
+import org.l2jmobius.gameserver.model.DailyMissionPlayerEntry;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnElementalSpiritUpgrade;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnElementalSpiritLearn;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+
+/**
+ * @author JoeAlisson
+ */
+public class SpiritDailyMissionHandler extends AbstractDailyMissionHandler
+{
+ private final int _amount;
+ private final ElementalType _type;
+
+ public SpiritDailyMissionHandler(DailyMissionDataHolder holder)
+ {
+ super(holder);
+ _type = getHolder().getParams().getEnum("element", ElementalType.class, ElementalType.NONE);
+ _amount = holder.getRequiredCompletions();
+ }
+
+ @Override
+ public void init()
+ {
+ final MissionKind kind = getHolder().getParams().getEnum("kind", MissionKind.class, null);
+ if (MissionKind.EVOLVE == kind)
+ {
+ Containers.Players().addListener(new ConsumerEventListener(this, EventType.ON_ELEMENTAL_SPIRIT_UPGRADE, (Consumer) this::onElementalSpiritUpgrade, this));
+ }
+ else if (MissionKind.LEARN == kind)
+ {
+ Containers.Players().addListener(new ConsumerEventListener(this, EventType.ON_ELEMENTAL_SPIRIT_LEARN, (Consumer) this::onElementalSpiritLearn, this));
+ }
+ }
+
+ @Override
+ public boolean isAvailable(PlayerInstance player)
+ {
+ final DailyMissionPlayerEntry entry = getPlayerEntry(player.getObjectId(), false);
+ return (entry != null) && (entry.getStatus() == DailyMissionStatus.AVAILABLE);
+ }
+
+ private void onElementalSpiritLearn(OnElementalSpiritLearn event)
+ {
+ final DailyMissionPlayerEntry missionData = getPlayerEntry(event.getPlayer().getObjectId(), true);
+ missionData.setProgress(1);
+ missionData.setStatus(DailyMissionStatus.AVAILABLE);
+ storePlayerEntry(missionData);
+ }
+
+ private void onElementalSpiritUpgrade(OnElementalSpiritUpgrade event)
+ {
+ final ElementalSpirit spirit = event.getSpirit();
+ if (ElementalType.of(spirit.getType()) != _type)
+ {
+ return;
+ }
+
+ final DailyMissionPlayerEntry missionData = getPlayerEntry(event.getPlayer().getObjectId(), true);
+ missionData.setProgress(spirit.getStage());
+ if (missionData.getProgress() >= _amount)
+ {
+ missionData.setStatus(DailyMissionStatus.AVAILABLE);
+ }
+ storePlayerEntry(missionData);
+ }
+
+ private enum MissionKind
+ {
+ LEARN,
+ EVOLVE
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritAttack.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritAttack.java
new file mode 100644
index 0000000000..529c36277e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritAttack.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.StatsSet;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritAttack extends AbstractStatEffect
+{
+ public ElementalSpiritAttack(StatsSet params)
+ {
+ super(params, params.getEnum("type", ElementalType.class).getAttackStat());
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritDefense.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritDefense.java
new file mode 100644
index 0000000000..32d541bcb3
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritDefense.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.StatsSet;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritDefense extends AbstractStatEffect
+{
+ public ElementalSpiritDefense(StatsSet params)
+ {
+ super(params, params.getEnum("type", ElementalType.class).getDefenseStat());
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/HealPercent.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/HealPercent.java
index 4ca447992c..289b1945c3 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/HealPercent.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/HealPercent.java
@@ -97,7 +97,7 @@ public final class HealPercent extends AbstractEffect
{
final double damage = -amount;
effected.reduceCurrentHp(damage, effector, skill, false, false, false, false);
- effector.sendDamageMessage(effected, skill, (int) damage, false, false);
+ effector.sendDamageMessage(effected, skill, (int) damage, 0, false, false);
}
}
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/Hp.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/Hp.java
index 145391fd17..1382d776db 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/Hp.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/Hp.java
@@ -102,7 +102,7 @@ public final class Hp extends AbstractEffect
{
final double damage = -amount;
effected.reduceCurrentHp(damage, effector, skill, false, false, false, false);
- effector.sendDamageMessage(effected, skill, (int) damage, false, false);
+ effector.sendDamageMessage(effected, skill, (int) damage, 0, false, false);
}
}
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/RealDamage.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/RealDamage.java
index 8b2801ee6c..1fdf1296cc 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/RealDamage.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/RealDamage.java
@@ -53,7 +53,7 @@ public class RealDamage extends AbstractEffect
effected.reduceCurrentHp(_power, effector, skill, false, false, false, false);
if (effector.isPlayer())
{
- effector.sendDamageMessage(effected, skill, (int) _power, false, false);
+ effector.sendDamageMessage(effected, skill, (int) _power, 0, false, false);
}
}
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/SpiritExpModify.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/SpiritExpModify.java
new file mode 100644
index 0000000000..6215d0c7ab
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/SpiritExpModify.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatsSet;
+import org.l2jmobius.gameserver.model.stats.Stats;
+
+/**
+ * @author JoeAlisson
+ */
+public class SpiritExpModify extends AbstractStatEffect
+{
+ public SpiritExpModify(StatsSet params)
+ {
+ super(params, Stats.ELEMENTAL_SPIRIT_BONUS_EXP);
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/spawns/Aden/Aden.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/spawns/Aden/Aden.xml
index 7f8b1bbdb1..2b13324bb0 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/spawns/Aden/Aden.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/spawns/Aden/Aden.xml
@@ -136,6 +136,7 @@
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/spawns/Giran/Giran.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/spawns/Giran/Giran.xml
index d2bea396fb..b7a0b41f76 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/spawns/Giran/Giran.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/spawns/Giran/Giran.xml
@@ -107,6 +107,7 @@
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20700-20799.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20700-20799.xml
index 7d85e85900..4e97970ff4 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20700-20799.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20700-20799.xml
@@ -3428,7 +3428,7 @@
-
+
@@ -3445,7 +3445,7 @@
BEASTMALE
-
+
@@ -3560,7 +3560,7 @@
-
+
@@ -3575,7 +3575,7 @@
HUMANOIDMALE
-
+
@@ -3609,7 +3609,7 @@
-
+
@@ -3624,7 +3624,7 @@
HUMANOIDMALE
-
+
@@ -3657,7 +3657,7 @@
-
+
@@ -3672,7 +3672,7 @@
HUMANOIDMALE
-
+
@@ -3705,7 +3705,7 @@
-
+
@@ -3726,7 +3726,7 @@
HUMANOIDMALE
-
+
@@ -3764,7 +3764,7 @@
-
+
@@ -3779,7 +3779,7 @@
GIANTMALE
-
+
@@ -3813,7 +3813,7 @@
-
+
@@ -3829,7 +3829,7 @@
ELEMENTALFEMALE
-
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20800-20899.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20800-20899.xml
index ebf73428df..afceb82f4f 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20800-20899.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20800-20899.xml
@@ -1,6 +1,6 @@
-
+
@@ -14,7 +14,7 @@
CONSTRUCTMALE
-
+
@@ -45,7 +45,7 @@
-
+
@@ -62,7 +62,7 @@
UNDEADMALE
-
+
@@ -96,7 +96,7 @@
-
+
@@ -115,7 +115,7 @@
DEMONICMALE
-
+
@@ -152,7 +152,7 @@
-
+
@@ -168,7 +168,7 @@
UNDEADMALE
-
+
@@ -3386,7 +3386,7 @@
-
+
@@ -3400,7 +3400,7 @@
ANIMALMALE
-
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20900-20999.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20900-20999.xml
index 2c5920d7ab..8c0487c362 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20900-20999.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/20900-20999.xml
@@ -5126,7 +5126,7 @@
-
+
@@ -5145,7 +5145,7 @@
UNDEADMALE
-
+
@@ -5180,7 +5180,7 @@
-
+
@@ -5194,8 +5194,10 @@
ELEMENTALMALE
+
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21600-21699.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21600-21699.xml
index 2006d82e4f..b761adde44 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21600-21699.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21600-21699.xml
@@ -3637,7 +3637,7 @@
-
+
@@ -3645,7 +3645,7 @@
HUMANOIDMALE
-
+
@@ -3679,7 +3679,7 @@
-
+
@@ -3694,7 +3694,7 @@
HUMANOIDMALE
-
+
@@ -3733,7 +3733,7 @@
-
+
@@ -3742,7 +3742,7 @@
HUMANOIDMALE
-
+
@@ -3776,14 +3776,14 @@
-
+ BUGMALE
-
+
@@ -3817,14 +3817,14 @@
-
+ BUGMALE
-
+
@@ -3858,7 +3858,7 @@
-
+
@@ -3866,7 +3866,7 @@
BUGMALE
-
+
@@ -3900,7 +3900,7 @@
-
+
@@ -3909,7 +3909,7 @@
UNDEADMALE
-
+
@@ -3943,7 +3943,7 @@
-
+
@@ -3951,7 +3951,7 @@
UNDEADMALE
-
+
@@ -3985,10 +3985,10 @@
-
+ DEMONICMALE
-
+
@@ -4013,7 +4013,7 @@
-
+
@@ -4021,7 +4021,7 @@
CONSTRUCTMALE
-
+
@@ -4055,7 +4055,7 @@
-
+
@@ -4063,7 +4063,7 @@
CONSTRUCTMALE
-
+
@@ -4097,7 +4097,7 @@
-
+
@@ -4105,7 +4105,7 @@
DEMONICMALE
-
+
@@ -4142,14 +4142,14 @@
-
+ DEMONICMALE
-
+
@@ -4186,10 +4186,10 @@
-
+ DEMONICMALE
-
+
@@ -4213,10 +4213,10 @@
-
+ DEMONICMALE
-
+
@@ -4241,10 +4241,10 @@
-
+ BEASTMALE
-
+
@@ -4287,10 +4287,10 @@
-
+ DRAGONMALE
-
+
@@ -4451,10 +4451,10 @@
-
+ DEMONICMALE
-
+
@@ -4479,10 +4479,10 @@
-
+ DRAGONMALE
-
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21700-21799.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21700-21799.xml
index 379be06446..00d794b493 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21700-21799.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21700-21799.xml
@@ -2505,10 +2505,10 @@
-
+ ELEMENTALMALE
-
+
@@ -2537,10 +2537,10 @@
-
+ ELEMENTALMALE
-
+
@@ -2570,10 +2570,10 @@
-
-
+ ELEMENTALFEMALE
+
@@ -2603,10 +2603,9 @@
-
-
+ ELEMENTAL
-
+
@@ -2635,10 +2634,9 @@
-
-
+ ETC
-
+
@@ -2667,10 +2665,9 @@
-
-
+ ELEMENTAL
-
+
@@ -2700,10 +2697,10 @@
-
-
+ ELEMENTALFEMALE
+
@@ -2732,10 +2729,10 @@
-
-
+ ELEMENTALFEMALE
+
@@ -2764,10 +2761,10 @@
-
-
+ ELEMENTALFEMALE
+
@@ -2797,7 +2794,7 @@
-
+
@@ -2812,7 +2809,7 @@
ELEMENTALMALE
-
+
@@ -2849,7 +2846,7 @@
-
+
@@ -2864,7 +2861,7 @@
ELEMENTALMALE
-
+
@@ -2901,7 +2898,7 @@
-
+
@@ -2916,7 +2913,7 @@
ELEMENTALMALE
-
+
@@ -2954,10 +2951,10 @@
-
+ ETCMALE
-
+
@@ -2980,10 +2977,10 @@
-
+ BEAST
-
+
@@ -3005,10 +3002,10 @@
-
+ DIVINE
-
+
@@ -3022,7 +3019,7 @@
-
+
@@ -3032,7 +3029,7 @@
-
+
@@ -3047,7 +3044,7 @@
DEMONICMALE
-
+
@@ -3078,7 +3075,7 @@
-
+
@@ -3093,7 +3090,7 @@
ELEMENTALMALE
-
+
@@ -3124,7 +3121,7 @@
-
+
@@ -3139,7 +3136,7 @@
ELEMENTALMALE
-
+
@@ -3170,7 +3167,7 @@
-
+
@@ -3185,7 +3182,7 @@
ELEMENTALMALE
-
+
@@ -3215,7 +3212,7 @@
-
+
@@ -3230,7 +3227,7 @@
ELEMENTALMALE
-
+
@@ -3261,7 +3258,7 @@
-
+
@@ -3276,7 +3273,7 @@
ELEMENTALMALE
-
+
@@ -3307,7 +3304,7 @@
-
+
@@ -3322,7 +3319,7 @@
ELEMENTALMALE
-
+
@@ -3353,7 +3350,7 @@
-
+
@@ -3368,7 +3365,7 @@
ELEMENTALMALE
-
+
@@ -3399,7 +3396,7 @@
-
+
@@ -3414,7 +3411,7 @@
ELEMENTALMALE
-
+
@@ -3445,7 +3442,7 @@
-
+
@@ -3460,7 +3457,7 @@
ELEMENTALMALE
-
+
@@ -3491,7 +3488,7 @@
-
+
@@ -3506,7 +3503,7 @@
ELEMENTALMALE
-
+
@@ -3537,7 +3534,7 @@
-
+
@@ -3552,7 +3549,7 @@
ELEMENTALMALE
-
+
@@ -3583,7 +3580,7 @@
-
+
@@ -3598,7 +3595,7 @@
ELEMENTALMALE
-
+
@@ -3630,7 +3627,7 @@
-
+
@@ -3645,7 +3642,7 @@
ELEMENTALMALE
-
+
@@ -3676,7 +3673,7 @@
-
+
@@ -3691,7 +3688,7 @@
ELEMENTALMALE
-
+
@@ -3722,7 +3719,7 @@
-
+
@@ -3737,7 +3734,7 @@
ELEMENTALMALE
-
+
@@ -3769,7 +3766,7 @@
-
+
@@ -3784,7 +3781,7 @@
HUMANOIDMALE
-
+
@@ -3815,7 +3812,7 @@
-
+
@@ -3830,7 +3827,7 @@
UNDEADMALE
-
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21800-21899.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21800-21899.xml
index cce3fabc25..648f5770e5 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21800-21899.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/npcs/21800-21899.xml
@@ -820,7 +820,7 @@
-
+
@@ -835,7 +835,7 @@
ANIMALMALE
-
+
@@ -868,7 +868,7 @@
-
+
@@ -886,7 +886,7 @@
ANIMALMALE
-
+
@@ -921,7 +921,7 @@
-
+
@@ -937,7 +937,7 @@
BEASTMALE
-
+
@@ -970,7 +970,7 @@
-
+
@@ -988,7 +988,7 @@
BEASTMALE
-
+
@@ -1023,7 +1023,7 @@
-
+
@@ -1038,7 +1038,7 @@
CONSTRUCTMALE
-
+
@@ -1071,8 +1071,7 @@
-
-
+
@@ -1089,7 +1088,7 @@
BEASTMALE
-
+
@@ -1124,8 +1123,7 @@
-
-
+
@@ -1145,7 +1143,7 @@
CONSTRUCTMALE
-
+
@@ -1184,8 +1182,7 @@
-
-
+
@@ -1206,7 +1203,7 @@
CONSTRUCTMALE
-
+
@@ -1246,8 +1243,7 @@
-
-
+
@@ -1266,7 +1262,7 @@
CONSTRUCTMALE
-
+
@@ -1305,7 +1301,7 @@
-
+
@@ -1322,7 +1318,7 @@
CONSTRUCTMALE
-
+
@@ -1356,7 +1352,7 @@
-
+
@@ -1377,7 +1373,7 @@
ANIMALMALE
-
+
@@ -1415,8 +1411,7 @@
-
-
+
@@ -1435,7 +1430,7 @@
CONSTRUCTMALE
-
+
@@ -1474,8 +1469,7 @@
-
-
+
@@ -1492,7 +1486,7 @@
CONSTRUCTMALE
-
+
@@ -1529,8 +1523,7 @@
-
-
+
@@ -1549,7 +1542,7 @@
CONSTRUCTMALE
-
+
@@ -1588,8 +1581,7 @@
-
-
+
@@ -1605,7 +1597,7 @@
BEASTMALE
-
+
@@ -1640,8 +1632,7 @@
-
-
+
@@ -1657,7 +1648,7 @@
DIVINEFEMALE
-
+
@@ -1692,8 +1683,7 @@
-
-
+
@@ -1711,7 +1701,7 @@
DIVINEFEMALE
-
+
@@ -1748,8 +1738,7 @@
-
-
+
@@ -1765,7 +1754,7 @@
DIVINEFEMALE
-
+
@@ -1800,8 +1789,7 @@
-
-
+
@@ -1816,7 +1804,7 @@
DIVINEMALE
-
+
@@ -1852,11 +1840,11 @@
-
-
+ DIVINEFEMALE
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/51000-51099.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/51000-51099.xml
index 5598c2e04d..b601b958ea 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/51000-51099.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/51000-51099.xml
@@ -727,21 +727,69 @@
icon.agathion_fire_1P
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 100
+ FIRE
+
+ icon.agathion_water_1P
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 100
+ WATER
+
+ icon.agathion_wind_1P
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 100
+ WIND
+
+ icon.agathion_earth_1P
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 100
+ EARTH
+
+ icon.ev_charge_scroll
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/51100-51199.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/51100-51199.xml
index 1b622ace26..ec67d5074f 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/51100-51199.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/51100-51199.xml
@@ -8,26 +8,70 @@
icon.etc_summon_aga_agit_i00
- A13000
+ 2
+ 85
+ A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 13568
+
+ icon.etc_summon_aga_agit_i00
- A13000
+ 2
+ 85
+ A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 13572
+
+ icon.etc_summon_aga_agit_i00
- A13000
+ 2
+ 85
+ A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 13576
+
+ icon.etc_summon_aga_agit_i00
- A13000
+ 2
+ 85
+ A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 13580
+
+
@@ -161,18 +205,54 @@
icon.etc_potion_blue_i00A1
+ true
+ 2
+ 1
+ 0
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 100
+ DIFF
+
+ icon.elemental_bless_scrl_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 30
+ PER
+
+ icon.elemental_bless_scrl_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ PER
+
+ icon.ev_charge_scroll
@@ -185,30 +265,74 @@
icon.etc_fire_potion_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 160000
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ FIRE
+
+ icon.etc_water_potion_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 160000
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ WATER
+
+ icon.etc_wind_potion_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 160000
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ WIND
+
+ icon.etc_earth_potion_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 160000
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ EARTH
+
+ A1
@@ -356,7 +480,20 @@
icon.etc_potion_blue_i00
+ true
+ 2
+ 1A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 300
+ DIFF
+
+ A1
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/54000-54099.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/54000-54099.xml
index 53d6d1346c..96e3f9b678 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/54000-54099.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/54000-54099.xml
@@ -153,33 +153,108 @@
icon.elemental_necklace_water_i00P
+ 1
+
+
+
+ 20
+ 40
+ 60
+ 80
+ 100
+
+ WATER
+
+ icon.elemental_necklace_fire_i00P
+ 1
+
+
+
+ 20
+ 40
+ 60
+ 80
+ 100
+
+ FIRE
+
+ icon.elemental_necklace_wind_i00P
+ 1
+
+
+
+ 20
+ 40
+ 60
+ 80
+ 100
+
+ WIND
+
+ icon.elemental_necklace_earth_i00P
+ 1
+
+
+
+ 20
+ 40
+ 60
+ 80
+ 100
+
+ EARTH
+
+ icon.skill_transform_s_attackP
+ 1
+
+
+
+ 3
+ 6
+ 10
+ 15
+ 30
+
+ PER
+
+ icon.elemental_bless_scrl_i00
- A1
- 4
- 1
+ A2
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 20
+ PER
+
+
@@ -195,21 +270,153 @@
icon.elemental_necklace_fire_i00P
+
+
+
+ 50
+ 50
+ 100
+ 100
+ 150
+ 150
+ 200
+ 200
+ 300
+ 300
+ 500
+
+
+
+
+ 0
+ 1
+ 1
+ 2
+ 2
+ 3
+ 3
+ 5
+ 7
+ 10
+ 15
+
+ PER
+
+ icon.elemental_necklace_water_i00P
+
+
+
+ 50
+ 50
+ 100
+ 100
+ 150
+ 150
+ 200
+ 200
+ 300
+ 300
+ 500
+
+
+
+
+ 0
+ 1
+ 1
+ 2
+ 2
+ 3
+ 3
+ 5
+ 7
+ 10
+ 15
+
+ PER
+
+ icon.elemental_necklace_wind_i00P
+
+
+
+ 50
+ 50
+ 100
+ 100
+ 150
+ 150
+ 200
+ 200
+ 300
+ 300
+ 500
+
+
+
+
+ 0
+ 1
+ 1
+ 2
+ 2
+ 3
+ 3
+ 5
+ 7
+ 10
+ 15
+
+ PER
+
+ icon.elemental_necklace_earth_i00P
+
+
+
+ 50
+ 50
+ 100
+ 100
+ 150
+ 150
+ 200
+ 200
+ 300
+ 300
+ 500
+
+
+
+
+ 0
+ 1
+ 1
+ 2
+ 2
+ 3
+ 3
+ 5
+ 7
+ 10
+ 15
+
+ PER
+
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/documentation.txt b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/documentation.txt
index f74cc44fc1..adf6534f54 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/documentation.txt
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/documentation.txt
@@ -100,6 +100,8 @@ DispelBySlotMyself: Removes given amount of effects by specified AbnormalType
DispelBySlotProbability: Removes given amount of effects by specified AbnormalType at a given rate.
DoubleCast: Triggers Fire, Water, Wind, Earth stance and enables the ability to cast two skills at once.
DuelistFury: Synergy effect for Faceoff effect. (l2jmobius)
+ElementalSpiritAttack: Elemental spirit attack stat effect. (JoeAlisson)
+ElementalSpiritDefense: Elemental spirit defense stat effect. (JoeAlisson)
EnableCloak: See/unsee cloaks.
EnemyCharge: Charges towards the enemy. Rush Impact.
EnergyAttack: Physical attack based on Momentum formula. Triple Sonic Slash, Double Sonic Slash etc.
@@ -278,6 +280,7 @@ SoulEating: Absorbs souls when taking exp from mobs and sets max soul count.
Sow: Planting a seed into NPC target. Manor stuff.
Speed: Speed stat.
SphericBarrier: Blocks damage and buff/debuff incoming from outside the specified range.
+SpiritExpModify: Spirit EXP modify stat effect. (JoeAlisson)
SpModify: Bonus SP stat.
Spoil: Spoils a mob activating its extra sweep drop.
StatBonusSkillCritical: Changes skill critical rate to depend on the specified base stat.
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/ElementalSpiritData.xsd b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/ElementalSpiritData.xsd
new file mode 100644
index 0000000000..c4fe1eb554
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/ElementalSpiritData.xsd
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/npcs.xsd b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/npcs.xsd
index 87d6e604e0..05803d592d 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/npcs.xsd
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/npcs.xsd
@@ -66,6 +66,7 @@
+
@@ -302,6 +303,7 @@
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/commons/util/CommonUtil.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/commons/util/CommonUtil.java
index 1c00dfe98a..c4a69288c2 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/commons/util/CommonUtil.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/commons/util/CommonUtil.java
@@ -16,6 +16,9 @@
*/
package org.l2jmobius.commons.util;
+import static java.util.Objects.isNull;
+import static java.util.Objects.nonNull;
+
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
@@ -27,11 +30,14 @@ import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.StringJoiner;
import java.util.StringTokenizer;
+import java.util.function.Predicate;
+import java.util.function.ToIntFunction;
import org.l2jmobius.Config;
@@ -587,4 +593,29 @@ public final class CommonUtil
final DecimalFormat formatter = new DecimalFormat(format, new DecimalFormatSymbols(Locale.ENGLISH));
return formatter.format(val);
}
+
+ public static boolean isNullOrEmpty(final CharSequence value)
+ {
+ return isNull(value) || (value.length() == 0);
+ }
+
+ public static boolean isNotEmpty(final String value)
+ {
+ return nonNull(value) && !value.isEmpty();
+ }
+
+ public static boolean isNullOrEmpty(final Collection> collection)
+ {
+ return isNull(collection) || collection.isEmpty();
+ }
+
+ public static int zeroIfNullOrElse(T obj, ToIntFunction action)
+ {
+ return isNull(obj) ? 0 : action.applyAsInt(obj);
+ }
+
+ public static boolean falseIfNullOrElse(T obj, Predicate predicate)
+ {
+ return nonNull(obj) && predicate.test(obj);
+ }
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/GameServer.java
index 8bf2bd0cd6..afafda0dc8 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/GameServer.java
@@ -55,6 +55,7 @@ import org.l2jmobius.gameserver.data.xml.impl.CombinationItemsData;
import org.l2jmobius.gameserver.data.xml.impl.CubicData;
import org.l2jmobius.gameserver.data.xml.impl.DailyMissionData;
import org.l2jmobius.gameserver.data.xml.impl.DoorData;
+import org.l2jmobius.gameserver.data.xml.impl.ElementalSpiritData;
import org.l2jmobius.gameserver.data.xml.impl.EnchantItemData;
import org.l2jmobius.gameserver.data.xml.impl.EnchantItemGroupsData;
import org.l2jmobius.gameserver.data.xml.impl.EnchantItemHPBonusData;
@@ -239,6 +240,7 @@ public class GameServer
ClanRewardData.getInstance();
DailyMissionHandler.getInstance().executeScript();
DailyMissionData.getInstance();
+ ElementalSpiritData.getInstance();
printSection("Skills");
SkillConditionHandler.getInstance().executeScript();
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/impl/ElementalSpiritData.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/impl/ElementalSpiritData.java
new file mode 100644
index 0000000000..1be9c187e0
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/impl/ElementalSpiritData.java
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml.impl;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritTemplateHolder;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(ElementalSpiritData.class.getName());
+
+ public static final long EXTRACT_FEE = 1000000;
+ public static final float FRAGMENT_XP_CONSUME = 50000.0f;
+ public static final int TALENT_INIT_FEE = 50000;
+
+ private static final Map> SPIRIT_DATA = new HashMap<>(4);
+
+ protected ElementalSpiritData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ parseDatapackFile("data/ElementalSpiritData.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + SPIRIT_DATA.size() + " elemental spirit templates.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", list -> forEach(list, "spirit", this::parseSpirit));
+ }
+
+ private void parseSpirit(Node spiritNode)
+ {
+ final NamedNodeMap attributes = spiritNode.getAttributes();
+ final byte type = parseByte(attributes, "type");
+ final byte stage = parseByte(attributes, "stage");
+ final int npcId = parseInteger(attributes, "npcId");
+ final int extractItem = parseInteger(attributes, "extractItem");
+ final int maxCharacteristics = parseInteger(attributes, "maxCharacteristics");
+ ElementalSpiritTemplateHolder template = new ElementalSpiritTemplateHolder(type, stage, npcId, extractItem, maxCharacteristics);
+ SPIRIT_DATA.computeIfAbsent(type, HashMap::new).put(stage, template);
+
+ forEach(spiritNode, "level", levelNode ->
+ {
+ final NamedNodeMap levelInfo = levelNode.getAttributes();
+ final int level = parseInteger(levelInfo, "id");
+ final int attack = parseInteger(levelInfo, "atk");
+ final int defense = parseInteger(levelInfo, "def");
+ final int criticalRate = parseInteger(levelInfo, "critRate");
+ final int criticalDamage = parseInteger(levelInfo, "critDam");
+ final long maxExperience = parseLong(levelInfo, "maxExp");
+ template.addLevelInfo(level, attack, defense, criticalRate, criticalDamage, maxExperience);
+ });
+
+ forEach(spiritNode, "itemToEvolve", itemNode ->
+ {
+ final NamedNodeMap itemInfo = itemNode.getAttributes();
+ final int itemId = parseInteger(itemInfo, "id");
+ final int count = parseInteger(itemInfo, "count", 1);
+ template.addItemToEvolve(itemId, count);
+ });
+
+ forEach(spiritNode, "absorbItem", absorbItemNode ->
+ {
+ final NamedNodeMap absorbInfo = absorbItemNode.getAttributes();
+ final int itemId = parseInteger(absorbInfo, "id");
+ final int experience = parseInteger(absorbInfo, "experience");
+ template.addAbsorbItem(itemId, experience);
+ });
+ }
+
+ public ElementalSpiritTemplateHolder getSpirit(byte type, byte stage)
+ {
+ if (SPIRIT_DATA.containsKey(type))
+ {
+ return SPIRIT_DATA.get(type).get(stage);
+ }
+ return null;
+ }
+
+ public static ElementalSpiritData getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ static final ElementalSpiritData INSTANCE = new ElementalSpiritData();
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/impl/NpcData.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/impl/NpcData.java
index da219ac6ce..28cecaacbe 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/impl/NpcData.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/impl/NpcData.java
@@ -42,6 +42,7 @@ import org.l2jmobius.commons.util.IXmlReader;
import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.AISkillScope;
import org.l2jmobius.gameserver.enums.DropType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.MpRewardAffectType;
import org.l2jmobius.gameserver.enums.MpRewardType;
import org.l2jmobius.gameserver.model.StatsSet;
@@ -110,6 +111,7 @@ public class NpcData implements IXmlReader
set.set("usingServerSideName", parseBoolean(attrs, "usingServerSideName"));
set.set("title", parseString(attrs, "title"));
set.set("usingServerSideTitle", parseBoolean(attrs, "usingServerSideTitle"));
+ set.set("elementalType", parseEnum(attrs, ElementalType.class, "element"));
for (Node npcNode = listNode.getFirstChild(); npcNode != null; npcNode = npcNode.getNextSibling())
{
attrs = npcNode.getAttributes();
@@ -143,6 +145,7 @@ public class NpcData implements IXmlReader
set.set("exp", parseDouble(attrs, "exp"));
set.set("sp", parseDouble(attrs, "sp"));
set.set("raidPoints", parseDouble(attrs, "raidPoints"));
+ set.set("attribute_exp", parseLong(attrs, "attribute_exp"));
break;
}
case "mpreward":
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/enums/ElementalType.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/enums/ElementalType.java
new file mode 100644
index 0000000000..1e0d98411e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/enums/ElementalType.java
@@ -0,0 +1,127 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.enums;
+
+import org.l2jmobius.gameserver.model.stats.Stats;
+
+/**
+ * @author JoeAlisson
+ */
+public enum ElementalType
+{
+ NONE,
+ FIRE,
+ WATER,
+ WIND,
+ EARTH;
+
+ public byte getId()
+ {
+ return (byte) (ordinal());
+ }
+
+ public static ElementalType of(byte elementId)
+ {
+ return values()[elementId];
+ }
+
+ public ElementalType getDominating()
+ {
+ return dominating(this);
+ }
+
+ public ElementalType dominating(ElementalType elementalType)
+ {
+ switch (elementalType)
+ {
+ case FIRE:
+ {
+ return WATER;
+ }
+ case WATER:
+ {
+ return EARTH;
+ }
+ case WIND:
+ {
+ return FIRE;
+ }
+ case EARTH:
+ {
+ return WIND;
+ }
+ default:
+ {
+ return NONE;
+ }
+ }
+ }
+
+ public Stats getAttackStat()
+ {
+ switch (this)
+ {
+ case EARTH:
+ {
+ return Stats.ELEMENTAL_SPIRIT_EARTH_ATTACK;
+ }
+ case WIND:
+ {
+ return Stats.ELEMENTAL_SPIRIT_WIND_ATTACK;
+ }
+ case FIRE:
+ {
+ return Stats.ELEMENTAL_SPIRIT_FIRE_ATTACK;
+ }
+ case WATER:
+ {
+ return Stats.ELEMENTAL_SPIRIT_WATER_ATTACK;
+ }
+ default:
+ {
+ return null;
+ }
+ }
+ }
+
+ public Stats getDefenseStat()
+ {
+ switch (this)
+ {
+ case EARTH:
+ {
+ return Stats.ELEMENTAL_SPIRIT_EARTH_DEFENSE;
+ }
+ case WIND:
+ {
+ return Stats.ELEMENTAL_SPIRIT_WIND_DEFENSE;
+ }
+ case FIRE:
+ {
+ return Stats.ELEMENTAL_SPIRIT_FIRE_DEFENSE;
+ }
+ case WATER:
+ {
+ return Stats.ELEMENTAL_SPIRIT_WATER_DEFENSE;
+ }
+ default:
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/ElementalSpiritInstanceManager.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/ElementalSpiritInstanceManager.java
new file mode 100644
index 0000000000..f58c587de8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/ElementalSpiritInstanceManager.java
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.instancemanager;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.database.DatabaseFactory;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder;
+
+/**
+ * @author Mobius
+ */
+public class ElementalSpiritInstanceManager
+{
+ private static final String LOAD_QUERY = "SELECT * FROM character_spirits WHERE charId=?";
+ private static final String STORE_QUERY = "REPLACE INTO character_spirits (charId, type, level, stage, experience, attack_points, defense_points, crit_rate_points, crit_damage_points, in_use) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+ public List findByPlayerId(int playerId)
+ {
+ final List result = new ArrayList<>();
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement stmt = con.prepareStatement(LOAD_QUERY))
+ {
+ stmt.setInt(1, playerId);
+ try (ResultSet rset = stmt.executeQuery())
+ {
+ while (rset.next())
+ {
+ final ElementalSpiritDataHolder newHolder = new ElementalSpiritDataHolder();
+ newHolder.setCharId(rset.getInt("charId"));
+ newHolder.setType(rset.getByte("type"));
+ newHolder.setLevel(rset.getByte("level"));
+ newHolder.setStage(rset.getByte("stage"));
+ newHolder.setExperience(rset.getLong("experience"));
+ newHolder.setAttackPoints(rset.getByte("attack_points"));
+ newHolder.setDefensePoints(rset.getByte("defense_points"));
+ newHolder.setCritRatePoints(rset.getByte("crit_rate_points"));
+ newHolder.setCritDamagePoints(rset.getByte("crit_damage_points"));
+ newHolder.setInUse(rset.getByte("in_use") == 1);
+ result.add(newHolder);
+ }
+ }
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ public void save(ElementalSpiritDataHolder data)
+ {
+ if (data == null)
+ {
+ return;
+ }
+
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement statement = con.prepareStatement(STORE_QUERY))
+ {
+ statement.setInt(1, data.getCharId());
+ statement.setInt(2, data.getType());
+ statement.setInt(3, data.getLevel());
+ statement.setInt(4, data.getStage());
+ statement.setLong(5, data.getExperience());
+ statement.setInt(6, data.getAttackPoints());
+ statement.setInt(7, data.getDefensePoints());
+ statement.setInt(8, data.getCritRatePoints());
+ statement.setInt(9, data.getCritDamagePoints());
+ statement.setInt(10, data.isInUse() ? 1 : 0);
+ statement.execute();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public static ElementalSpiritInstanceManager getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final ElementalSpiritInstanceManager INSTANCE = new ElementalSpiritInstanceManager();
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/ElementalSpirit.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/ElementalSpirit.java
new file mode 100644
index 0000000000..2b84bf0339
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/ElementalSpirit.java
@@ -0,0 +1,275 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model;
+
+import static java.lang.Math.max;
+
+import java.util.List;
+
+import org.l2jmobius.gameserver.data.xml.impl.ElementalSpiritData;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.instancemanager.ElementalSpiritInstanceManager;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventDispatcher;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnElementalSpiritUpgrade;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritAbsorbItemHolder;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritTemplateHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ExElementalSpiritGetExp;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpirit
+{
+ private final PlayerInstance _owner;
+ private ElementalSpiritTemplateHolder _template;
+ private final ElementalSpiritDataHolder _data;
+
+ public ElementalSpirit(ElementalType type, PlayerInstance owner)
+ {
+ _data = new ElementalSpiritDataHolder(type.getId(), owner.getObjectId());
+ _template = ElementalSpiritData.getInstance().getSpirit(type.getId(), _data.getStage());
+ _owner = owner;
+ }
+
+ public ElementalSpirit(ElementalSpiritDataHolder data, PlayerInstance owner)
+ {
+ _owner = owner;
+ _data = data;
+ _template = ElementalSpiritData.getInstance().getSpirit(data.getType(), data.getStage());
+ }
+
+ public void addExperience(long experience)
+ {
+ _data.addExperience(experience);
+ _owner.sendPacket(new SystemMessage(SystemMessageId.OBTAINED_S2_ATTRIBUTE_XP_OF_S1).addInt((int) experience).addElementalSpirit(getType()));
+ if (_data.getExperience() > getExperienceToNextLevel())
+ {
+ levelUp();
+ _owner.sendPacket(new SystemMessage(SystemMessageId.S1_ATTRIBUTE_SPIRIT_BECAME_LEVEL_S2).addElementalSpirit(getType()).addByte(_data.getLevel()));
+ _owner.sendPacket(new ElementalSpiritInfo(_owner, _owner.getActiveElementalSpiritType(), (byte) 0));
+ final UserInfo userInfo = new UserInfo(_owner);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ _owner.sendPacket(userInfo);
+
+ }
+ _owner.sendPacket(new ExElementalSpiritGetExp(getType(), _data.getExperience()));
+ }
+
+ private void levelUp()
+ {
+ do
+ {
+ if (_data.getLevel() < getMaxLevel())
+ {
+ _data.increaseLevel();
+ }
+ else
+ {
+ _data.setExperience(getExperienceToNextLevel());
+ }
+ }
+ while (_data.getExperience() > getExperienceToNextLevel());
+ }
+
+ public int getAvailableCharacteristicsPoints()
+ {
+ final int stage = _data.getStage();
+ final int level = _data.getLevel();
+ final int points = ((stage - 1) * 11) + (stage > 2 ? (level - 1) * 2 : level - 1);
+ return max(points - _data.getAttackPoints() - _data.getDefensePoints() - _data.getCritDamagePoints() - _data.getCritRatePoints(), 0);
+ }
+
+ public ElementalSpiritAbsorbItemHolder getAbsorbItem(int itemId)
+ {
+ for (ElementalSpiritAbsorbItemHolder absorbItem : getAbsorbItems())
+ {
+ if (absorbItem.getId() == itemId)
+ {
+ return absorbItem;
+ }
+ }
+ return null;
+ }
+
+ public int getExtractAmount()
+ {
+ return Math.round(_data.getExperience() / ElementalSpiritData.FRAGMENT_XP_CONSUME);
+ }
+
+ public void resetStage()
+ {
+ _data.setLevel((byte) 1);
+ _data.setExperience(0);
+ resetCharacteristics();
+ }
+
+ public boolean canEvolve()
+ {
+ return (getStage() < 3) && (getLevel() == 10) && (getExperience() == getExperienceToNextLevel());
+ }
+
+ public void upgrade()
+ {
+ _data.increaseStage();
+ _data.setLevel((byte) 1);
+ _data.setExperience(0);
+ _template = ElementalSpiritData.getInstance().getSpirit(_data.getType(), _data.getStage());
+ EventDispatcher.getInstance().notifyEventAsync(new OnElementalSpiritUpgrade(_owner, this), _owner);
+
+ }
+
+ public void resetCharacteristics()
+ {
+ _data.setAttackPoints((byte) 0);
+ _data.setDefensePoints((byte) 0);
+ _data.setCritRatePoints((byte) 0);
+ _data.setCritDamagePoints((byte) 0);
+ }
+
+ public byte getType()
+ {
+ return _template.getType();
+ }
+
+ public byte getStage()
+ {
+ return _template.getStage();
+ }
+
+ public int getNpcId()
+ {
+ return _template.getNpcId();
+ }
+
+ public long getExperience()
+ {
+ return _data.getExperience();
+ }
+
+ public long getExperienceToNextLevel()
+ {
+ return _template.getMaxExperienceAtLevel(_data.getLevel());
+ }
+
+ public byte getLevel()
+ {
+ return _data.getLevel();
+ }
+
+ public int getMaxLevel()
+ {
+ return _template.getMaxLevel();
+ }
+
+ public int getAttack()
+ {
+ return _template.getAttackAtLevel(_data.getLevel()) + (_data.getAttackPoints() * 5);
+ }
+
+ public int getDefense()
+ {
+ return _template.getDefenseAtLevel(_data.getLevel()) + (_data.getDefensePoints() * 5);
+ }
+
+ public int getMaxCharacteristics()
+ {
+ return _template.getMaxCharacteristics();
+ }
+
+ public int getAttackPoints()
+ {
+ return _data.getAttackPoints();
+ }
+
+ public int getDefensePoints()
+ {
+ return _data.getDefensePoints();
+ }
+
+ public int getCriticalRatePoints()
+ {
+ return _data.getCritRatePoints();
+ }
+
+ public int getCriticalDamagePoints()
+ {
+ return _data.getCritDamagePoints();
+ }
+
+ public List getItemsToEvolve()
+ {
+ return _template.getItemsToEvolve();
+ }
+
+ public List getAbsorbItems()
+ {
+ return _template.getAbsorbItems();
+ }
+
+ public int getExtractItem()
+ {
+ return _template.getExtractItem();
+ }
+
+ public void save()
+ {
+ ElementalSpiritInstanceManager.getInstance().save(_data);
+ }
+
+ public void addAttackPoints(byte attackPoints)
+ {
+ _data.addAttackPoints(attackPoints);
+ }
+
+ public void addDefensePoints(byte defensePoints)
+ {
+ _data.addDefensePoints(defensePoints);
+ }
+
+ public void addCritRatePoints(byte critRatePoints)
+ {
+ _data.addCritRatePoints(critRatePoints);
+ }
+
+ public void addCritDamage(byte critDamagePoints)
+ {
+ _data.addCritDamagePoints(critDamagePoints);
+ }
+
+ public int getCriticalRate()
+ {
+ return _template.getCriticalRateAtLevel(_data.getLevel()) + getCriticalRatePoints();
+ }
+
+ public int getCriticalDamage()
+ {
+ return _template.getCriticalDamageAtLevel(_data.getLevel()) + getCriticalRatePoints();
+ }
+
+ public void setInUse(boolean value)
+ {
+ _data.setInUse(value);
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index c8e3c18d06..f0469106c7 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -42,6 +42,7 @@ import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.InstanceType;
import org.l2jmobius.gameserver.enums.Team;
import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
@@ -50,6 +51,7 @@ import org.l2jmobius.gameserver.instancemanager.WalkingManager;
import org.l2jmobius.gameserver.model.AggroInfo;
import org.l2jmobius.gameserver.model.CommandChannel;
import org.l2jmobius.gameserver.model.DamageDoneInfo;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
import org.l2jmobius.gameserver.model.Party;
import org.l2jmobius.gameserver.model.Seed;
import org.l2jmobius.gameserver.model.WorldObject;
@@ -519,6 +521,8 @@ public class Attackable extends Npc
attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), exp, _isRaid), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(attacker, exp);
}
+
+ rewardAttributeExp(attacker, damage, totalDamage);
}
}
}
@@ -616,6 +620,11 @@ public class Attackable extends Npc
if (partyDmg > 0)
{
attackerParty.distributeXpAndSp(exp, sp, rewardedMembers, partyLvl, partyDmg, this);
+
+ for (PlayerInstance rewardedMember : rewardedMembers)
+ {
+ rewardAttributeExp(rewardedMember, damage, totalDamage);
+ }
}
}
}
@@ -627,6 +636,19 @@ public class Attackable extends Npc
}
}
+ private void rewardAttributeExp(PlayerInstance player, long damage, long totalDamage)
+ {
+ if ((player.getActiveElementalSpiritType() > 0) && (getAttributeExp() > 0) && (getElementalSpiritType() != ElementalType.NONE))
+ {
+ final long attributeExp = (long) (((getAttributeExp() * damage) / totalDamage) * player.getElementalSpiritXpBonus());
+ final ElementalSpirit spirit = player.getElementalSpirit(getElementalSpiritType().getDominating());
+ if (spirit != null)
+ {
+ spirit.addExperience(attributeExp);
+ }
+ }
+ }
+
@Override
public void addAttackerToAttackByList(Creature creature)
{
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Creature.java
index 1d4237d89a..3144dc44d3 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Creature.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Creature.java
@@ -54,6 +54,7 @@ import org.l2jmobius.gameserver.data.xml.impl.TransformData;
import org.l2jmobius.gameserver.enums.AttributeType;
import org.l2jmobius.gameserver.enums.BasicProperty;
import org.l2jmobius.gameserver.enums.CategoryType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.InstanceType;
import org.l2jmobius.gameserver.enums.ItemSkillType;
import org.l2jmobius.gameserver.enums.Race;
@@ -2691,6 +2692,18 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
info.addComponentType(UserInfoType.ATK_ELEMENTAL);
break;
}
+ case ELEMENTAL_SPIRIT_EARTH_ATTACK:
+ case ELEMENTAL_SPIRIT_EARTH_DEFENSE:
+ case ELEMENTAL_SPIRIT_FIRE_ATTACK:
+ case ELEMENTAL_SPIRIT_FIRE_DEFENSE:
+ case ELEMENTAL_SPIRIT_WATER_ATTACK:
+ case ELEMENTAL_SPIRIT_WATER_DEFENSE:
+ case ELEMENTAL_SPIRIT_WIND_ATTACK:
+ case ELEMENTAL_SPIRIT_WIND_DEFENSE:
+ {
+ info.addComponentType(UserInfoType.ATT_SPIRITS);
+ break;
+ }
}
}
}
@@ -4506,11 +4519,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
}
}
- final double damageCap = _stat.getValue(Stats.DAMAGE_LIMIT);
- if (damageCap > 0)
- {
- value = Math.min(value, damageCap);
- }
+ double elementalDamage = 0;
// Calculate PvP/PvE damage received. It is a post-attack stat.
if (attacker != null)
@@ -4523,6 +4532,15 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
{
value *= (100 + _stat.getValue(Stats.PVE_DAMAGE_TAKEN)) / 100;
}
+
+ elementalDamage = Formulas.calcSpiritElementalDamage(attacker, this);
+ value += elementalDamage;
+ }
+
+ final double damageCap = _stat.getValue(Stats.DAMAGE_LIMIT);
+ if (damageCap > 0)
+ {
+ value = Math.min(value, damageCap);
}
if (Config.CHAMPION_ENABLE && isChampion() && (Config.CHAMPION_HP != 0))
@@ -4540,7 +4558,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (attacker != null)
{
- attacker.sendDamageMessage(this, skill, (int) value, critical, false);
+ attacker.sendDamageMessage(this, skill, (int) value, elementalDamage, critical, false);
}
}
@@ -4671,10 +4689,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* @param target
* @param skill
* @param damage
+ * @param elementalDamage
* @param crit
* @param miss
*/
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
}
@@ -5472,4 +5491,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
_buffFinishTask = null;
}
}
+
+ public double getElementalSpiritDefenseOf(ElementalType type)
+ {
+ return getElementalSpiritType() == type ? 100 : 0;
+ }
+
+ public ElementalType getElementalSpiritType()
+ {
+ return ElementalType.NONE;
+ }
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Npc.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Npc.java
index c50ed91d05..b3cf15fe5c 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Npc.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Npc.java
@@ -29,6 +29,7 @@ import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.AISkillScope;
import org.l2jmobius.gameserver.enums.AIType;
import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.InstanceType;
import org.l2jmobius.gameserver.enums.MpRewardAffectType;
import org.l2jmobius.gameserver.enums.PrivateStoreType;
@@ -868,6 +869,17 @@ public class Npc extends Creature
return getTemplate().getSP() * rateMul;
}
+ public long getAttributeExp()
+ {
+ return getTemplate().getAttributeExp();
+ }
+
+ @Override
+ public ElementalType getElementalSpiritType()
+ {
+ return getTemplate().getElementalType();
+ }
+
/**
* Kill the NpcInstance (the corpse disappeared after 7 seconds).
* Actions:
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Summon.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Summon.java
index 71d6606772..a614eec679 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Summon.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/Summon.java
@@ -734,7 +734,7 @@ public abstract class Summon extends Playable
}
@Override
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
if (miss || (_owner == null))
{
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/DoppelgangerInstance.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/DoppelgangerInstance.java
index a41fd1e41d..cedf3a08f3 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/DoppelgangerInstance.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/DoppelgangerInstance.java
@@ -124,11 +124,11 @@ public class DoppelgangerInstance extends Npc
public void doAttack(double damage, Creature target, Skill skill, boolean isDOT, boolean directlyToHp, boolean critical, boolean reflect)
{
super.doAttack(damage, target, skill, isDOT, directlyToHp, critical, reflect);
- sendDamageMessage(target, skill, (int) damage, critical, false);
+ sendDamageMessage(target, skill, (int) damage, 0, critical, false);
}
@Override
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
if (miss || (getSummoner() == null) || !getSummoner().isPlayer())
{
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index 8275a59c00..d3de2ad522 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -47,6 +47,7 @@ import java.util.stream.Collectors;
import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.database.DatabaseFactory;
+import org.l2jmobius.commons.util.CommonUtil;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.GameTimeController;
import org.l2jmobius.gameserver.ItemsAutoDestroy;
@@ -83,6 +84,7 @@ import org.l2jmobius.gameserver.enums.CastleSide;
import org.l2jmobius.gameserver.enums.CategoryType;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.ClanWarState;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.GroupType;
import org.l2jmobius.gameserver.enums.HtmlActionScope;
import org.l2jmobius.gameserver.enums.IllegalActionPunishmentType;
@@ -108,6 +110,7 @@ import org.l2jmobius.gameserver.instancemanager.AntiFeedManager;
import org.l2jmobius.gameserver.instancemanager.CastleManager;
import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import org.l2jmobius.gameserver.instancemanager.DuelManager;
+import org.l2jmobius.gameserver.instancemanager.ElementalSpiritInstanceManager;
import org.l2jmobius.gameserver.instancemanager.FortManager;
import org.l2jmobius.gameserver.instancemanager.FortSiegeManager;
import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
@@ -125,6 +128,7 @@ import org.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import org.l2jmobius.gameserver.model.BlockList;
import org.l2jmobius.gameserver.model.CommandChannel;
import org.l2jmobius.gameserver.model.ContactList;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.Macro;
import org.l2jmobius.gameserver.model.MacroList;
@@ -213,6 +217,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerReputa
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerSubChange;
import org.l2jmobius.gameserver.model.fishing.Fishing;
import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.MovieHolder;
import org.l2jmobius.gameserver.model.holders.PlayerEventHolder;
@@ -847,6 +852,9 @@ public final class PlayerInstance extends Playable
private final Set _whisperers = ConcurrentHashMap.newKeySet();
+ private ElementalSpirit[] _spirits;
+ private ElementalType _activeElementalSpiritType;
+
// Selling buffs system
private boolean _isSellingBuffs = false;
private List _sellingBuffs = null;
@@ -2350,6 +2358,7 @@ public final class PlayerInstance extends Playable
if (getClassId().level() == 3)
{
sendPacket(SystemMessageId.CONGRATULATIONS_YOU_VE_COMPLETED_YOUR_THIRD_CLASS_TRANSFER_QUEST);
+ initElementalSpirits();
}
else
{
@@ -6662,6 +6671,11 @@ public final class PlayerInstance extends Playable
player.setSponsor(rset.getInt("sponsor"));
player.setLvlJoinedAcademy(rset.getInt("lvl_joined_academy"));
+ if ((player.getLevel() >= 76) && (player.getClassId().level() > 2))
+ {
+ player.initElementalSpirits();
+ }
+
CursedWeaponsManager.getInstance().checkPlayer(player);
// Set the x,y,z position of the PlayerInstance and make it invisible
@@ -7085,6 +7099,17 @@ public final class PlayerInstance extends Playable
{
aVars.storeMe();
}
+
+ if (_spirits != null)
+ {
+ for (ElementalSpirit spirit : _spirits)
+ {
+ if (spirit != null)
+ {
+ spirit.save();
+ }
+ }
+ }
}
@Override
@@ -11434,7 +11459,7 @@ public final class PlayerInstance extends Playable
}
@Override
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
// Check if hit is missed
if (miss)
@@ -11497,7 +11522,15 @@ public final class PlayerInstance extends Playable
}
else if (this != target)
{
- sm = new SystemMessage(SystemMessageId.C1_HAS_INFLICTED_S3_DAMAGE_ON_C2);
+ if (elementalDamage != 0)
+ {
+ sm = new SystemMessage(SystemMessageId.S1_HAS_INFLICTED_S3_DAMAGE_ATTRIBUTE_DAMAGE_S4_TO_S2);
+ }
+ else
+ {
+ sm = new SystemMessage(SystemMessageId.C1_HAS_INFLICTED_S3_DAMAGE_ON_C2);
+ }
+
sm.addPcName(this);
// Localisation related.
@@ -11513,6 +11546,10 @@ public final class PlayerInstance extends Playable
sm.addString(targetName);
sm.addInt(damage);
+ if (elementalDamage != 0)
+ {
+ sm.addInt((int) elementalDamage);
+ }
sm.addPopup(target.getObjectId(), getObjectId(), -damage);
}
@@ -13922,4 +13959,139 @@ public final class PlayerInstance extends Playable
getVariables().set(ATTENDANCE_INDEX_VAR, rewardIndex);
}
}
+
+ public void initElementalSpirits()
+ {
+ tryLoadSpirits();
+
+ if (_spirits == null)
+ {
+ final ElementalType[] types = ElementalType.values();
+ _spirits = new ElementalSpirit[types.length - 1]; // exclude None
+
+ for (ElementalType type : types)
+ {
+ if (ElementalType.NONE == type)
+ {
+ continue;
+ }
+
+ final ElementalSpirit spirit = new ElementalSpirit(type, this);
+ _spirits[type.getId() - 1] = spirit;
+ spirit.save();
+ }
+ }
+
+ if (_activeElementalSpiritType == null)
+ {
+ changeElementalSpirit(ElementalType.FIRE.getId());
+ }
+ }
+
+ private void tryLoadSpirits()
+ {
+ final List spiritsData = ElementalSpiritInstanceManager.getInstance().findByPlayerId(getObjectId());
+ if (!spiritsData.isEmpty())
+ {
+ _spirits = new ElementalSpirit[ElementalType.values().length - 1];
+ for (ElementalSpiritDataHolder spiritData : spiritsData)
+ {
+ _spirits[spiritData.getType() - 1] = new ElementalSpirit(spiritData, this);
+ if (spiritData.isInUse())
+ {
+ _activeElementalSpiritType = ElementalType.of(spiritData.getType());
+ }
+ }
+ }
+ }
+
+ public double getActiveElementalSpiritAttack()
+ {
+ return getStat().getElementalSpiritPower(_activeElementalSpiritType, CommonUtil.zeroIfNullOrElse(getElementalSpirit(_activeElementalSpiritType), ElementalSpirit::getAttack));
+ }
+
+ public double getFireSpiritDefense()
+ {
+ return getElementalSpiritDefenseOf(ElementalType.FIRE);
+ }
+
+ public double getWaterSpiritDefense()
+ {
+ return getElementalSpiritDefenseOf(ElementalType.WATER);
+ }
+
+ public double getWindSpiritDefense()
+ {
+ return getElementalSpiritDefenseOf(ElementalType.WIND);
+ }
+
+ public double getEarthSpiritDefense()
+ {
+ return getElementalSpiritDefenseOf(ElementalType.EARTH);
+ }
+
+ @Override
+ public double getElementalSpiritDefenseOf(ElementalType type)
+ {
+ return getStat().getElementalSpiritDefense(type, CommonUtil.zeroIfNullOrElse(getElementalSpirit(type), ElementalSpirit::getDefense));
+ }
+
+ public double getElementalSpiritCritRate()
+ {
+ return getStat().getElementalSpiritCriticalRate(CommonUtil.zeroIfNullOrElse(getElementalSpirit(_activeElementalSpiritType), ElementalSpirit::getCriticalRate));
+ }
+
+ public double getElementalSpiritCritDamage()
+ {
+ return getStat().getElementalSpiritCriticalDamage(CommonUtil.zeroIfNullOrElse(getElementalSpirit(_activeElementalSpiritType), ElementalSpirit::getCriticalDamage));
+ }
+
+ public double getElementalSpiritXpBonus()
+ {
+ return getStat().getElementalSpiritXpBonus();
+ }
+
+ public ElementalSpirit getElementalSpirit(ElementalType type)
+ {
+ if ((_spirits == null) || (type == null) || (type == ElementalType.NONE))
+ {
+ return null;
+ }
+ return _spirits[type.getId() - 1];
+ }
+
+ public byte getActiveElementalSpiritType()
+ {
+ return (byte) CommonUtil.zeroIfNullOrElse(_activeElementalSpiritType, ElementalType::getId);
+ }
+
+ public void changeElementalSpirit(byte element)
+ {
+ _activeElementalSpiritType = ElementalType.of(element);
+
+ if (_spirits != null)
+ {
+ for (ElementalSpirit spirit : _spirits)
+ {
+ if (spirit != null)
+ {
+ spirit.setInUse(spirit.getType() == element);
+ }
+ }
+ }
+
+ final UserInfo userInfo = new UserInfo(this, false);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ sendPacket(userInfo);
+ }
+
+ public ElementalSpirit[] getSpirits()
+ {
+ return _spirits;
+ }
+
+ public boolean isInBattle()
+ {
+ return AttackStanceTaskManager.getInstance().hasAttackStanceTask(this);
+ }
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/TrapInstance.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/TrapInstance.java
index a9eec7c6ca..1082bca00f 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/TrapInstance.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/TrapInstance.java
@@ -249,11 +249,11 @@ public final class TrapInstance extends Npc
public void doAttack(double damage, Creature target, Skill skill, boolean isDOT, boolean directlyToHp, boolean critical, boolean reflect)
{
super.doAttack(damage, target, skill, isDOT, directlyToHp, critical, reflect);
- sendDamageMessage(target, skill, (int) damage, critical, false);
+ sendDamageMessage(target, skill, (int) damage, 0, critical, false);
}
@Override
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
if (miss || (_owner == null))
{
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java
index 7c1fc412ec..fd1778f549 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java
@@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.data.xml.impl.ExperienceData;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.PartySmallWindowUpdateType;
import org.l2jmobius.gameserver.enums.UserInfoType;
import org.l2jmobius.gameserver.model.Party;
@@ -684,6 +685,31 @@ public class PlayerStat extends PlayableStat
return (int) getValue(Stats.ARTIFACT_SLOTS, 0);
}
+ public double getElementalSpiritXpBonus()
+ {
+ return getValue(Stats.ELEMENTAL_SPIRIT_BONUS_EXP, 1);
+ }
+
+ public double getElementalSpiritPower(ElementalType type, double base)
+ {
+ return type == null ? 0 : getValue(type.getAttackStat(), base);
+ }
+
+ public double getElementalSpiritCriticalRate(int base)
+ {
+ return getValue(Stats.ELEMENTAL_SPIRIT_CRITICAL_RATE, base);
+ }
+
+ public double getElementalSpiritCriticalDamage(double base)
+ {
+ return getValue(Stats.ELEMENTAL_SPIRIT_CRITICAL_DAMAGE, base);
+ }
+
+ public double getElementalSpiritDefense(ElementalType type, double base)
+ {
+ return type == null ? 0 : getValue(type.getDefenseStat(), base);
+ }
+
@Override
protected void onRecalculateStats(boolean broadcast)
{
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
index 2813a06e63..3b38557c75 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
@@ -31,6 +31,7 @@ import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.AISkillScope;
import org.l2jmobius.gameserver.enums.AIType;
import org.l2jmobius.gameserver.enums.DropType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.MpRewardAffectType;
import org.l2jmobius.gameserver.enums.MpRewardType;
import org.l2jmobius.gameserver.enums.Race;
@@ -118,6 +119,9 @@ public final class NpcTemplate extends CreatureTemplate implements IIdentifiable
private List _extendDrop;
+ private ElementalType _elementalType;
+ private long _attributeExp;
+
/**
* Constructor of Creature.
* @param set The StatsSet object to transfer data to the method
@@ -142,6 +146,8 @@ public final class NpcTemplate extends CreatureTemplate implements IIdentifiable
setRace(set.getEnum("race", Race.class, Race.NONE));
_sex = set.getEnum("sex", Sex.class, Sex.ETC);
+ _elementalType = set.getEnum("elementalType", ElementalType.class, ElementalType.NONE);
+
_chestId = set.getInt("chestId", 0);
_rhandId = set.getInt("rhandId", 0);
_lhandId = set.getInt("lhandId", 0);
@@ -150,6 +156,7 @@ public final class NpcTemplate extends CreatureTemplate implements IIdentifiable
_exp = set.getDouble("exp", 0);
_sp = set.getDouble("sp", 0);
_raidPoints = set.getDouble("raidPoints", 0);
+ _attributeExp = set.getLong("attribute_exp", 0);
_unique = set.getBoolean("unique", false);
_attackable = set.getBoolean("attackable", true);
@@ -354,6 +361,16 @@ public final class NpcTemplate extends CreatureTemplate implements IIdentifiable
return _raidPoints;
}
+ public long getAttributeExp()
+ {
+ return _attributeExp;
+ }
+
+ public ElementalType getElementalType()
+ {
+ return _elementalType;
+ }
+
public boolean isUnique()
{
return _unique;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/EventType.java
index 77c1c74906..607e9dd022 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -37,6 +37,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureTeleport;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureTeleported;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureZoneEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureZoneExit;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnElementalSpiritUpgrade;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableFactionCall;
@@ -56,6 +57,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnNpcSkillSee;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnNpcSpawn;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnNpcTeleport;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnNpcTeleportRequest;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnElementalSpiritLearn;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayableExpChanged;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerAbilityPointsChanged;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerAugment;
@@ -286,7 +288,10 @@ public enum EventType
ON_INSTANCE_DESTROY(OnInstanceDestroy.class, void.class),
ON_INSTANCE_ENTER(OnInstanceEnter.class, void.class),
ON_INSTANCE_LEAVE(OnInstanceLeave.class, void.class),
- ON_INSTANCE_STATUS_CHANGE(OnInstanceStatusChange.class, void.class);
+ ON_INSTANCE_STATUS_CHANGE(OnInstanceStatusChange.class, void.class),
+
+ ON_ELEMENTAL_SPIRIT_UPGRADE(OnElementalSpiritUpgrade.class, void.class),
+ ON_ELEMENTAL_SPIRIT_LEARN(OnElementalSpiritLearn.class, void.class);
private final Class extends IBaseEvent> _eventClass;
private final Class>[] _returnClass;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/OnElementalSpiritUpgrade.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/OnElementalSpiritUpgrade.java
new file mode 100644
index 0000000000..018a283d1c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/OnElementalSpiritUpgrade.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature;
+
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author JoeAlisson
+ */
+public class OnElementalSpiritUpgrade implements IBaseEvent
+{
+ private final ElementalSpirit _spirit;
+ private final PlayerInstance _player;
+
+ public OnElementalSpiritUpgrade(PlayerInstance player, ElementalSpirit spirit)
+ {
+ _player = player;
+ _spirit = spirit;
+ }
+
+ public ElementalSpirit getSpirit()
+ {
+ return _spirit;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_ELEMENTAL_SPIRIT_UPGRADE;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnElementalSpiritLearn.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnElementalSpiritLearn.java
new file mode 100644
index 0000000000..6b05b7d982
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnElementalSpiritLearn.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author JoeAlisson
+ */
+public class OnElementalSpiritLearn implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnElementalSpiritLearn(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_ELEMENTAL_SPIRIT_LEARN;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritAbsorbItemHolder.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritAbsorbItemHolder.java
new file mode 100644
index 0000000000..009bca8bc4
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritAbsorbItemHolder.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritAbsorbItemHolder
+{
+ private final int _id;
+ private final int _experience;
+
+ public ElementalSpiritAbsorbItemHolder(int itemId, int experience)
+ {
+ _id = itemId;
+ _experience = experience;
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getExperience()
+ {
+ return _experience;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritDataHolder.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritDataHolder.java
new file mode 100644
index 0000000000..0ae7c46f0c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritDataHolder.java
@@ -0,0 +1,179 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritDataHolder
+{
+ private int _charId;
+ private byte _type;
+ private byte _level = 1;
+ private byte _stage;
+ private long _experience;
+ private byte _attackPoints;
+ private byte _defensePoints;
+ private byte _critRatePoints;
+ private byte _critDamagePoints;
+ private boolean _inUse;
+
+ public ElementalSpiritDataHolder()
+ {
+ }
+
+ public ElementalSpiritDataHolder(byte type, int objectId)
+ {
+ _charId = objectId;
+ _type = type;
+ }
+
+ public int getCharId()
+ {
+ return _charId;
+ }
+
+ public void setCharId(int charId)
+ {
+ _charId = charId;
+ }
+
+ public byte getType()
+ {
+ return _type;
+ }
+
+ public void setType(byte type)
+ {
+ _type = type;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public void setLevel(byte level)
+ {
+ _level = level;
+ }
+
+ public byte getStage()
+ {
+ return _stage;
+ }
+
+ public void setStage(byte stage)
+ {
+ _stage = stage;
+ }
+
+ public long getExperience()
+ {
+ return _experience;
+ }
+
+ public void setExperience(long experience)
+ {
+ _experience = experience;
+ }
+
+ public byte getAttackPoints()
+ {
+ return _attackPoints;
+ }
+
+ public void setAttackPoints(byte attackPoints)
+ {
+ _attackPoints = attackPoints;
+ }
+
+ public byte getDefensePoints()
+ {
+ return _defensePoints;
+ }
+
+ public void setDefensePoints(byte defensePoints)
+ {
+ _defensePoints = defensePoints;
+ }
+
+ public byte getCritRatePoints()
+ {
+ return _critRatePoints;
+ }
+
+ public void setCritRatePoints(byte critRatePoints)
+ {
+ _critRatePoints = critRatePoints;
+ }
+
+ public byte getCritDamagePoints()
+ {
+ return _critDamagePoints;
+ }
+
+ public void setCritDamagePoints(byte critDamagePoints)
+ {
+ _critDamagePoints = critDamagePoints;
+ }
+
+ public void addExperience(long experience)
+ {
+ _experience += experience;
+ }
+
+ public void increaseLevel()
+ {
+ _level++;
+ }
+
+ public boolean isInUse()
+ {
+ return _inUse;
+ }
+
+ public void setInUse(boolean value)
+ {
+ _inUse = value;
+ }
+
+ public void addAttackPoints(byte attackPoints)
+ {
+ _attackPoints += attackPoints;
+ }
+
+ public void addDefensePoints(byte defensePoints)
+ {
+ _defensePoints += defensePoints;
+ }
+
+ public void addCritRatePoints(byte critRatePoints)
+ {
+ _critRatePoints = critRatePoints;
+ }
+
+ public void addCritDamagePoints(byte critDamagePoints)
+ {
+ _critDamagePoints += critDamagePoints;
+ }
+
+ public void increaseStage()
+ {
+ _stage++;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritTemplateHolder.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritTemplateHolder.java
new file mode 100644
index 0000000000..fcac778ac9
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritTemplateHolder.java
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritTemplateHolder
+{
+ private final byte _type;
+ private final byte _stage;
+ private final int _npcId;
+ private final int _maxCharacteristics;
+ private final int _extractItem;
+
+ private final Map _levels;
+ private List _itemsToEvolve;
+ private List _absorbItems;
+
+ public ElementalSpiritTemplateHolder(byte type, byte stage, int npcId, int extractItem, int maxCharacteristics)
+ {
+ _type = type;
+ _stage = stage;
+ _npcId = npcId;
+ _extractItem = extractItem;
+ _maxCharacteristics = maxCharacteristics;
+ _levels = new HashMap<>(10);
+ }
+
+ public void addLevelInfo(int level, int attack, int defense, int criticalRate, int criticalDamage, long maxExperience)
+ {
+ final SpiritLevel spiritLevel = new SpiritLevel();
+ spiritLevel.attack = attack;
+ spiritLevel.defense = defense;
+ spiritLevel.criticalRate = criticalRate;
+ spiritLevel.criticalDamage = criticalDamage;
+ spiritLevel.maxExperience = maxExperience;
+ _levels.put((byte) level, spiritLevel);
+ }
+
+ public void addItemToEvolve(Integer itemId, Integer count)
+ {
+ if (_itemsToEvolve == null)
+ {
+ _itemsToEvolve = new ArrayList<>(2);
+ }
+ _itemsToEvolve.add(new ItemHolder(itemId, count));
+ }
+
+ public byte getType()
+ {
+ return _type;
+ }
+
+ public byte getStage()
+ {
+ return _stage;
+ }
+
+ public int getNpcId()
+ {
+ return _npcId;
+ }
+
+ public long getMaxExperienceAtLevel(byte level)
+ {
+ return _levels.get(level).maxExperience;
+ }
+
+ public int getMaxLevel()
+ {
+ return _levels.size();
+ }
+
+ public int getAttackAtLevel(byte level)
+ {
+ return _levels.get(level).attack;
+ }
+
+ public int getDefenseAtLevel(byte level)
+ {
+ return _levels.get(level).defense;
+ }
+
+ public int getCriticalRateAtLevel(byte level)
+ {
+ return _levels.get(level).criticalRate;
+ }
+
+ public int getCriticalDamageAtLevel(byte level)
+ {
+ return _levels.get(level).criticalDamage;
+ }
+
+ public int getMaxCharacteristics()
+ {
+ return _maxCharacteristics;
+ }
+
+ public List getItemsToEvolve()
+ {
+ return _itemsToEvolve == null ? Collections.emptyList() : _itemsToEvolve;
+ }
+
+ public void addAbsorbItem(Integer itemId, Integer experience)
+ {
+ if (_absorbItems == null)
+ {
+ _absorbItems = new ArrayList<>();
+ }
+ _absorbItems.add(new ElementalSpiritAbsorbItemHolder(itemId, experience));
+ }
+
+ public List getAbsorbItems()
+ {
+ return _absorbItems == null ? Collections.emptyList() : _absorbItems;
+ }
+
+ public int getExtractItem()
+ {
+ return _extractItem;
+ }
+
+ private static class SpiritLevel
+ {
+ public SpiritLevel()
+ {
+ }
+
+ long maxExperience;
+ int criticalDamage;
+ int criticalRate;
+ int defense;
+ int attack;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/Formulas.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/Formulas.java
index 3d75ea852e..92c5c50e1b 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/Formulas.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/Formulas.java
@@ -27,6 +27,7 @@ import org.l2jmobius.gameserver.data.xml.impl.KarmaData;
import org.l2jmobius.gameserver.enums.AttributeType;
import org.l2jmobius.gameserver.enums.BasicProperty;
import org.l2jmobius.gameserver.enums.DispelSlotType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.Position;
import org.l2jmobius.gameserver.enums.ShotType;
import org.l2jmobius.gameserver.model.actor.Creature;
@@ -1652,4 +1653,77 @@ public final class Formulas
return 1;
}
+
+ public static double calcSpiritElementalDamage(Creature attacker, Creature target)
+ {
+ if (attacker.isPlayer())
+ {
+ final PlayerInstance attackerPlayer = attacker.getActingPlayer();
+ ElementalType type = ElementalType.of(attackerPlayer.getActiveElementalSpiritType());
+
+ if (ElementalType.NONE == type)
+ {
+ return 0;
+ }
+
+ final double critRate = attackerPlayer.getElementalSpiritCritRate();
+ final boolean isCrit = Math.min(critRate, 380) > Rnd.get(1000);
+ final double critDamage = attackerPlayer.getElementalSpiritCritDamage();
+ final double attack = attackerPlayer.getActiveElementalSpiritAttack() - target.getElementalSpiritDefenseOf(type);
+ if (target.isPlayer())
+ {
+ return calcSpiritElementalPvPDamage(attack, critDamage, isCrit);
+ }
+ return calcSpiritElementalPvEDamage(type, target.getElementalSpiritType(), attack, critDamage, isCrit);
+ }
+
+ return 0;
+ }
+
+ private static double calcSpiritElementalPvPDamage(double attack, double critDamage, boolean isCrit)
+ {
+ double damage = (attack * 1.223) + Rnd.get(-20, +20);
+ if (isCrit)
+ {
+ damage += (attack * 1.223) + (((attack * 0.03) + 24) * critDamage) + Rnd.get(-5, 30);
+ }
+ return damage;
+ }
+
+ private static double calcSpiritElementalPvEDamage(ElementalType attackerType, ElementalType targetType, double attack, double critDamage, boolean isCrit)
+ {
+ double damage;
+ double baseDamage = (attack * 0.8) + Rnd.get(-25, 25);
+ double bonus = 1;
+ if (targetType == ElementalType.NONE)
+ {
+ damage = attack * 0.735;
+ }
+ else if (attackerType.getDominating() == targetType)
+ {
+ damage = (-1136 + baseDamage) * 0.6;
+ bonus = 0.6;
+ }
+ else if (targetType.getDominating() == attackerType)
+ {
+ damage = (185 + baseDamage) * 1.2;
+ bonus = 1.2;
+ }
+ else if (targetType == attackerType)
+ {
+ damage = baseDamage;
+ }
+ else
+ {
+ damage = (-477 + baseDamage) * 0.8;
+ bonus = 0.8;
+ }
+
+ if (isCrit)
+ {
+ damage += ((40 + ((9.2 + (attack * 0.048)) * critDamage)) * bonus) + Rnd.get(-10, 50);
+ }
+
+ return damage;
+ }
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/Stats.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/Stats.java
index d1defb05d5..24ff26bae8 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/Stats.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/stats/Stats.java
@@ -89,6 +89,19 @@ public enum Stats
HATE_ATTACK("attackHate"),
REAR_DAMAGE_RATE("rearDamage"),
+ // ELEMENTAL SPIRITS
+ ELEMENTAL_SPIRIT_FIRE_ATTACK("elementalSpiritFireAttack"),
+ ELEMENTAL_SPIRIT_WATER_ATTACK("elementalSpiritWaterAttack"),
+ ELEMENTAL_SPIRIT_WIND_ATTACK("elementalSpiritWindAttack"),
+ ELEMENTAL_SPIRIT_EARTH_ATTACK("elementalSpiritEarthAttack"),
+ ELEMENTAL_SPIRIT_FIRE_DEFENSE("elementalSpiritFireDefense"),
+ ELEMENTAL_SPIRIT_WATER_DEFENSE("elementalSpiritWaterDefense"),
+ ELEMENTAL_SPIRIT_WIND_DEFENSE("elementalSpiritWindDefense"),
+ ELEMENTAL_SPIRIT_EARTH_DEFENSE("elementalSpiritEarthDefense"),
+ ELEMENTAL_SPIRIT_CRITICAL_RATE("elementalSpiritCriticalRate"),
+ ELEMENTAL_SPIRIT_CRITICAL_DAMAGE("elementalSpiritCriticalDamage"),
+ ELEMENTAL_SPIRIT_BONUS_EXP("elementalSpiritExp"),
+
// PVP BONUS
PVP_PHYSICAL_ATTACK_DAMAGE("pvpPhysDmg"),
PVP_MAGICAL_SKILL_DAMAGE("pvpMagicalDmg"),
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index f2e8906daa..47151992cd 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -60,7 +60,16 @@ import org.l2jmobius.gameserver.network.clientpackets.crystalization.RequestCrys
import org.l2jmobius.gameserver.network.clientpackets.crystalization.RequestCrystallizeItemCancel;
import org.l2jmobius.gameserver.network.clientpackets.dailymission.RequestOneDayRewardReceive;
import org.l2jmobius.gameserver.network.clientpackets.dailymission.RequestTodoList;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalInitTalent;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritAbsorb;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritAbsorbInfo;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritChangeType;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritEvolution;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritEvolutionInfo;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritExtract;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritExtractInfo;
import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritInfo;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritSetTalent;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.friend.RequestFriendDetailInfo;
@@ -423,21 +432,21 @@ public enum ExIncomingPackets implements IIncomingPackets
EX_PLEDGE_ITEM_INFO(0x14E, null, ConnectionState.IN_GAME),
EX_PLEDGE_ITEM_BUY(0x14F, null, ConnectionState.IN_GAME),
EX_ELEMENTAL_SPIRIT_INFO(0x150, ExElementalSpiritInfo::new, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_EXTRACT_INFO(0x151, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_EXTRACT(0x152, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_EVOLUTION_INFO(0x153, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_EVOLUTION(0x154, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_SET_TALENT(0x155, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_INIT_TALENT(0x156, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_ABSORB_INFO(0x157, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_ABSORB(0x158, null, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_EXTRACT_INFO(0x151, ExElementalSpiritExtractInfo::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_EXTRACT(0x152, ExElementalSpiritExtract::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_EVOLUTION_INFO(0x153, ExElementalSpiritEvolutionInfo::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_EVOLUTION(0x154, ExElementalSpiritEvolution::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_SET_TALENT(0x155, ExElementalSpiritSetTalent::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_INIT_TALENT(0x156, ExElementalInitTalent::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_ABSORB_INFO(0x157, ExElementalSpiritAbsorbInfo::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_ABSORB(0x158, ExElementalSpiritAbsorb::new, ConnectionState.IN_GAME),
EX_REQUEST_LOCKED_ITEM(0x159, null, ConnectionState.IN_GAME),
EX_REQUEST_UNLOCKED_ITEM(0x15A, null, ConnectionState.IN_GAME),
EX_LOCKED_ITEM_CANCEL(0x15B, null, ConnectionState.IN_GAME),
EX_UNLOCKED_ITEM_CANCEL(0x15C, null, ConnectionState.IN_GAME),
- REQUEST_BLOCK_LIST_FOR_AD(0x15D, null, ConnectionState.IN_GAME),
- REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_CHANGE_TYPE(0x15F, null, ConnectionState.IN_GAME), // 152
+ EX_ELEMENTAL_SPIRIT_CHANGE_TYPE(0x15D, ExElementalSpiritChangeType::new, ConnectionState.IN_GAME), // 152
+ REQUEST_BLOCK_LIST_FOR_AD(0x15E, null, ConnectionState.IN_GAME),
+ REQUEST_USER_BAN_INFO(0x15F, null, ConnectionState.IN_GAME),
EX_INTERACT_MODIFY(0x160, null, ConnectionState.IN_GAME), // 152
EX_TRY_ENCHANT_ARTIFACT(0x161, null, ConnectionState.IN_GAME), // 152
EX_XIGN_CODE(0x162, null, ConnectionState.IN_GAME); // 152
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalInitTalent.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalInitTalent.java
new file mode 100644
index 0000000000..14a27e814c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalInitTalent.java
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.data.xml.impl.ElementalSpiritData;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritSetTalent;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalInitTalent implements IClientIncomingPacket
+{
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ if (player.isInBattle())
+ {
+ client.sendPacket(new SystemMessage(SystemMessageId.UNABLE_TO_RESET_SPIRIT_ATTRIBUTE_DURING_BATTLE));
+ client.sendPacket(new ElementalSpiritSetTalent(player, _type, false));
+ return;
+ }
+
+ if (player.reduceAdena("Talent", ElementalSpiritData.TALENT_INIT_FEE, player, true))
+ {
+ spirit.resetCharacteristics();
+ client.sendPacket(new SystemMessage(SystemMessageId.RESET_THE_SELECTED_SPIRIT_S_CHARACTERISTICS_SUCCESSFULLY));
+ client.sendPacket(new ElementalSpiritSetTalent(player, _type, true));
+ }
+ else
+ {
+ client.sendPacket(new ElementalSpiritSetTalent(player, _type, false));
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorb.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorb.java
new file mode 100644
index 0000000000..15a2d4a37f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorb.java
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.PrivateStoreType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritAbsorbItemHolder;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritAbsorb;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritAbsorb implements IClientIncomingPacket
+{
+ private byte _type;
+ private int _itemId;
+ private int _amount;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ packet.readD(); // items for now is always 1
+ _itemId = packet.readD();
+ _amount = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ final ElementalSpiritAbsorbItemHolder absorbItem = spirit.getAbsorbItem(_itemId);
+ if (absorbItem == null)
+ {
+ player.sendPacket(new ElementalSpiritAbsorb(player, _type, false));
+ return;
+ }
+
+ final boolean canAbsorb = checkConditions(player, spirit);
+ if (canAbsorb)
+ {
+ client.sendPacket(SystemMessageId.SUCCESFUL_ABSORPTION);
+ spirit.addExperience(absorbItem.getExperience() * _amount);
+ final UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ client.sendPacket(userInfo);
+ }
+ client.sendPacket(new ElementalSpiritAbsorb(player, _type, canAbsorb));
+ }
+
+ private boolean checkConditions(PlayerInstance player, ElementalSpirit spirit)
+ {
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessageId.CANNOT_EVOLVE_ABSORB_EXTRACT_WHILE_USING_THE_PRIVATE_STORE_WORKSHOP);
+ return false;
+ }
+ if (player.isInBattle())
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_ABSORB_DURING_BATTLE);
+ return false;
+ }
+ if ((spirit.getLevel() == spirit.getMaxLevel()) && (spirit.getExperience() == spirit.getExperienceToNextLevel()))
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_ABSORB_BECAUSE_REACHED_MAXIMUM_LEVEL);
+ return false;
+ }
+ if ((_amount < 1) || !player.destroyItemByItemId("Absorb", _itemId, _amount, player, true))
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_INGREDIENTS_TO_ABSORB);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorbInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorbInfo.java
new file mode 100644
index 0000000000..70aa8f9afb
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorbInfo.java
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritAbsorbInfo;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritAbsorbInfo implements IClientIncomingPacket
+{
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ packet.readC(); // unk
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ client.sendPacket(new ElementalSpiritAbsorbInfo(player, _type));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritChangeType.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritChangeType.java
new file mode 100644
index 0000000000..3f5aabb16d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritChangeType.java
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritInfo;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritChangeType implements IClientIncomingPacket
+{
+ private byte _type;
+ private byte _element;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ _element = (byte) packet.readC(); // 1 - Fire, 2 - Water, 3 - Wind, 4 Earth
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ player.changeElementalSpirit(_element);
+ client.sendPacket(new ElementalSpiritInfo(player, _element, _type));
+ client.sendPacket(new SystemMessage(SystemMessageId.S1_WILL_BE_YOUR_ATTRIBUTE_ATTACK_FROM_NOW_ON).addElementalSpirit(_element));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolution.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolution.java
new file mode 100644
index 0000000000..59bee00d84
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolution.java
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import java.util.stream.Collectors;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.InventoryBlockType;
+import org.l2jmobius.gameserver.enums.PrivateStoreType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.itemcontainer.PlayerInventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritEvolution;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritEvolution implements IClientIncomingPacket
+{
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ final boolean canEvolve = checkConditions(player, spirit);
+ if (canEvolve)
+ {
+ spirit.upgrade();
+ client.sendPacket(new SystemMessage(SystemMessageId.S1_EVOLVED_TO_S2_STAR).addElementalSpirit(_type).addInt(spirit.getStage()));
+ final UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ client.sendPacket(userInfo);
+ }
+ client.sendPacket(new ElementalSpiritEvolution(player, _type, canEvolve));
+ }
+
+ private boolean checkConditions(PlayerInstance player, ElementalSpirit spirit)
+ {
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessageId.CANNOT_EVOLVE_ABSORB_EXTRACT_WHILE_USING_THE_PRIVATE_STORE_WORKSHOP);
+ return false;
+ }
+ if (player.isInBattle())
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_EVOLVE_DURING_BATTLE);
+ return false;
+ }
+ if (!spirit.canEvolve())
+ {
+ player.sendPacket(SystemMessageId.THIS_SPIRIT_CANNOT_EVOLVE);
+ return false;
+ }
+ if (!consumeEvolveItems(player, spirit))
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_INGREDIENTS_FOR_EVOLUTION);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean consumeEvolveItems(PlayerInstance player, ElementalSpirit spirit)
+ {
+ final PlayerInventory inventory = player.getInventory();
+ try
+ {
+ inventory.setInventoryBlock(spirit.getItemsToEvolve().stream().map(ItemHolder::getId).collect(Collectors.toList()), InventoryBlockType.BLACKLIST);
+ for (ItemHolder itemHolder : spirit.getItemsToEvolve())
+ {
+ if (inventory.getInventoryItemCount(itemHolder.getId(), -1) < itemHolder.getCount())
+ {
+ return false;
+ }
+ }
+
+ for (ItemHolder itemHolder : spirit.getItemsToEvolve())
+ {
+ player.destroyItemByItemId("Evolve", itemHolder.getId(), itemHolder.getCount(), player, true);
+ }
+ return true;
+ }
+ finally
+ {
+ inventory.unblock();
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolutionInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolutionInfo.java
new file mode 100644
index 0000000000..e56fe717bb
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolutionInfo.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritEvolutionInfo;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritEvolutionInfo implements IClientIncomingPacket
+{
+ private byte _id;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _id = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ client.sendPacket(new ElementalSpiritEvolutionInfo(player, _id));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtract.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtract.java
new file mode 100644
index 0000000000..b56de927e9
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtract.java
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.data.xml.impl.ElementalSpiritData;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.PrivateStoreType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritExtract;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritExtract implements IClientIncomingPacket
+{
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ final boolean canExtract = checkConditions(player, spirit);
+ if (canExtract)
+ {
+ final int amount = spirit.getExtractAmount();
+ client.sendPacket(new SystemMessage(SystemMessageId.EXTRACTED_S1_S2_SUCCESSFULLY).addItemName(spirit.getExtractItem()).addInt(amount));
+ spirit.resetStage();
+ player.addItem("Extract", spirit.getExtractItem(), amount, player, true);
+
+ final UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ client.sendPacket(userInfo);
+ }
+
+ client.sendPacket(new ElementalSpiritExtract(player, _type, canExtract));
+ }
+
+ private boolean checkConditions(PlayerInstance player, ElementalSpirit spirit)
+ {
+ if (spirit.getExtractAmount() < 1)
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_ATTRIBUTE_XP_FOR_EXTRACTION);
+ return false;
+ }
+ if (!player.getInventory().validateCapacity(1))
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_EXTRACT_BECAUSE_INVENTORY_IS_FULL);
+ return false;
+ }
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessageId.CANNOT_EVOLVE_ABSORB_EXTRACT_WHILE_USING_THE_PRIVATE_STORE_WORKSHOP);
+ return false;
+ }
+ if (player.isInBattle())
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_EVOLVE_DURING_BATTLE);
+ return false;
+ }
+ if (!player.reduceAdena("Extract", ElementalSpiritData.EXTRACT_FEE, player, true))
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_INGREDIENTS_TO_EXTRACT);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtractInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtractInfo.java
new file mode 100644
index 0000000000..86a7317d11
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtractInfo.java
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritExtractInfo;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritExtractInfo implements IClientIncomingPacket
+{
+
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ client.sendPacket(new ElementalSpiritExtractInfo(player, _type));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritInfo.java
index a9347a67c2..a15b135e9c 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritInfo.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritInfo.java
@@ -20,19 +20,19 @@ import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritInfo;
/**
- * @author Mobius
+ * @author JoeAlisson
*/
public class ExElementalSpiritInfo implements IClientIncomingPacket
{
- @SuppressWarnings("unused")
- private int _id;
+ private byte _type;
@Override
public boolean read(GameClient client, PacketReader packet)
{
- _id = packet.readC();
+ _type = (byte) packet.readC();
return true;
}
@@ -45,6 +45,6 @@ public class ExElementalSpiritInfo implements IClientIncomingPacket
return;
}
- // player.sendPacket(new org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ExElementalSpiritInfo());
+ client.sendPacket(new ElementalSpiritInfo(player, player.getActiveElementalSpiritType(), _type));
}
-}
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritSetTalent.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritSetTalent.java
new file mode 100644
index 0000000000..731406e41d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritSetTalent.java
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritSetTalent;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritSetTalent implements IClientIncomingPacket
+{
+ private byte _type;
+ private byte _attackPoints;
+ private byte _defensePoints;
+ private byte _critRate;
+ private byte _critDamage;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ packet.readC(); // Characteristics for now always 4
+
+ packet.readC(); // attack id
+ _attackPoints = (byte) packet.readC();
+
+ packet.readC(); // defense id
+ _defensePoints = (byte) packet.readC();
+
+ packet.readC(); // crit rate id
+ _critRate = (byte) packet.readC();
+
+ packet.readC(); // crit damage id
+ _critDamage = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ boolean result = false;
+ if (spirit != null)
+ {
+ if ((_attackPoints > 0) && (spirit.getAvailableCharacteristicsPoints() >= _attackPoints))
+ {
+ spirit.addAttackPoints(_attackPoints);
+ result = true;
+ }
+
+ if ((_defensePoints > 0) && (spirit.getAvailableCharacteristicsPoints() >= _defensePoints))
+ {
+ spirit.addDefensePoints(_defensePoints);
+ result = true;
+ }
+
+ if ((_critRate > 0) && (spirit.getAvailableCharacteristicsPoints() >= _critRate))
+ {
+ spirit.addCritRatePoints(_critRate);
+ result = true;
+ }
+
+ if ((_critDamage > 0) && (spirit.getAvailableCharacteristicsPoints() >= _critDamage))
+ {
+ spirit.addCritDamage(_critDamage);
+ result = true;
+ }
+ }
+
+ if (result)
+ {
+ final UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ client.sendPacket(userInfo);
+ client.sendPacket(new SystemMessage(SystemMessageId.CHARACTERISTICS_WERE_APPLIED_SUCCESSFULLY));
+ }
+ client.sendPacket(new ElementalSpiritSetTalent(player, _type, result));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ConfirmDlg.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ConfirmDlg.java
index adf7845f18..dd70213119 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ConfirmDlg.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ConfirmDlg.java
@@ -80,6 +80,7 @@ public class ConfirmDlg implements IClientOutgoingPacket
case SystemMessage.TYPE_ELEMENT_NAME:
case SystemMessage.TYPE_BYTE:
case SystemMessage.TYPE_FACTION_NAME:
+ case SystemMessage.TYPE_ELEMENTAL_SPIRIT:
{
packet.writeC(param.getIntValue());
break;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/SystemMessage.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/SystemMessage.java
index 13a9444fe9..641446744f 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/SystemMessage.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/SystemMessage.java
@@ -80,6 +80,7 @@ public final class SystemMessage implements IClientOutgoingPacket
}
}
+ public static final byte TYPE_ELEMENTAL_SPIRIT = 26;
public static final byte TYPE_FACTION_NAME = 24; // c(short), faction id.
// id 22 d (shared with 1-3,17,22
// id 21 h
@@ -374,6 +375,12 @@ public final class SystemMessage implements IClientOutgoingPacket
return this;
}
+ public SystemMessage addElementalSpirit(int elementType)
+ {
+ append(new SMParam(TYPE_ELEMENTAL_SPIRIT, elementType));
+ return this;
+ }
+
public SMParam[] getParams()
{
return _params;
@@ -419,6 +426,7 @@ public final class SystemMessage implements IClientOutgoingPacket
case TYPE_ELEMENT_NAME:
case TYPE_BYTE:
case TYPE_FACTION_NAME:
+ case TYPE_ELEMENTAL_SPIRIT:
{
packet.writeC(param.getIntValue());
break;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/UserInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/UserInfo.java
index 7199f724d9..d2ea90ce38 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/UserInfo.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/UserInfo.java
@@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.network.serverpackets;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.data.xml.impl.ExperienceData;
-import org.l2jmobius.gameserver.enums.AttributeType;
import org.l2jmobius.gameserver.enums.UserInfoType;
import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import org.l2jmobius.gameserver.model.Party;
@@ -376,12 +375,12 @@ public class UserInfo extends AbstractMaskPacket
if (containsMask(UserInfoType.ATT_SPIRITS)) // 152
{
packet.writeH(26);
- packet.writeD(_player.getAttackElementValue(_player.getAttackElement())); // Attribute Attack Power
- packet.writeD(_player.getDefenseElementValue(AttributeType.FIRE)); // Fire defence
- packet.writeD(_player.getDefenseElementValue(AttributeType.WATER)); // Water defence
- packet.writeD(_player.getDefenseElementValue(AttributeType.WIND)); // Wind defence
- packet.writeD(_player.getDefenseElementValue(AttributeType.EARTH)); // Earth defence
- packet.writeD(0x00); // Enabled 1 - Disabled 0 // Third class player?
+ packet.writeD((int) _player.getActiveElementalSpiritAttack());
+ packet.writeD((int) _player.getFireSpiritDefense());
+ packet.writeD((int) _player.getWaterSpiritDefense());
+ packet.writeD((int) _player.getWindSpiritDefense());
+ packet.writeD((int) _player.getEarthSpiritDefense());
+ packet.writeD(_player.getActiveElementalSpiritType());
}
return true;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/AbstractElementalSpiritPacket.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/AbstractElementalSpiritPacket.java
new file mode 100644
index 0000000000..f0d1fb0d65
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/AbstractElementalSpiritPacket.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+abstract class AbstractElementalSpiritPacket implements IClientOutgoingPacket
+{
+ void writeSpiritInfo(PacketWriter packet, ElementalSpirit spirit)
+ {
+ packet.writeC(spirit.getStage());
+ packet.writeD(spirit.getNpcId());
+ packet.writeQ(spirit.getExperience());
+ packet.writeQ(spirit.getExperienceToNextLevel());
+ packet.writeQ(spirit.getExperienceToNextLevel());
+ packet.writeD(spirit.getLevel());
+ packet.writeD(spirit.getMaxLevel());
+ packet.writeD(spirit.getAvailableCharacteristicsPoints());
+ packet.writeD(spirit.getAttackPoints());
+ packet.writeD(spirit.getDefensePoints());
+ packet.writeD(spirit.getCriticalRatePoints());
+ packet.writeD(spirit.getCriticalDamagePoints());
+ packet.writeD(spirit.getMaxCharacteristics());
+ packet.writeD(spirit.getMaxCharacteristics());
+ packet.writeD(spirit.getMaxCharacteristics());
+ packet.writeD(spirit.getMaxCharacteristics());
+
+ packet.writeC(1); // unk
+
+ for (int j = 0; j < 1; j++)
+ {
+ packet.writeH(2);
+ packet.writeQ(100);
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorb.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorb.java
new file mode 100644
index 0000000000..8929baea65
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorb.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritAbsorb extends UpdateElementalSpiritPacket
+{
+ public ElementalSpiritAbsorb(PlayerInstance player, byte type, boolean absorbed)
+ {
+ super(player, type, absorbed);
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_ABSORB.writeId(packet);
+ writeUpdate(packet);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorbInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorbInfo.java
new file mode 100644
index 0000000000..66579ff8ab
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorbInfo.java
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritAbsorbItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritAbsorbInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final byte _type;
+
+ public ElementalSpiritAbsorbInfo(PlayerInstance player, byte type)
+ {
+ _player = player;
+ _type = type;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_ABSORB_INFO.writeId(packet);
+
+ final ElementalSpirit spirit = _player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ packet.writeC(0x00);
+ packet.writeC(0x00);
+ return true;
+ }
+
+ packet.writeC(0x01);
+ packet.writeC(_type);
+ packet.writeC(spirit.getStage());
+ packet.writeQ(spirit.getExperience());
+ packet.writeQ(spirit.getExperienceToNextLevel()); // NextExp
+ packet.writeQ(spirit.getExperienceToNextLevel()); // MaxExp
+ packet.writeD(spirit.getLevel());
+ packet.writeD(spirit.getMaxLevel());
+
+ final List absorbItems = spirit.getAbsorbItems();
+ packet.writeD(absorbItems.size()); // AbsorbCount
+ for (ElementalSpiritAbsorbItemHolder absorbItem : absorbItems)
+ {
+ packet.writeD(absorbItem.getId());
+ packet.writeD(CommonUtil.zeroIfNullOrElse(_player.getInventory().getItemByItemId(absorbItem.getId()), item -> (int) item.getCount()));
+ packet.writeD(absorbItem.getExperience());
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolution.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolution.java
new file mode 100644
index 0000000000..e7bf800936
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolution.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritEvolution extends UpdateElementalSpiritPacket
+{
+ public ElementalSpiritEvolution(PlayerInstance player, byte type, boolean evolved)
+ {
+ super(player, type, evolved);
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_EVOLUTION.writeId(packet);
+ writeUpdate(packet);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolutionInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolutionInfo.java
new file mode 100644
index 0000000000..98d0586c69
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolutionInfo.java
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritEvolutionInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final byte _type;
+
+ public ElementalSpiritEvolutionInfo(PlayerInstance player, byte type)
+ {
+ _player = player;
+ _type = type;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_EVOLUTION_INFO.writeId(packet);
+
+ final ElementalSpirit spirit = _player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ packet.writeC(0);
+ packet.writeD(0);
+ return true;
+ }
+
+ packet.writeC(_type);
+ packet.writeD(spirit.getNpcId());
+ packet.writeD(0x01); // unk
+ packet.writeD(spirit.getStage());
+ packet.writeF(100); // chance ??
+
+ final List items = spirit.getItemsToEvolve();
+ packet.writeD(items.size());
+ for (ItemHolder item : items)
+ {
+ packet.writeD(item.getId());
+ packet.writeQ(item.getCount());
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtract.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtract.java
new file mode 100644
index 0000000000..2f4519e73a
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtract.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritExtract extends UpdateElementalSpiritPacket
+{
+ public ElementalSpiritExtract(PlayerInstance player, byte type, boolean extracted)
+ {
+ super(player, type, extracted);
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_EXTRACT.writeId(packet);
+ writeUpdate(packet);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtractInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtractInfo.java
new file mode 100644
index 0000000000..db2c606219
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtractInfo.java
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritExtractInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final byte _type;
+
+ public ElementalSpiritExtractInfo(PlayerInstance player, byte type)
+ {
+ _player = player;
+ _type = type;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_EXTRACT_INFO.writeId(packet);
+
+ final ElementalSpirit spirit = _player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ packet.writeC(0);
+ packet.writeC(0);
+ return true;
+ }
+
+ packet.writeC(_type); // active elemental spirit
+ packet.writeC(1); // is extract ?
+
+ packet.writeC(1); // cost count
+ // for each cost count
+ packet.writeD(57); // item id
+ packet.writeD(1000000); // item count
+
+ packet.writeD(spirit.getExtractItem());
+ packet.writeD(spirit.getExtractAmount());
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritInfo.java
new file mode 100644
index 0000000000..e55bc735f1
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritInfo.java
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritInfo extends AbstractElementalSpiritPacket
+{
+ private final PlayerInstance _player;
+ private final byte _spiritType;
+ private final byte _type;
+
+ public ElementalSpiritInfo(PlayerInstance player, byte spiritType, byte packetType)
+ {
+ _player = player;
+ _spiritType = spiritType;
+ _type = packetType;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_INFO.writeId(packet);
+
+ final ElementalSpirit[] spirits = _player.getSpirits();
+ if (spirits == null)
+ {
+ packet.writeC(0);
+ packet.writeC(0);
+ packet.writeC(0);
+ return true;
+ }
+
+ packet.writeC(_type); // show spirit info window 1; Change type 2; Only update 0
+ packet.writeC(_spiritType);
+
+ packet.writeC(spirits.length); // spirit count
+
+ for (ElementalSpirit spirit : spirits)
+ {
+ packet.writeC(spirit.getType());
+ packet.writeC(0x01); // spirit active ?
+ // if active
+ writeSpiritInfo(packet, spirit);
+ }
+
+ packet.writeD(1); // Reset talent items count
+ for (int j = 0; j < 1; j++)
+ {
+ packet.writeD(57);
+ packet.writeQ(50000);
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritSetTalent.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritSetTalent.java
new file mode 100644
index 0000000000..c6184ee407
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritSetTalent.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritSetTalent extends UpdateElementalSpiritPacket
+{
+ public ElementalSpiritSetTalent(PlayerInstance player, byte type, boolean result)
+ {
+ super(player, type, result);
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_SET_TALENT.writeId(packet);
+ writeUpdate(packet);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ExElementalSpiritGetExp.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ExElementalSpiritGetExp.java
new file mode 100644
index 0000000000..bc05ef3212
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ExElementalSpiritGetExp.java
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritGetExp implements IClientOutgoingPacket
+{
+ private final long _experience;
+ private final byte _type;
+
+ public ExElementalSpiritGetExp(byte type, long experience)
+ {
+ _type = type;
+ _experience = experience;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_GET_EXP.writeId(packet);
+
+ packet.writeC(_type);
+ packet.writeQ(_experience);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/UpdateElementalSpiritPacket.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/UpdateElementalSpiritPacket.java
new file mode 100644
index 0000000000..e81ae91f8c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/UpdateElementalSpiritPacket.java
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+
+/**
+ * @author JoeAlisson
+ */
+public abstract class UpdateElementalSpiritPacket extends AbstractElementalSpiritPacket
+{
+ private final PlayerInstance _player;
+ private final byte _type;
+ private final boolean _update;
+
+ UpdateElementalSpiritPacket(PlayerInstance player, byte type, boolean update)
+ {
+ _player = player;
+ _type = type;
+ _update = update;
+ }
+
+ protected void writeUpdate(PacketWriter packet)
+ {
+ packet.writeC(_update ? 1 : 0);
+ packet.writeC(_type);
+
+ if (_update)
+ {
+ final ElementalSpirit spirit = _player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ return;
+ }
+
+ packet.writeC(_type);
+ writeSpiritInfo(packet, spirit);
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/readme.txt b/L2J_Mobius_Classic_2.3_SevenSigns/readme.txt
index 39ca6e12bb..a97d62edf2 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/readme.txt
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/readme.txt
@@ -79,6 +79,7 @@ Seven Signs: https://eu.4gameforum.com/threads/658543/
-Parsed new NPCs from client
-Updated skiltrees and skills from L2Wiki
-Updated experience values from L2Wiki
+-Elemental Spirits
-Land of Winds spawns
-Goddard territory spawns
-Goddard clanhalls
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/db_installer/sql/game/character_spirits.sql b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/db_installer/sql/game/character_spirits.sql
new file mode 100644
index 0000000000..2d0b88e637
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/db_installer/sql/game/character_spirits.sql
@@ -0,0 +1,17 @@
+DROP TABLE IF EXISTS `character_spirits`;
+CREATE TABLE `character_spirits`
+(
+ `charId` INT UNSIGNED NOT NULL,
+ `type` TINYINT NOT NULL,
+ `level` TINYINT NOT NULL DEFAULT 1,
+ `stage` TINYINT NOT NULL DEFAULT 0,
+ `experience` BIGINT NOT NULL DEFAULT 0,
+ `attack_points` TINYINT NOT NULL DEFAULT 0,
+ `defense_points` TINYINT NOT NULL DEFAULT 0,
+ `crit_rate_points` TINYINT NOT NULL DEFAULT 0,
+ `crit_damage_points` TINYINT NOT NULL DEFAULT 0,
+ `in_use` BOOLEAN NOT NULL DEFAULT FALSE,
+ PRIMARY KEY (`charId`, `type`),
+ FOREIGN KEY FK_CHARACTER_SPIRITS (`charId`) REFERENCES characters (`charId`) ON DELETE CASCADE
+) ENGINE = InnoDB
+ DEFAULT CHARSET = utf8;
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/ElementalSpiritData.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/ElementalSpiritData.xml
new file mode 100644
index 0000000000..36fa5ea7f0
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/ElementalSpiritData.xml
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-1.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-1.htm
new file mode 100644
index 0000000000..ace0eab708
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-1.htm
@@ -0,0 +1,14 @@
+Svein:
+What are you curious to know about spirits?
+I will do my best to tell you everything I know.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-11.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-11.htm
new file mode 100644
index 0000000000..d8420b8987
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-11.htm
@@ -0,0 +1,8 @@
+Svein:
+Are you curious about checking the spirits' status?
+Start by opening the Character Information window.
+(You can open Character Information window with Alt+T.)
+If you click the Spirits button in the lower screen, you can check the spirits' status.
+Is there anything else you're curious about?
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-12.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-12.htm
new file mode 100644
index 0000000000..58e113dc91
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-12.htm
@@ -0,0 +1,15 @@
+Svein:
+Attribute Effect changes damage dealt and taken in battle.
+[Attribute Types]
+Spirits are classified according to 4 attributes of water, fire, wind and earth.
+[Attribute Attack and Growth]
+When you attack monsters, damage increases depending on attribute.
+But when you attack monsters by attribute, damage changes according to the monsters' attribute growth.
+With Growth Effect, a strong attribute gives 20% more damage, while a weak attribute can give no more than 60% damage.
+Relative Growth refers to relativity between attributes, where water is strong than fire and fire is stronger than wind. Also, wind is stronger than earth and earth is stronger than water.
+The attributes ae relatively linked, so you must not be careless with any one attribute.
+[Attribute Defense]
+If you're attacked with an attribute, your attribute defense withstands the attack.
+In this situation, it is important to know who has the higher attribute P. Def.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-13.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-13.htm
new file mode 100644
index 0000000000..f78eb3ad34
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-13.htm
@@ -0,0 +1,14 @@
+Svein:
+To grow spirits, defeat attribute monsters to acquire XP of the dominating attribute.
+Where are attribute monsters, you ask?
+Wind Attack Hunting Ground: Wind Plateau
+Earth Attack Hunting Ground: Wall of Argos
+Water Attack Hunting Ground: Garden of Eva
+Fire Attack Hunting Ground: Fore of the Gods
+And the spirits you can grow at each hunting ground vary, so keep that in mind when selecting.
+Wind Attack Hunting Ground: Obtained Fire Attack XP
+Earth Attack Hunting Ground: Obtained Wind Attack XP
+Water Attack Hunting Ground: Obtained Earth Attack XP
+Fire Attack Hunting Ground: Obtained Water Attack XP
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-14.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-14.htm
new file mode 100644
index 0000000000..97f19c85d9
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-14.htm
@@ -0,0 +1,9 @@
+Svein:
+The spirits have 4 main types of strength.
+Attribute Attack Strength: Increases damage when attacking with spirits' strength
+Attribute Defense Strength: Decrease damage received by spirits' strength.
+Attribute Critical Hit Effect: Increases critical hit effect of attribute.
+Attribute Critical Power: Increases amount of attack strength during critical hit
+Spirits' strength increases when they level up or are invested with attributes.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-15.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-15.htm
new file mode 100644
index 0000000000..47b7d9b834
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-15.htm
@@ -0,0 +1,6 @@
+Svein:
+Characteristics are skill types that raise spirits' strength. Each time a spirit levels up, it gains Characteristic Points and its strength increases when the Characteristic Points are added to each ability.
+When you evolve spirits, the highest possible level for the Characteristic increases, so evolution is essential.
+It is possible to reset at any time, so do not worry and add Characteristics however you see fit.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-16.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-16.htm
new file mode 100644
index 0000000000..3b1d5faeac
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-16.htm
@@ -0,0 +1,8 @@
+Svein:
+Each Spirit can grow up to 10 levels.
+Also, it is possible to evolve spirits that have completed growth.
+When spirits evolve, they increase strength an return to level 1, allowing them to grow them to Level 10 again.
+Don't forget that you need an Evolution Stone to evolve Spirits.
+(To evolve Spirits must reach Level 10 at 100%, so they require the ingredients for evoution from the Evolution Stone.)
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-17.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-17.htm
new file mode 100644
index 0000000000..837c4ab53d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-17.htm
@@ -0,0 +1,5 @@
+Svein:
+When hunting at the Attribute Hunting Ground, you can acquire a Spirit Rough Jewel.
+A Spirits Rough Jewel is the power of a spirit that is hardened like stone. It is possible for spirits to drain this strength and grow. If you acquire a Spirits Rough Jewel, try using it with your spirits. You can give them the Spirits Rough Jewel to the Spirits by clicking the Absorb tab in teh Manage Spirits window.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-18.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-18.htm
new file mode 100644
index 0000000000..b160e6807f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-18.htm
@@ -0,0 +1,9 @@
+Svein:
+You can extract strength from the spirits you have grown.
+The extracted spirits' strength glitters like stars and is called Attribute Fragment.
+You can extract Fire Attribute Fragment from fire spirits and Wind Attribute Fragment from wind spirits.
+You can extract Attribute Fragment by clicking the Extract button in the Manage Spirits window and paying the fee.
+It is possible to enhance various items with Attribute Fragment. If you are interested, plesse como to see me.
+(A spirit whose Attribute Fragment has been extracted returns to Level 1 of its classification, Please keep this in mind when extracting.)
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-19.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-19.htm
new file mode 100644
index 0000000000..c45e6a0f85
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053-19.htm
@@ -0,0 +1,8 @@
+Svein:
+It is possible to change attributes by clicking the Attributes button in the Character Information window.
+P. Atk. attribute is given by selected spirits.
+Do not change attributes too frequently. Spirits also need to be ready to give strength.
+(There is a delay time by schedule for Change Attribute.)
+When attacked by an attribute monster, you attribute defense will kick in, so do not worry.
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053.htm
index 6136178c44..f5fc1c50be 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053.htm
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/html/merchant/34053.htm
@@ -1,11 +1,11 @@
-Svein:
-Have you heard of Spirits?
-Honestly, there are not many people who actually know about them.
-Not all Spirits are hostile, as the common opinion goes. Moreover, there are those among them who would like to befriend a mighty warrior, like yourself.
-I can tell you more if you want.
-
-
-
-
-
+Svein:
+Adventurer, have you heard of Spirits?
+There are few who know of the spirits.
+Not all Spirits are hostile, as many believe. There are those who wish to befriend mortals. If you're interested, I can also Help you.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500000.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500000.xml
index 9acb37695a..80853ef786 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500000.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500000.xml
@@ -1,122 +1,122 @@
-
-
-
- 34053
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ 34053
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500001.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500001.xml
new file mode 100644
index 0000000000..429d8333a8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500001.xml
@@ -0,0 +1,26 @@
+
+
+
+ 34053
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500002.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500002.xml
new file mode 100644
index 0000000000..5253f5b790
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500002.xml
@@ -0,0 +1,146 @@
+
+
+
+ 34053
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500003.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500003.xml
new file mode 100644
index 0000000000..9d732322d2
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/multisell/3500003.xml
@@ -0,0 +1,139 @@
+
+
+
+ 34053
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/AttributeMaster.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/AttributeMaster.java
new file mode 100644
index 0000000000..b587098f78
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/AttributeMaster.java
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package ai.others.AttributeMaster;
+
+import java.util.Arrays;
+
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.Npc;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventDispatcher;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnElementalSpiritLearn;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritInfo;
+
+import ai.AbstractNpcAI;
+
+/**
+ * @author JoeAlisson
+ */
+public class AttributeMaster extends AbstractNpcAI
+{
+
+ private static final int SVEIN = 34053;
+
+ private AttributeMaster()
+ {
+ addStartNpc(SVEIN);
+ addTalkId(SVEIN);
+ }
+
+ @Override
+ public String onAdvEvent(String event, Npc npc, PlayerInstance player)
+ {
+ if ("learn".equalsIgnoreCase(event))
+ {
+ if ((player.getLevel() < 76) || (player.getClassId().level() < 3))
+ {
+ return "no-3rdClass.htm";
+ }
+
+ if (player.getSpirits() == null)
+ {
+ player.initElementalSpirits();
+ }
+
+ if (Arrays.stream(player.getSpirits()).allMatch(elementalSpirit -> elementalSpirit.getStage() > 0))
+ {
+ return "already.htm";
+ }
+
+ for (ElementalSpirit spirit : player.getSpirits())
+ {
+ if (spirit.getStage() == 0)
+ {
+ spirit.upgrade();
+ }
+ }
+ UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ player.sendPacket(userInfo);
+ player.sendPacket(new ElementalSpiritInfo(player, player.getActiveElementalSpiritType(), (byte) 0x01));
+ EventDispatcher.getInstance().notifyEventAsync(new OnElementalSpiritLearn(player), player);
+ return "learn.htm";
+ }
+ return null;
+ }
+
+ public static AbstractNpcAI provider()
+ {
+ return new AttributeMaster();
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/already.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/already.htm
new file mode 100644
index 0000000000..39a9d2b86f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/already.htm
@@ -0,0 +1,5 @@
+Svein:
+You Already know about spirits!
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/learn.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/learn.htm
new file mode 100644
index 0000000000..a80c1f3919
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/learn.htm
@@ -0,0 +1,7 @@
+Svein:
+You seem to be ready to accept the power spirits!
+I'll introduce the spirits to you...
+From now on you can use power of the spirits.
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/no-3rdClass.htm b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/no-3rdClass.htm
new file mode 100644
index 0000000000..10c99eaf62
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/AttributeMaster/no-3rdClass.htm
@@ -0,0 +1,7 @@
+Svein:
+You are not ready to accept the power spirits,
+I must only give spirits to those who can rule over their power.
+If not, they will be overpowered by the spirits.
+(Only 3rd Class Characters may receive the Spirits).
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/DailyMissionMasterHandler.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/DailyMissionMasterHandler.java
index d6889f46bc..8564b01a8b 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/DailyMissionMasterHandler.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/DailyMissionMasterHandler.java
@@ -30,6 +30,7 @@ import handlers.dailymissionhandlers.MonsterDailyMissionHandler;
import handlers.dailymissionhandlers.OlympiadDailyMissionHandler;
import handlers.dailymissionhandlers.QuestDailyMissionHandler;
import handlers.dailymissionhandlers.SiegeDailyMissionHandler;
+import handlers.dailymissionhandlers.SpiritDailyMissionHandler;
/**
* @author UnAfraid
@@ -50,6 +51,7 @@ public class DailyMissionMasterHandler
DailyMissionHandler.getInstance().registerHandler("boss", BossDailyMissionHandler::new);
DailyMissionHandler.getInstance().registerHandler("monster", MonsterDailyMissionHandler::new);
DailyMissionHandler.getInstance().registerHandler("fishing", FishingDailyMissionHandler::new);
+ DailyMissionHandler.getInstance().registerHandler("spirit", SpiritDailyMissionHandler::new);
LOGGER.info(DailyMissionMasterHandler.class.getSimpleName() + ": Loaded " + DailyMissionHandler.getInstance().size() + " handlers.");
}
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/EffectMasterHandler.java
index 8b9f5e4f7d..227a69590e 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -130,6 +130,8 @@ public final class EffectMasterHandler
EffectHandler.getInstance().registerHandler("DispelBySlotProbability", DispelBySlotProbability::new);
EffectHandler.getInstance().registerHandler("DoubleCast", DoubleCast::new);
EffectHandler.getInstance().registerHandler("DuelistFury", DuelistFury::new);
+ EffectHandler.getInstance().registerHandler("ElementalSpiritAttack", ElementalSpiritAttack::new);
+ EffectHandler.getInstance().registerHandler("ElementalSpiritDefense", ElementalSpiritDefense::new);
EffectHandler.getInstance().registerHandler("EnableCloak", EnableCloak::new);
EffectHandler.getInstance().registerHandler("EnergyAttack", EnergyAttack::new);
EffectHandler.getInstance().registerHandler("EnlargeAbnormalSlot", EnlargeAbnormalSlot::new);
@@ -309,6 +311,7 @@ public final class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Sow", Sow::new);
EffectHandler.getInstance().registerHandler("Speed", Speed::new);
EffectHandler.getInstance().registerHandler("SphericBarrier", SphericBarrier::new);
+ EffectHandler.getInstance().registerHandler("SpiritXpModify", SpiritExpModify::new);
EffectHandler.getInstance().registerHandler("SpModify", SpModify::new);
EffectHandler.getInstance().registerHandler("Spoil", Spoil::new);
EffectHandler.getInstance().registerHandler("StatBonusSkillCritical", StatBonusSkillCritical::new);
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/dailymissionhandlers/SpiritDailyMissionHandler.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/dailymissionhandlers/SpiritDailyMissionHandler.java
new file mode 100644
index 0000000000..001695cb7e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/dailymissionhandlers/SpiritDailyMissionHandler.java
@@ -0,0 +1,100 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.dailymissionhandlers;
+
+import java.util.function.Consumer;
+
+import org.l2jmobius.gameserver.enums.DailyMissionStatus;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.handler.AbstractDailyMissionHandler;
+import org.l2jmobius.gameserver.model.DailyMissionDataHolder;
+import org.l2jmobius.gameserver.model.DailyMissionPlayerEntry;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnElementalSpiritUpgrade;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnElementalSpiritLearn;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+
+/**
+ * @author JoeAlisson
+ */
+public class SpiritDailyMissionHandler extends AbstractDailyMissionHandler
+{
+ private final int _amount;
+ private final ElementalType _type;
+
+ public SpiritDailyMissionHandler(DailyMissionDataHolder holder)
+ {
+ super(holder);
+ _type = getHolder().getParams().getEnum("element", ElementalType.class, ElementalType.NONE);
+ _amount = holder.getRequiredCompletions();
+ }
+
+ @Override
+ public void init()
+ {
+ final MissionKind kind = getHolder().getParams().getEnum("kind", MissionKind.class, null);
+ if (MissionKind.EVOLVE == kind)
+ {
+ Containers.Players().addListener(new ConsumerEventListener(this, EventType.ON_ELEMENTAL_SPIRIT_UPGRADE, (Consumer) this::onElementalSpiritUpgrade, this));
+ }
+ else if (MissionKind.LEARN == kind)
+ {
+ Containers.Players().addListener(new ConsumerEventListener(this, EventType.ON_ELEMENTAL_SPIRIT_LEARN, (Consumer) this::onElementalSpiritLearn, this));
+ }
+ }
+
+ @Override
+ public boolean isAvailable(PlayerInstance player)
+ {
+ final DailyMissionPlayerEntry entry = getPlayerEntry(player.getObjectId(), false);
+ return (entry != null) && (entry.getStatus() == DailyMissionStatus.AVAILABLE);
+ }
+
+ private void onElementalSpiritLearn(OnElementalSpiritLearn event)
+ {
+ final DailyMissionPlayerEntry missionData = getPlayerEntry(event.getPlayer().getObjectId(), true);
+ missionData.setProgress(1);
+ missionData.setStatus(DailyMissionStatus.AVAILABLE);
+ storePlayerEntry(missionData);
+ }
+
+ private void onElementalSpiritUpgrade(OnElementalSpiritUpgrade event)
+ {
+ final ElementalSpirit spirit = event.getSpirit();
+ if (ElementalType.of(spirit.getType()) != _type)
+ {
+ return;
+ }
+
+ final DailyMissionPlayerEntry missionData = getPlayerEntry(event.getPlayer().getObjectId(), true);
+ missionData.setProgress(spirit.getStage());
+ if (missionData.getProgress() >= _amount)
+ {
+ missionData.setStatus(DailyMissionStatus.AVAILABLE);
+ }
+ storePlayerEntry(missionData);
+ }
+
+ private enum MissionKind
+ {
+ LEARN,
+ EVOLVE
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritAttack.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritAttack.java
new file mode 100644
index 0000000000..b069c26601
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritAttack.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.StatsSet;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritAttack extends AbstractStatEffect
+{
+ public ElementalSpiritAttack(StatsSet params)
+ {
+ super(params, params.getEnum("type", ElementalType.class).getAttackStat());
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritDefense.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritDefense.java
new file mode 100644
index 0000000000..4d270b97a6
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/ElementalSpiritDefense.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.StatsSet;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritDefense extends AbstractStatEffect
+{
+ public ElementalSpiritDefense(StatsSet params)
+ {
+ super(params, params.getEnum("type", ElementalType.class).getDefenseStat());
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/HealPercent.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/HealPercent.java
index 4ca447992c..289b1945c3 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/HealPercent.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/HealPercent.java
@@ -97,7 +97,7 @@ public final class HealPercent extends AbstractEffect
{
final double damage = -amount;
effected.reduceCurrentHp(damage, effector, skill, false, false, false, false);
- effector.sendDamageMessage(effected, skill, (int) damage, false, false);
+ effector.sendDamageMessage(effected, skill, (int) damage, 0, false, false);
}
}
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/Hp.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/Hp.java
index 145391fd17..1382d776db 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/Hp.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/Hp.java
@@ -102,7 +102,7 @@ public final class Hp extends AbstractEffect
{
final double damage = -amount;
effected.reduceCurrentHp(damage, effector, skill, false, false, false, false);
- effector.sendDamageMessage(effected, skill, (int) damage, false, false);
+ effector.sendDamageMessage(effected, skill, (int) damage, 0, false, false);
}
}
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/RealDamage.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/RealDamage.java
index 8b2801ee6c..1fdf1296cc 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/RealDamage.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/RealDamage.java
@@ -53,7 +53,7 @@ public class RealDamage extends AbstractEffect
effected.reduceCurrentHp(_power, effector, skill, false, false, false, false);
if (effector.isPlayer())
{
- effector.sendDamageMessage(effected, skill, (int) _power, false, false);
+ effector.sendDamageMessage(effected, skill, (int) _power, 0, false, false);
}
}
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/SpiritExpModify.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/SpiritExpModify.java
new file mode 100644
index 0000000000..29c8f7b5be
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/SpiritExpModify.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatsSet;
+import org.l2jmobius.gameserver.model.stats.Stats;
+
+/**
+ * @author JoeAlisson
+ */
+public class SpiritExpModify extends AbstractStatEffect
+{
+ public SpiritExpModify(StatsSet params)
+ {
+ super(params, Stats.ELEMENTAL_SPIRIT_BONUS_EXP);
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/spawns/Aden/Aden.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/spawns/Aden/Aden.xml
index 7f8b1bbdb1..2b13324bb0 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/spawns/Aden/Aden.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/spawns/Aden/Aden.xml
@@ -136,6 +136,7 @@
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/spawns/Giran/Giran.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/spawns/Giran/Giran.xml
index d2bea396fb..b7a0b41f76 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/spawns/Giran/Giran.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/spawns/Giran/Giran.xml
@@ -107,6 +107,7 @@
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20700-20799.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20700-20799.xml
index 7d85e85900..4e97970ff4 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20700-20799.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20700-20799.xml
@@ -3428,7 +3428,7 @@
-
+
@@ -3445,7 +3445,7 @@
BEASTMALE
-
+
@@ -3560,7 +3560,7 @@
-
+
@@ -3575,7 +3575,7 @@
HUMANOIDMALE
-
+
@@ -3609,7 +3609,7 @@
-
+
@@ -3624,7 +3624,7 @@
HUMANOIDMALE
-
+
@@ -3657,7 +3657,7 @@
-
+
@@ -3672,7 +3672,7 @@
HUMANOIDMALE
-
+
@@ -3705,7 +3705,7 @@
-
+
@@ -3726,7 +3726,7 @@
HUMANOIDMALE
-
+
@@ -3764,7 +3764,7 @@
-
+
@@ -3779,7 +3779,7 @@
GIANTMALE
-
+
@@ -3813,7 +3813,7 @@
-
+
@@ -3829,7 +3829,7 @@
ELEMENTALFEMALE
-
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20800-20899.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20800-20899.xml
index ebf73428df..afceb82f4f 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20800-20899.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20800-20899.xml
@@ -1,6 +1,6 @@
-
+
@@ -14,7 +14,7 @@
CONSTRUCTMALE
-
+
@@ -45,7 +45,7 @@
-
+
@@ -62,7 +62,7 @@
UNDEADMALE
-
+
@@ -96,7 +96,7 @@
-
+
@@ -115,7 +115,7 @@
DEMONICMALE
-
+
@@ -152,7 +152,7 @@
-
+
@@ -168,7 +168,7 @@
UNDEADMALE
-
+
@@ -3386,7 +3386,7 @@
-
+
@@ -3400,7 +3400,7 @@
ANIMALMALE
-
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20900-20999.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20900-20999.xml
index 2c5920d7ab..8c0487c362 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20900-20999.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/20900-20999.xml
@@ -5126,7 +5126,7 @@
-
+
@@ -5145,7 +5145,7 @@
UNDEADMALE
-
+
@@ -5180,7 +5180,7 @@
-
+
@@ -5194,8 +5194,10 @@
ELEMENTALMALE
+
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21600-21699.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21600-21699.xml
index 2006d82e4f..b761adde44 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21600-21699.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21600-21699.xml
@@ -3637,7 +3637,7 @@
-
+
@@ -3645,7 +3645,7 @@
HUMANOIDMALE
-
+
@@ -3679,7 +3679,7 @@
-
+
@@ -3694,7 +3694,7 @@
HUMANOIDMALE
-
+
@@ -3733,7 +3733,7 @@
-
+
@@ -3742,7 +3742,7 @@
HUMANOIDMALE
-
+
@@ -3776,14 +3776,14 @@
-
+ BUGMALE
-
+
@@ -3817,14 +3817,14 @@
-
+ BUGMALE
-
+
@@ -3858,7 +3858,7 @@
-
+
@@ -3866,7 +3866,7 @@
BUGMALE
-
+
@@ -3900,7 +3900,7 @@
-
+
@@ -3909,7 +3909,7 @@
UNDEADMALE
-
+
@@ -3943,7 +3943,7 @@
-
+
@@ -3951,7 +3951,7 @@
UNDEADMALE
-
+
@@ -3985,10 +3985,10 @@
-
+ DEMONICMALE
-
+
@@ -4013,7 +4013,7 @@
-
+
@@ -4021,7 +4021,7 @@
CONSTRUCTMALE
-
+
@@ -4055,7 +4055,7 @@
-
+
@@ -4063,7 +4063,7 @@
CONSTRUCTMALE
-
+
@@ -4097,7 +4097,7 @@
-
+
@@ -4105,7 +4105,7 @@
DEMONICMALE
-
+
@@ -4142,14 +4142,14 @@
-
+ DEMONICMALE
-
+
@@ -4186,10 +4186,10 @@
-
+ DEMONICMALE
-
+
@@ -4213,10 +4213,10 @@
-
+ DEMONICMALE
-
+
@@ -4241,10 +4241,10 @@
-
+ BEASTMALE
-
+
@@ -4287,10 +4287,10 @@
-
+ DRAGONMALE
-
+
@@ -4451,10 +4451,10 @@
-
+ DEMONICMALE
-
+
@@ -4479,10 +4479,10 @@
-
+ DRAGONMALE
-
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21700-21799.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21700-21799.xml
index 379be06446..00d794b493 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21700-21799.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21700-21799.xml
@@ -2505,10 +2505,10 @@
-
+ ELEMENTALMALE
-
+
@@ -2537,10 +2537,10 @@
-
+ ELEMENTALMALE
-
+
@@ -2570,10 +2570,10 @@
-
-
+ ELEMENTALFEMALE
+
@@ -2603,10 +2603,9 @@
-
-
+ ELEMENTAL
-
+
@@ -2635,10 +2634,9 @@
-
-
+ ETC
-
+
@@ -2667,10 +2665,9 @@
-
-
+ ELEMENTAL
-
+
@@ -2700,10 +2697,10 @@
-
-
+ ELEMENTALFEMALE
+
@@ -2732,10 +2729,10 @@
-
-
+ ELEMENTALFEMALE
+
@@ -2764,10 +2761,10 @@
-
-
+ ELEMENTALFEMALE
+
@@ -2797,7 +2794,7 @@
-
+
@@ -2812,7 +2809,7 @@
ELEMENTALMALE
-
+
@@ -2849,7 +2846,7 @@
-
+
@@ -2864,7 +2861,7 @@
ELEMENTALMALE
-
+
@@ -2901,7 +2898,7 @@
-
+
@@ -2916,7 +2913,7 @@
ELEMENTALMALE
-
+
@@ -2954,10 +2951,10 @@
-
+ ETCMALE
-
+
@@ -2980,10 +2977,10 @@
-
+ BEAST
-
+
@@ -3005,10 +3002,10 @@
-
+ DIVINE
-
+
@@ -3022,7 +3019,7 @@
-
+
@@ -3032,7 +3029,7 @@
-
+
@@ -3047,7 +3044,7 @@
DEMONICMALE
-
+
@@ -3078,7 +3075,7 @@
-
+
@@ -3093,7 +3090,7 @@
ELEMENTALMALE
-
+
@@ -3124,7 +3121,7 @@
-
+
@@ -3139,7 +3136,7 @@
ELEMENTALMALE
-
+
@@ -3170,7 +3167,7 @@
-
+
@@ -3185,7 +3182,7 @@
ELEMENTALMALE
-
+
@@ -3215,7 +3212,7 @@
-
+
@@ -3230,7 +3227,7 @@
ELEMENTALMALE
-
+
@@ -3261,7 +3258,7 @@
-
+
@@ -3276,7 +3273,7 @@
ELEMENTALMALE
-
+
@@ -3307,7 +3304,7 @@
-
+
@@ -3322,7 +3319,7 @@
ELEMENTALMALE
-
+
@@ -3353,7 +3350,7 @@
-
+
@@ -3368,7 +3365,7 @@
ELEMENTALMALE
-
+
@@ -3399,7 +3396,7 @@
-
+
@@ -3414,7 +3411,7 @@
ELEMENTALMALE
-
+
@@ -3445,7 +3442,7 @@
-
+
@@ -3460,7 +3457,7 @@
ELEMENTALMALE
-
+
@@ -3491,7 +3488,7 @@
-
+
@@ -3506,7 +3503,7 @@
ELEMENTALMALE
-
+
@@ -3537,7 +3534,7 @@
-
+
@@ -3552,7 +3549,7 @@
ELEMENTALMALE
-
+
@@ -3583,7 +3580,7 @@
-
+
@@ -3598,7 +3595,7 @@
ELEMENTALMALE
-
+
@@ -3630,7 +3627,7 @@
-
+
@@ -3645,7 +3642,7 @@
ELEMENTALMALE
-
+
@@ -3676,7 +3673,7 @@
-
+
@@ -3691,7 +3688,7 @@
ELEMENTALMALE
-
+
@@ -3722,7 +3719,7 @@
-
+
@@ -3737,7 +3734,7 @@
ELEMENTALMALE
-
+
@@ -3769,7 +3766,7 @@
-
+
@@ -3784,7 +3781,7 @@
HUMANOIDMALE
-
+
@@ -3815,7 +3812,7 @@
-
+
@@ -3830,7 +3827,7 @@
UNDEADMALE
-
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21800-21899.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21800-21899.xml
index cce3fabc25..648f5770e5 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21800-21899.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/npcs/21800-21899.xml
@@ -820,7 +820,7 @@
-
+
@@ -835,7 +835,7 @@
ANIMALMALE
-
+
@@ -868,7 +868,7 @@
-
+
@@ -886,7 +886,7 @@
ANIMALMALE
-
+
@@ -921,7 +921,7 @@
-
+
@@ -937,7 +937,7 @@
BEASTMALE
-
+
@@ -970,7 +970,7 @@
-
+
@@ -988,7 +988,7 @@
BEASTMALE
-
+
@@ -1023,7 +1023,7 @@
-
+
@@ -1038,7 +1038,7 @@
CONSTRUCTMALE
-
+
@@ -1071,8 +1071,7 @@
-
-
+
@@ -1089,7 +1088,7 @@
BEASTMALE
-
+
@@ -1124,8 +1123,7 @@
-
-
+
@@ -1145,7 +1143,7 @@
CONSTRUCTMALE
-
+
@@ -1184,8 +1182,7 @@
-
-
+
@@ -1206,7 +1203,7 @@
CONSTRUCTMALE
-
+
@@ -1246,8 +1243,7 @@
-
-
+
@@ -1266,7 +1262,7 @@
CONSTRUCTMALE
-
+
@@ -1305,7 +1301,7 @@
-
+
@@ -1322,7 +1318,7 @@
CONSTRUCTMALE
-
+
@@ -1356,7 +1352,7 @@
-
+
@@ -1377,7 +1373,7 @@
ANIMALMALE
-
+
@@ -1415,8 +1411,7 @@
-
-
+
@@ -1435,7 +1430,7 @@
CONSTRUCTMALE
-
+
@@ -1474,8 +1469,7 @@
-
-
+
@@ -1492,7 +1486,7 @@
CONSTRUCTMALE
-
+
@@ -1529,8 +1523,7 @@
-
-
+
@@ -1549,7 +1542,7 @@
CONSTRUCTMALE
-
+
@@ -1588,8 +1581,7 @@
-
-
+
@@ -1605,7 +1597,7 @@
BEASTMALE
-
+
@@ -1640,8 +1632,7 @@
-
-
+
@@ -1657,7 +1648,7 @@
DIVINEFEMALE
-
+
@@ -1692,8 +1683,7 @@
-
-
+
@@ -1711,7 +1701,7 @@
DIVINEFEMALE
-
+
@@ -1748,8 +1738,7 @@
-
-
+
@@ -1765,7 +1754,7 @@
DIVINEFEMALE
-
+
@@ -1800,8 +1789,7 @@
-
-
+
@@ -1816,7 +1804,7 @@
DIVINEMALE
-
+
@@ -1852,11 +1840,11 @@
-
-
+ DIVINEFEMALE
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/51000-51099.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/51000-51099.xml
index da6a3e8187..dbb362d52b 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/51000-51099.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/51000-51099.xml
@@ -728,21 +728,69 @@
icon.agathion_fire_1P
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 100
+ FIRE
+
+ icon.agathion_water_1P
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 100
+ WATER
+
+ icon.agathion_wind_1P
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 100
+ WIND
+
+ icon.agathion_earth_1P
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 100
+ EARTH
+
+ icon.ev_charge_scroll
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/51100-51199.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/51100-51199.xml
index 77b55d87d2..ea2d1d582f 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/51100-51199.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/51100-51199.xml
@@ -8,26 +8,70 @@
icon.etc_summon_aga_agit_i00
- A13000
+ 2
+ 85
+ A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 13568
+
+ icon.etc_summon_aga_agit_i00
- A13000
+ 2
+ 85
+ A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 13572
+
+ icon.etc_summon_aga_agit_i00
- A13000
+ 2
+ 85
+ A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 13576
+
+ icon.etc_summon_aga_agit_i00
- A13000
+ 2
+ 85
+ A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 13580
+
+
@@ -161,18 +205,54 @@
icon.etc_potion_blue_i00A1
+ true
+ 2
+ 1
+ 0
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 100
+ DIFF
+
+ icon.elemental_bless_scrl_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 30
+ PER
+
+ icon.elemental_bless_scrl_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ PER
+
+ icon.ev_charge_scroll
@@ -185,30 +265,74 @@
icon.etc_fire_potion_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 160000
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ FIRE
+
+ icon.etc_water_potion_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 160000
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ WATER
+
+ icon.etc_wind_potion_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 160000
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ WIND
+
+ icon.etc_earth_potion_i00
- A1
- 4
+ A2
+ 1
+ 1200
+ 160000
+ true
+ SELF
+ SINGLE
+
+
+ 50
+ EARTH
+
+ A1
@@ -356,7 +480,20 @@
icon.etc_potion_blue_i00
+ true
+ 2
+ 1A1
+ 5
+ 0
+ SELF
+ SINGLE
+
+
+ 300
+ DIFF
+
+ A1
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/54000-54099.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/54000-54099.xml
index 3458b88cfb..05a0f1a832 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/54000-54099.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/54000-54099.xml
@@ -153,33 +153,108 @@
icon.elemental_necklace_water_i00P
+ 1
+
+
+
+ 20
+ 40
+ 60
+ 80
+ 100
+
+ WATER
+
+ icon.elemental_necklace_fire_i00P
+ 1
+
+
+
+ 20
+ 40
+ 60
+ 80
+ 100
+
+ FIRE
+
+ icon.elemental_necklace_wind_i00P
+ 1
+
+
+
+ 20
+ 40
+ 60
+ 80
+ 100
+
+ WIND
+
+ icon.elemental_necklace_earth_i00P
+ 1
+
+
+
+ 20
+ 40
+ 60
+ 80
+ 100
+
+ EARTH
+
+ icon.skill_transform_s_attackP
+ 1
+
+
+
+ 3
+ 6
+ 10
+ 15
+ 30
+
+ PER
+
+ icon.elemental_bless_scrl_i00
- A1
- 4
- 1
+ A2
+ 1
+ 1200
+ 1
+ true
+ SELF
+ SINGLE
+
+
+ 20
+ PER
+
+
@@ -195,21 +270,153 @@
icon.elemental_necklace_fire_i00P
+
+
+
+ 50
+ 50
+ 100
+ 100
+ 150
+ 150
+ 200
+ 200
+ 300
+ 300
+ 500
+
+
+
+
+ 0
+ 1
+ 1
+ 2
+ 2
+ 3
+ 3
+ 5
+ 7
+ 10
+ 15
+
+ PER
+
+ icon.elemental_necklace_water_i00P
+
+
+
+ 50
+ 50
+ 100
+ 100
+ 150
+ 150
+ 200
+ 200
+ 300
+ 300
+ 500
+
+
+
+
+ 0
+ 1
+ 1
+ 2
+ 2
+ 3
+ 3
+ 5
+ 7
+ 10
+ 15
+
+ PER
+
+ icon.elemental_necklace_wind_i00P
+
+
+
+ 50
+ 50
+ 100
+ 100
+ 150
+ 150
+ 200
+ 200
+ 300
+ 300
+ 500
+
+
+
+
+ 0
+ 1
+ 1
+ 2
+ 2
+ 3
+ 3
+ 5
+ 7
+ 10
+ 15
+
+ PER
+
+ icon.elemental_necklace_earth_i00P
+
+
+
+ 50
+ 50
+ 100
+ 100
+ 150
+ 150
+ 200
+ 200
+ 300
+ 300
+ 500
+
+
+
+
+ 0
+ 1
+ 1
+ 2
+ 2
+ 3
+ 3
+ 5
+ 7
+ 10
+ 15
+
+ PER
+
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/documentation.txt b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/documentation.txt
index f74cc44fc1..adf6534f54 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/documentation.txt
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/documentation.txt
@@ -100,6 +100,8 @@ DispelBySlotMyself: Removes given amount of effects by specified AbnormalType
DispelBySlotProbability: Removes given amount of effects by specified AbnormalType at a given rate.
DoubleCast: Triggers Fire, Water, Wind, Earth stance and enables the ability to cast two skills at once.
DuelistFury: Synergy effect for Faceoff effect. (l2jmobius)
+ElementalSpiritAttack: Elemental spirit attack stat effect. (JoeAlisson)
+ElementalSpiritDefense: Elemental spirit defense stat effect. (JoeAlisson)
EnableCloak: See/unsee cloaks.
EnemyCharge: Charges towards the enemy. Rush Impact.
EnergyAttack: Physical attack based on Momentum formula. Triple Sonic Slash, Double Sonic Slash etc.
@@ -278,6 +280,7 @@ SoulEating: Absorbs souls when taking exp from mobs and sets max soul count.
Sow: Planting a seed into NPC target. Manor stuff.
Speed: Speed stat.
SphericBarrier: Blocks damage and buff/debuff incoming from outside the specified range.
+SpiritExpModify: Spirit EXP modify stat effect. (JoeAlisson)
SpModify: Bonus SP stat.
Spoil: Spoils a mob activating its extra sweep drop.
StatBonusSkillCritical: Changes skill critical rate to depend on the specified base stat.
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/ElementalSpiritData.xsd b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/ElementalSpiritData.xsd
new file mode 100644
index 0000000000..d301984741
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/ElementalSpiritData.xsd
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/npcs.xsd b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/npcs.xsd
index 87d6e604e0..05803d592d 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/npcs.xsd
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/npcs.xsd
@@ -66,6 +66,7 @@
+
@@ -302,6 +303,7 @@
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/commons/util/CommonUtil.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/commons/util/CommonUtil.java
index 1c00dfe98a..c4a69288c2 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/commons/util/CommonUtil.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/commons/util/CommonUtil.java
@@ -16,6 +16,9 @@
*/
package org.l2jmobius.commons.util;
+import static java.util.Objects.isNull;
+import static java.util.Objects.nonNull;
+
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
@@ -27,11 +30,14 @@ import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.StringJoiner;
import java.util.StringTokenizer;
+import java.util.function.Predicate;
+import java.util.function.ToIntFunction;
import org.l2jmobius.Config;
@@ -587,4 +593,29 @@ public final class CommonUtil
final DecimalFormat formatter = new DecimalFormat(format, new DecimalFormatSymbols(Locale.ENGLISH));
return formatter.format(val);
}
+
+ public static boolean isNullOrEmpty(final CharSequence value)
+ {
+ return isNull(value) || (value.length() == 0);
+ }
+
+ public static boolean isNotEmpty(final String value)
+ {
+ return nonNull(value) && !value.isEmpty();
+ }
+
+ public static boolean isNullOrEmpty(final Collection> collection)
+ {
+ return isNull(collection) || collection.isEmpty();
+ }
+
+ public static int zeroIfNullOrElse(T obj, ToIntFunction action)
+ {
+ return isNull(obj) ? 0 : action.applyAsInt(obj);
+ }
+
+ public static boolean falseIfNullOrElse(T obj, Predicate predicate)
+ {
+ return nonNull(obj) && predicate.test(obj);
+ }
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/GameServer.java
index 4b6f559189..2a93156d12 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/GameServer.java
@@ -55,6 +55,7 @@ import org.l2jmobius.gameserver.data.xml.impl.CombinationItemsData;
import org.l2jmobius.gameserver.data.xml.impl.CubicData;
import org.l2jmobius.gameserver.data.xml.impl.DailyMissionData;
import org.l2jmobius.gameserver.data.xml.impl.DoorData;
+import org.l2jmobius.gameserver.data.xml.impl.ElementalSpiritData;
import org.l2jmobius.gameserver.data.xml.impl.EnchantItemData;
import org.l2jmobius.gameserver.data.xml.impl.EnchantItemGroupsData;
import org.l2jmobius.gameserver.data.xml.impl.EnchantItemHPBonusData;
@@ -240,6 +241,7 @@ public class GameServer
ClanRewardData.getInstance();
DailyMissionHandler.getInstance().executeScript();
DailyMissionData.getInstance();
+ ElementalSpiritData.getInstance();
printSection("Skills");
SkillConditionHandler.getInstance().executeScript();
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/impl/ElementalSpiritData.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/impl/ElementalSpiritData.java
new file mode 100644
index 0000000000..1be9c187e0
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/impl/ElementalSpiritData.java
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml.impl;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritTemplateHolder;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(ElementalSpiritData.class.getName());
+
+ public static final long EXTRACT_FEE = 1000000;
+ public static final float FRAGMENT_XP_CONSUME = 50000.0f;
+ public static final int TALENT_INIT_FEE = 50000;
+
+ private static final Map> SPIRIT_DATA = new HashMap<>(4);
+
+ protected ElementalSpiritData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ parseDatapackFile("data/ElementalSpiritData.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + SPIRIT_DATA.size() + " elemental spirit templates.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ forEach(doc, "list", list -> forEach(list, "spirit", this::parseSpirit));
+ }
+
+ private void parseSpirit(Node spiritNode)
+ {
+ final NamedNodeMap attributes = spiritNode.getAttributes();
+ final byte type = parseByte(attributes, "type");
+ final byte stage = parseByte(attributes, "stage");
+ final int npcId = parseInteger(attributes, "npcId");
+ final int extractItem = parseInteger(attributes, "extractItem");
+ final int maxCharacteristics = parseInteger(attributes, "maxCharacteristics");
+ ElementalSpiritTemplateHolder template = new ElementalSpiritTemplateHolder(type, stage, npcId, extractItem, maxCharacteristics);
+ SPIRIT_DATA.computeIfAbsent(type, HashMap::new).put(stage, template);
+
+ forEach(spiritNode, "level", levelNode ->
+ {
+ final NamedNodeMap levelInfo = levelNode.getAttributes();
+ final int level = parseInteger(levelInfo, "id");
+ final int attack = parseInteger(levelInfo, "atk");
+ final int defense = parseInteger(levelInfo, "def");
+ final int criticalRate = parseInteger(levelInfo, "critRate");
+ final int criticalDamage = parseInteger(levelInfo, "critDam");
+ final long maxExperience = parseLong(levelInfo, "maxExp");
+ template.addLevelInfo(level, attack, defense, criticalRate, criticalDamage, maxExperience);
+ });
+
+ forEach(spiritNode, "itemToEvolve", itemNode ->
+ {
+ final NamedNodeMap itemInfo = itemNode.getAttributes();
+ final int itemId = parseInteger(itemInfo, "id");
+ final int count = parseInteger(itemInfo, "count", 1);
+ template.addItemToEvolve(itemId, count);
+ });
+
+ forEach(spiritNode, "absorbItem", absorbItemNode ->
+ {
+ final NamedNodeMap absorbInfo = absorbItemNode.getAttributes();
+ final int itemId = parseInteger(absorbInfo, "id");
+ final int experience = parseInteger(absorbInfo, "experience");
+ template.addAbsorbItem(itemId, experience);
+ });
+ }
+
+ public ElementalSpiritTemplateHolder getSpirit(byte type, byte stage)
+ {
+ if (SPIRIT_DATA.containsKey(type))
+ {
+ return SPIRIT_DATA.get(type).get(stage);
+ }
+ return null;
+ }
+
+ public static ElementalSpiritData getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ static final ElementalSpiritData INSTANCE = new ElementalSpiritData();
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/impl/NpcData.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/impl/NpcData.java
index da219ac6ce..28cecaacbe 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/impl/NpcData.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/impl/NpcData.java
@@ -42,6 +42,7 @@ import org.l2jmobius.commons.util.IXmlReader;
import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.AISkillScope;
import org.l2jmobius.gameserver.enums.DropType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.MpRewardAffectType;
import org.l2jmobius.gameserver.enums.MpRewardType;
import org.l2jmobius.gameserver.model.StatsSet;
@@ -110,6 +111,7 @@ public class NpcData implements IXmlReader
set.set("usingServerSideName", parseBoolean(attrs, "usingServerSideName"));
set.set("title", parseString(attrs, "title"));
set.set("usingServerSideTitle", parseBoolean(attrs, "usingServerSideTitle"));
+ set.set("elementalType", parseEnum(attrs, ElementalType.class, "element"));
for (Node npcNode = listNode.getFirstChild(); npcNode != null; npcNode = npcNode.getNextSibling())
{
attrs = npcNode.getAttributes();
@@ -143,6 +145,7 @@ public class NpcData implements IXmlReader
set.set("exp", parseDouble(attrs, "exp"));
set.set("sp", parseDouble(attrs, "sp"));
set.set("raidPoints", parseDouble(attrs, "raidPoints"));
+ set.set("attribute_exp", parseLong(attrs, "attribute_exp"));
break;
}
case "mpreward":
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/enums/ElementalType.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/enums/ElementalType.java
new file mode 100644
index 0000000000..86643c048a
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/enums/ElementalType.java
@@ -0,0 +1,127 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.enums;
+
+import org.l2jmobius.gameserver.model.stats.Stats;
+
+/**
+ * @author JoeAlisson
+ */
+public enum ElementalType
+{
+ NONE,
+ FIRE,
+ WATER,
+ WIND,
+ EARTH;
+
+ public byte getId()
+ {
+ return (byte) (ordinal());
+ }
+
+ public static ElementalType of(byte elementId)
+ {
+ return values()[elementId];
+ }
+
+ public ElementalType getDominating()
+ {
+ return dominating(this);
+ }
+
+ public ElementalType dominating(ElementalType elementalType)
+ {
+ switch (elementalType)
+ {
+ case FIRE:
+ {
+ return WATER;
+ }
+ case WATER:
+ {
+ return EARTH;
+ }
+ case WIND:
+ {
+ return FIRE;
+ }
+ case EARTH:
+ {
+ return WIND;
+ }
+ default:
+ {
+ return NONE;
+ }
+ }
+ }
+
+ public Stats getAttackStat()
+ {
+ switch (this)
+ {
+ case EARTH:
+ {
+ return Stats.ELEMENTAL_SPIRIT_EARTH_ATTACK;
+ }
+ case WIND:
+ {
+ return Stats.ELEMENTAL_SPIRIT_WIND_ATTACK;
+ }
+ case FIRE:
+ {
+ return Stats.ELEMENTAL_SPIRIT_FIRE_ATTACK;
+ }
+ case WATER:
+ {
+ return Stats.ELEMENTAL_SPIRIT_WATER_ATTACK;
+ }
+ default:
+ {
+ return null;
+ }
+ }
+ }
+
+ public Stats getDefenseStat()
+ {
+ switch (this)
+ {
+ case EARTH:
+ {
+ return Stats.ELEMENTAL_SPIRIT_EARTH_DEFENSE;
+ }
+ case WIND:
+ {
+ return Stats.ELEMENTAL_SPIRIT_WIND_DEFENSE;
+ }
+ case FIRE:
+ {
+ return Stats.ELEMENTAL_SPIRIT_FIRE_DEFENSE;
+ }
+ case WATER:
+ {
+ return Stats.ELEMENTAL_SPIRIT_WATER_DEFENSE;
+ }
+ default:
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/ElementalSpiritInstanceManager.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/ElementalSpiritInstanceManager.java
new file mode 100644
index 0000000000..f58c587de8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/ElementalSpiritInstanceManager.java
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.instancemanager;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.l2jmobius.commons.database.DatabaseFactory;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder;
+
+/**
+ * @author Mobius
+ */
+public class ElementalSpiritInstanceManager
+{
+ private static final String LOAD_QUERY = "SELECT * FROM character_spirits WHERE charId=?";
+ private static final String STORE_QUERY = "REPLACE INTO character_spirits (charId, type, level, stage, experience, attack_points, defense_points, crit_rate_points, crit_damage_points, in_use) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+ public List findByPlayerId(int playerId)
+ {
+ final List result = new ArrayList<>();
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement stmt = con.prepareStatement(LOAD_QUERY))
+ {
+ stmt.setInt(1, playerId);
+ try (ResultSet rset = stmt.executeQuery())
+ {
+ while (rset.next())
+ {
+ final ElementalSpiritDataHolder newHolder = new ElementalSpiritDataHolder();
+ newHolder.setCharId(rset.getInt("charId"));
+ newHolder.setType(rset.getByte("type"));
+ newHolder.setLevel(rset.getByte("level"));
+ newHolder.setStage(rset.getByte("stage"));
+ newHolder.setExperience(rset.getLong("experience"));
+ newHolder.setAttackPoints(rset.getByte("attack_points"));
+ newHolder.setDefensePoints(rset.getByte("defense_points"));
+ newHolder.setCritRatePoints(rset.getByte("crit_rate_points"));
+ newHolder.setCritDamagePoints(rset.getByte("crit_damage_points"));
+ newHolder.setInUse(rset.getByte("in_use") == 1);
+ result.add(newHolder);
+ }
+ }
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ public void save(ElementalSpiritDataHolder data)
+ {
+ if (data == null)
+ {
+ return;
+ }
+
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement statement = con.prepareStatement(STORE_QUERY))
+ {
+ statement.setInt(1, data.getCharId());
+ statement.setInt(2, data.getType());
+ statement.setInt(3, data.getLevel());
+ statement.setInt(4, data.getStage());
+ statement.setLong(5, data.getExperience());
+ statement.setInt(6, data.getAttackPoints());
+ statement.setInt(7, data.getDefensePoints());
+ statement.setInt(8, data.getCritRatePoints());
+ statement.setInt(9, data.getCritDamagePoints());
+ statement.setInt(10, data.isInUse() ? 1 : 0);
+ statement.execute();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public static ElementalSpiritInstanceManager getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final ElementalSpiritInstanceManager INSTANCE = new ElementalSpiritInstanceManager();
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/ElementalSpirit.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/ElementalSpirit.java
new file mode 100644
index 0000000000..15e07f0a57
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/ElementalSpirit.java
@@ -0,0 +1,275 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model;
+
+import static java.lang.Math.max;
+
+import java.util.List;
+
+import org.l2jmobius.gameserver.data.xml.impl.ElementalSpiritData;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.instancemanager.ElementalSpiritInstanceManager;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventDispatcher;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnElementalSpiritUpgrade;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritAbsorbItemHolder;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritTemplateHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ExElementalSpiritGetExp;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpirit
+{
+ private final PlayerInstance _owner;
+ private ElementalSpiritTemplateHolder _template;
+ private final ElementalSpiritDataHolder _data;
+
+ public ElementalSpirit(ElementalType type, PlayerInstance owner)
+ {
+ _data = new ElementalSpiritDataHolder(type.getId(), owner.getObjectId());
+ _template = ElementalSpiritData.getInstance().getSpirit(type.getId(), _data.getStage());
+ _owner = owner;
+ }
+
+ public ElementalSpirit(ElementalSpiritDataHolder data, PlayerInstance owner)
+ {
+ _owner = owner;
+ _data = data;
+ _template = ElementalSpiritData.getInstance().getSpirit(data.getType(), data.getStage());
+ }
+
+ public void addExperience(long experience)
+ {
+ _data.addExperience(experience);
+ _owner.sendPacket(new SystemMessage(SystemMessageId.OBTAINED_S2_ATTRIBUTE_XP_OF_S1).addInt((int) experience).addElementalSpirit(getType()));
+ if (_data.getExperience() > getExperienceToNextLevel())
+ {
+ levelUp();
+ _owner.sendPacket(new SystemMessage(SystemMessageId.S1_ATTRIBUTE_SPIRIT_BECAME_LEVEL_S2).addElementalSpirit(getType()).addByte(_data.getLevel()));
+ _owner.sendPacket(new ElementalSpiritInfo(_owner, _owner.getActiveElementalSpiritType(), (byte) 0));
+ final UserInfo userInfo = new UserInfo(_owner);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ _owner.sendPacket(userInfo);
+
+ }
+ _owner.sendPacket(new ExElementalSpiritGetExp(getType(), _data.getExperience()));
+ }
+
+ private void levelUp()
+ {
+ do
+ {
+ if (_data.getLevel() < getMaxLevel())
+ {
+ _data.increaseLevel();
+ }
+ else
+ {
+ _data.setExperience(getExperienceToNextLevel());
+ }
+ }
+ while (_data.getExperience() > getExperienceToNextLevel());
+ }
+
+ public int getAvailableCharacteristicsPoints()
+ {
+ final int stage = _data.getStage();
+ final int level = _data.getLevel();
+ final int points = ((stage - 1) * 11) + (stage > 2 ? (level - 1) * 2 : level - 1);
+ return max(points - _data.getAttackPoints() - _data.getDefensePoints() - _data.getCritDamagePoints() - _data.getCritRatePoints(), 0);
+ }
+
+ public ElementalSpiritAbsorbItemHolder getAbsorbItem(int itemId)
+ {
+ for (ElementalSpiritAbsorbItemHolder absorbItem : getAbsorbItems())
+ {
+ if (absorbItem.getId() == itemId)
+ {
+ return absorbItem;
+ }
+ }
+ return null;
+ }
+
+ public int getExtractAmount()
+ {
+ return Math.round(_data.getExperience() / ElementalSpiritData.FRAGMENT_XP_CONSUME);
+ }
+
+ public void resetStage()
+ {
+ _data.setLevel((byte) 1);
+ _data.setExperience(0);
+ resetCharacteristics();
+ }
+
+ public boolean canEvolve()
+ {
+ return (getStage() < 3) && (getLevel() == 10) && (getExperience() == getExperienceToNextLevel());
+ }
+
+ public void upgrade()
+ {
+ _data.increaseStage();
+ _data.setLevel((byte) 1);
+ _data.setExperience(0);
+ _template = ElementalSpiritData.getInstance().getSpirit(_data.getType(), _data.getStage());
+ EventDispatcher.getInstance().notifyEventAsync(new OnElementalSpiritUpgrade(_owner, this), _owner);
+
+ }
+
+ public void resetCharacteristics()
+ {
+ _data.setAttackPoints((byte) 0);
+ _data.setDefensePoints((byte) 0);
+ _data.setCritRatePoints((byte) 0);
+ _data.setCritDamagePoints((byte) 0);
+ }
+
+ public byte getType()
+ {
+ return _template.getType();
+ }
+
+ public byte getStage()
+ {
+ return _template.getStage();
+ }
+
+ public int getNpcId()
+ {
+ return _template.getNpcId();
+ }
+
+ public long getExperience()
+ {
+ return _data.getExperience();
+ }
+
+ public long getExperienceToNextLevel()
+ {
+ return _template.getMaxExperienceAtLevel(_data.getLevel());
+ }
+
+ public byte getLevel()
+ {
+ return _data.getLevel();
+ }
+
+ public int getMaxLevel()
+ {
+ return _template.getMaxLevel();
+ }
+
+ public int getAttack()
+ {
+ return _template.getAttackAtLevel(_data.getLevel()) + (_data.getAttackPoints() * 5);
+ }
+
+ public int getDefense()
+ {
+ return _template.getDefenseAtLevel(_data.getLevel()) + (_data.getDefensePoints() * 5);
+ }
+
+ public int getMaxCharacteristics()
+ {
+ return _template.getMaxCharacteristics();
+ }
+
+ public int getAttackPoints()
+ {
+ return _data.getAttackPoints();
+ }
+
+ public int getDefensePoints()
+ {
+ return _data.getDefensePoints();
+ }
+
+ public int getCriticalRatePoints()
+ {
+ return _data.getCritRatePoints();
+ }
+
+ public int getCriticalDamagePoints()
+ {
+ return _data.getCritDamagePoints();
+ }
+
+ public List getItemsToEvolve()
+ {
+ return _template.getItemsToEvolve();
+ }
+
+ public List getAbsorbItems()
+ {
+ return _template.getAbsorbItems();
+ }
+
+ public int getExtractItem()
+ {
+ return _template.getExtractItem();
+ }
+
+ public void save()
+ {
+ ElementalSpiritInstanceManager.getInstance().save(_data);
+ }
+
+ public void addAttackPoints(byte attackPoints)
+ {
+ _data.addAttackPoints(attackPoints);
+ }
+
+ public void addDefensePoints(byte defensePoints)
+ {
+ _data.addDefensePoints(defensePoints);
+ }
+
+ public void addCritRatePoints(byte critRatePoints)
+ {
+ _data.addCritRatePoints(critRatePoints);
+ }
+
+ public void addCritDamage(byte critDamagePoints)
+ {
+ _data.addCritDamagePoints(critDamagePoints);
+ }
+
+ public int getCriticalRate()
+ {
+ return _template.getCriticalRateAtLevel(_data.getLevel()) + getCriticalRatePoints();
+ }
+
+ public int getCriticalDamage()
+ {
+ return _template.getCriticalDamageAtLevel(_data.getLevel()) + getCriticalRatePoints();
+ }
+
+ public void setInUse(boolean value)
+ {
+ _data.setInUse(value);
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index c8e3c18d06..f0469106c7 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -42,6 +42,7 @@ import org.l2jmobius.gameserver.datatables.EventDroplist.DateDrop;
import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.DropType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.InstanceType;
import org.l2jmobius.gameserver.enums.Team;
import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
@@ -50,6 +51,7 @@ import org.l2jmobius.gameserver.instancemanager.WalkingManager;
import org.l2jmobius.gameserver.model.AggroInfo;
import org.l2jmobius.gameserver.model.CommandChannel;
import org.l2jmobius.gameserver.model.DamageDoneInfo;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
import org.l2jmobius.gameserver.model.Party;
import org.l2jmobius.gameserver.model.Seed;
import org.l2jmobius.gameserver.model.WorldObject;
@@ -519,6 +521,8 @@ public class Attackable extends Npc
attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), exp, _isRaid), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(attacker, exp);
}
+
+ rewardAttributeExp(attacker, damage, totalDamage);
}
}
}
@@ -616,6 +620,11 @@ public class Attackable extends Npc
if (partyDmg > 0)
{
attackerParty.distributeXpAndSp(exp, sp, rewardedMembers, partyLvl, partyDmg, this);
+
+ for (PlayerInstance rewardedMember : rewardedMembers)
+ {
+ rewardAttributeExp(rewardedMember, damage, totalDamage);
+ }
}
}
}
@@ -627,6 +636,19 @@ public class Attackable extends Npc
}
}
+ private void rewardAttributeExp(PlayerInstance player, long damage, long totalDamage)
+ {
+ if ((player.getActiveElementalSpiritType() > 0) && (getAttributeExp() > 0) && (getElementalSpiritType() != ElementalType.NONE))
+ {
+ final long attributeExp = (long) (((getAttributeExp() * damage) / totalDamage) * player.getElementalSpiritXpBonus());
+ final ElementalSpirit spirit = player.getElementalSpirit(getElementalSpiritType().getDominating());
+ if (spirit != null)
+ {
+ spirit.addExperience(attributeExp);
+ }
+ }
+ }
+
@Override
public void addAttackerToAttackByList(Creature creature)
{
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Creature.java
index 1d4237d89a..3144dc44d3 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Creature.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Creature.java
@@ -54,6 +54,7 @@ import org.l2jmobius.gameserver.data.xml.impl.TransformData;
import org.l2jmobius.gameserver.enums.AttributeType;
import org.l2jmobius.gameserver.enums.BasicProperty;
import org.l2jmobius.gameserver.enums.CategoryType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.InstanceType;
import org.l2jmobius.gameserver.enums.ItemSkillType;
import org.l2jmobius.gameserver.enums.Race;
@@ -2691,6 +2692,18 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
info.addComponentType(UserInfoType.ATK_ELEMENTAL);
break;
}
+ case ELEMENTAL_SPIRIT_EARTH_ATTACK:
+ case ELEMENTAL_SPIRIT_EARTH_DEFENSE:
+ case ELEMENTAL_SPIRIT_FIRE_ATTACK:
+ case ELEMENTAL_SPIRIT_FIRE_DEFENSE:
+ case ELEMENTAL_SPIRIT_WATER_ATTACK:
+ case ELEMENTAL_SPIRIT_WATER_DEFENSE:
+ case ELEMENTAL_SPIRIT_WIND_ATTACK:
+ case ELEMENTAL_SPIRIT_WIND_DEFENSE:
+ {
+ info.addComponentType(UserInfoType.ATT_SPIRITS);
+ break;
+ }
}
}
}
@@ -4506,11 +4519,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
}
}
- final double damageCap = _stat.getValue(Stats.DAMAGE_LIMIT);
- if (damageCap > 0)
- {
- value = Math.min(value, damageCap);
- }
+ double elementalDamage = 0;
// Calculate PvP/PvE damage received. It is a post-attack stat.
if (attacker != null)
@@ -4523,6 +4532,15 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
{
value *= (100 + _stat.getValue(Stats.PVE_DAMAGE_TAKEN)) / 100;
}
+
+ elementalDamage = Formulas.calcSpiritElementalDamage(attacker, this);
+ value += elementalDamage;
+ }
+
+ final double damageCap = _stat.getValue(Stats.DAMAGE_LIMIT);
+ if (damageCap > 0)
+ {
+ value = Math.min(value, damageCap);
}
if (Config.CHAMPION_ENABLE && isChampion() && (Config.CHAMPION_HP != 0))
@@ -4540,7 +4558,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
if (attacker != null)
{
- attacker.sendDamageMessage(this, skill, (int) value, critical, false);
+ attacker.sendDamageMessage(this, skill, (int) value, elementalDamage, critical, false);
}
}
@@ -4671,10 +4689,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
* @param target
* @param skill
* @param damage
+ * @param elementalDamage
* @param crit
* @param miss
*/
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
}
@@ -5472,4 +5491,14 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe
_buffFinishTask = null;
}
}
+
+ public double getElementalSpiritDefenseOf(ElementalType type)
+ {
+ return getElementalSpiritType() == type ? 100 : 0;
+ }
+
+ public ElementalType getElementalSpiritType()
+ {
+ return ElementalType.NONE;
+ }
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Npc.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Npc.java
index c50ed91d05..b3cf15fe5c 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Npc.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Npc.java
@@ -29,6 +29,7 @@ import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.AISkillScope;
import org.l2jmobius.gameserver.enums.AIType;
import org.l2jmobius.gameserver.enums.ChatType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.InstanceType;
import org.l2jmobius.gameserver.enums.MpRewardAffectType;
import org.l2jmobius.gameserver.enums.PrivateStoreType;
@@ -868,6 +869,17 @@ public class Npc extends Creature
return getTemplate().getSP() * rateMul;
}
+ public long getAttributeExp()
+ {
+ return getTemplate().getAttributeExp();
+ }
+
+ @Override
+ public ElementalType getElementalSpiritType()
+ {
+ return getTemplate().getElementalType();
+ }
+
/**
* Kill the NpcInstance (the corpse disappeared after 7 seconds).
* Actions:
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Summon.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Summon.java
index 71d6606772..a614eec679 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Summon.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/Summon.java
@@ -734,7 +734,7 @@ public abstract class Summon extends Playable
}
@Override
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
if (miss || (_owner == null))
{
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/DoppelgangerInstance.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/DoppelgangerInstance.java
index a41fd1e41d..cedf3a08f3 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/DoppelgangerInstance.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/DoppelgangerInstance.java
@@ -124,11 +124,11 @@ public class DoppelgangerInstance extends Npc
public void doAttack(double damage, Creature target, Skill skill, boolean isDOT, boolean directlyToHp, boolean critical, boolean reflect)
{
super.doAttack(damage, target, skill, isDOT, directlyToHp, critical, reflect);
- sendDamageMessage(target, skill, (int) damage, critical, false);
+ sendDamageMessage(target, skill, (int) damage, 0, critical, false);
}
@Override
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
if (miss || (getSummoner() == null) || !getSummoner().isPlayer())
{
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index 9372c85feb..34c58b29b1 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -47,6 +47,7 @@ import java.util.stream.Collectors;
import org.l2jmobius.Config;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.commons.database.DatabaseFactory;
+import org.l2jmobius.commons.util.CommonUtil;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.GameTimeController;
import org.l2jmobius.gameserver.ItemsAutoDestroy;
@@ -83,6 +84,7 @@ import org.l2jmobius.gameserver.enums.CastleSide;
import org.l2jmobius.gameserver.enums.CategoryType;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.ClanWarState;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.GroupType;
import org.l2jmobius.gameserver.enums.HtmlActionScope;
import org.l2jmobius.gameserver.enums.IllegalActionPunishmentType;
@@ -108,6 +110,7 @@ import org.l2jmobius.gameserver.instancemanager.AntiFeedManager;
import org.l2jmobius.gameserver.instancemanager.CastleManager;
import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import org.l2jmobius.gameserver.instancemanager.DuelManager;
+import org.l2jmobius.gameserver.instancemanager.ElementalSpiritInstanceManager;
import org.l2jmobius.gameserver.instancemanager.FortManager;
import org.l2jmobius.gameserver.instancemanager.FortSiegeManager;
import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
@@ -125,6 +128,7 @@ import org.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import org.l2jmobius.gameserver.model.BlockList;
import org.l2jmobius.gameserver.model.CommandChannel;
import org.l2jmobius.gameserver.model.ContactList;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.Macro;
import org.l2jmobius.gameserver.model.MacroList;
@@ -213,6 +217,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerReputa
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerSubChange;
import org.l2jmobius.gameserver.model.fishing.Fishing;
import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.MovieHolder;
import org.l2jmobius.gameserver.model.holders.PlayerEventHolder;
@@ -847,6 +852,9 @@ public final class PlayerInstance extends Playable
private final Set _whisperers = ConcurrentHashMap.newKeySet();
+ private ElementalSpirit[] _spirits;
+ private ElementalType _activeElementalSpiritType;
+
// Selling buffs system
private boolean _isSellingBuffs = false;
private List _sellingBuffs = null;
@@ -2350,6 +2358,7 @@ public final class PlayerInstance extends Playable
if (getClassId().level() == 3)
{
sendPacket(SystemMessageId.CONGRATULATIONS_YOU_VE_COMPLETED_YOUR_THIRD_CLASS_TRANSFER_QUEST);
+ initElementalSpirits();
}
else
{
@@ -6662,6 +6671,11 @@ public final class PlayerInstance extends Playable
player.setSponsor(rset.getInt("sponsor"));
player.setLvlJoinedAcademy(rset.getInt("lvl_joined_academy"));
+ if ((player.getLevel() >= 76) && (player.getClassId().level() > 2))
+ {
+ player.initElementalSpirits();
+ }
+
CursedWeaponsManager.getInstance().checkPlayer(player);
// Set the x,y,z position of the PlayerInstance and make it invisible
@@ -7085,6 +7099,17 @@ public final class PlayerInstance extends Playable
{
aVars.storeMe();
}
+
+ if (_spirits != null)
+ {
+ for (ElementalSpirit spirit : _spirits)
+ {
+ if (spirit != null)
+ {
+ spirit.save();
+ }
+ }
+ }
}
@Override
@@ -11434,7 +11459,7 @@ public final class PlayerInstance extends Playable
}
@Override
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
// Check if hit is missed
if (miss)
@@ -11497,7 +11522,15 @@ public final class PlayerInstance extends Playable
}
else if (this != target)
{
- sm = new SystemMessage(SystemMessageId.C1_HAS_INFLICTED_S3_DAMAGE_ON_C2);
+ if (elementalDamage != 0)
+ {
+ sm = new SystemMessage(SystemMessageId.S1_HAS_INFLICTED_S3_DAMAGE_ATTRIBUTE_DAMAGE_S4_TO_S2);
+ }
+ else
+ {
+ sm = new SystemMessage(SystemMessageId.C1_HAS_INFLICTED_S3_DAMAGE_ON_C2);
+ }
+
sm.addPcName(this);
// Localisation related.
@@ -11513,6 +11546,10 @@ public final class PlayerInstance extends Playable
sm.addString(targetName);
sm.addInt(damage);
+ if (elementalDamage != 0)
+ {
+ sm.addInt((int) elementalDamage);
+ }
sm.addPopup(target.getObjectId(), getObjectId(), -damage);
}
@@ -13922,4 +13959,139 @@ public final class PlayerInstance extends Playable
getVariables().set(ATTENDANCE_INDEX_VAR, rewardIndex);
}
}
+
+ public void initElementalSpirits()
+ {
+ tryLoadSpirits();
+
+ if (_spirits == null)
+ {
+ final ElementalType[] types = ElementalType.values();
+ _spirits = new ElementalSpirit[types.length - 1]; // exclude None
+
+ for (ElementalType type : types)
+ {
+ if (ElementalType.NONE == type)
+ {
+ continue;
+ }
+
+ final ElementalSpirit spirit = new ElementalSpirit(type, this);
+ _spirits[type.getId() - 1] = spirit;
+ spirit.save();
+ }
+ }
+
+ if (_activeElementalSpiritType == null)
+ {
+ changeElementalSpirit(ElementalType.FIRE.getId());
+ }
+ }
+
+ private void tryLoadSpirits()
+ {
+ final List spiritsData = ElementalSpiritInstanceManager.getInstance().findByPlayerId(getObjectId());
+ if (!spiritsData.isEmpty())
+ {
+ _spirits = new ElementalSpirit[ElementalType.values().length - 1];
+ for (ElementalSpiritDataHolder spiritData : spiritsData)
+ {
+ _spirits[spiritData.getType() - 1] = new ElementalSpirit(spiritData, this);
+ if (spiritData.isInUse())
+ {
+ _activeElementalSpiritType = ElementalType.of(spiritData.getType());
+ }
+ }
+ }
+ }
+
+ public double getActiveElementalSpiritAttack()
+ {
+ return getStat().getElementalSpiritPower(_activeElementalSpiritType, CommonUtil.zeroIfNullOrElse(getElementalSpirit(_activeElementalSpiritType), ElementalSpirit::getAttack));
+ }
+
+ public double getFireSpiritDefense()
+ {
+ return getElementalSpiritDefenseOf(ElementalType.FIRE);
+ }
+
+ public double getWaterSpiritDefense()
+ {
+ return getElementalSpiritDefenseOf(ElementalType.WATER);
+ }
+
+ public double getWindSpiritDefense()
+ {
+ return getElementalSpiritDefenseOf(ElementalType.WIND);
+ }
+
+ public double getEarthSpiritDefense()
+ {
+ return getElementalSpiritDefenseOf(ElementalType.EARTH);
+ }
+
+ @Override
+ public double getElementalSpiritDefenseOf(ElementalType type)
+ {
+ return getStat().getElementalSpiritDefense(type, CommonUtil.zeroIfNullOrElse(getElementalSpirit(type), ElementalSpirit::getDefense));
+ }
+
+ public double getElementalSpiritCritRate()
+ {
+ return getStat().getElementalSpiritCriticalRate(CommonUtil.zeroIfNullOrElse(getElementalSpirit(_activeElementalSpiritType), ElementalSpirit::getCriticalRate));
+ }
+
+ public double getElementalSpiritCritDamage()
+ {
+ return getStat().getElementalSpiritCriticalDamage(CommonUtil.zeroIfNullOrElse(getElementalSpirit(_activeElementalSpiritType), ElementalSpirit::getCriticalDamage));
+ }
+
+ public double getElementalSpiritXpBonus()
+ {
+ return getStat().getElementalSpiritXpBonus();
+ }
+
+ public ElementalSpirit getElementalSpirit(ElementalType type)
+ {
+ if ((_spirits == null) || (type == null) || (type == ElementalType.NONE))
+ {
+ return null;
+ }
+ return _spirits[type.getId() - 1];
+ }
+
+ public byte getActiveElementalSpiritType()
+ {
+ return (byte) CommonUtil.zeroIfNullOrElse(_activeElementalSpiritType, ElementalType::getId);
+ }
+
+ public void changeElementalSpirit(byte element)
+ {
+ _activeElementalSpiritType = ElementalType.of(element);
+
+ if (_spirits != null)
+ {
+ for (ElementalSpirit spirit : _spirits)
+ {
+ if (spirit != null)
+ {
+ spirit.setInUse(spirit.getType() == element);
+ }
+ }
+ }
+
+ final UserInfo userInfo = new UserInfo(this, false);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ sendPacket(userInfo);
+ }
+
+ public ElementalSpirit[] getSpirits()
+ {
+ return _spirits;
+ }
+
+ public boolean isInBattle()
+ {
+ return AttackStanceTaskManager.getInstance().hasAttackStanceTask(this);
+ }
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/TrapInstance.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/TrapInstance.java
index a9eec7c6ca..1082bca00f 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/TrapInstance.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/TrapInstance.java
@@ -249,11 +249,11 @@ public final class TrapInstance extends Npc
public void doAttack(double damage, Creature target, Skill skill, boolean isDOT, boolean directlyToHp, boolean critical, boolean reflect)
{
super.doAttack(damage, target, skill, isDOT, directlyToHp, critical, reflect);
- sendDamageMessage(target, skill, (int) damage, critical, false);
+ sendDamageMessage(target, skill, (int) damage, 0, critical, false);
}
@Override
- public void sendDamageMessage(Creature target, Skill skill, int damage, boolean crit, boolean miss)
+ public void sendDamageMessage(Creature target, Skill skill, int damage, double elementalDamage, boolean crit, boolean miss)
{
if (miss || (_owner == null))
{
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java
index 7c1fc412ec..fd1778f549 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java
@@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.data.xml.impl.ExperienceData;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.PartySmallWindowUpdateType;
import org.l2jmobius.gameserver.enums.UserInfoType;
import org.l2jmobius.gameserver.model.Party;
@@ -684,6 +685,31 @@ public class PlayerStat extends PlayableStat
return (int) getValue(Stats.ARTIFACT_SLOTS, 0);
}
+ public double getElementalSpiritXpBonus()
+ {
+ return getValue(Stats.ELEMENTAL_SPIRIT_BONUS_EXP, 1);
+ }
+
+ public double getElementalSpiritPower(ElementalType type, double base)
+ {
+ return type == null ? 0 : getValue(type.getAttackStat(), base);
+ }
+
+ public double getElementalSpiritCriticalRate(int base)
+ {
+ return getValue(Stats.ELEMENTAL_SPIRIT_CRITICAL_RATE, base);
+ }
+
+ public double getElementalSpiritCriticalDamage(double base)
+ {
+ return getValue(Stats.ELEMENTAL_SPIRIT_CRITICAL_DAMAGE, base);
+ }
+
+ public double getElementalSpiritDefense(ElementalType type, double base)
+ {
+ return type == null ? 0 : getValue(type.getDefenseStat(), base);
+ }
+
@Override
protected void onRecalculateStats(boolean broadcast)
{
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
index 2813a06e63..3b38557c75 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
@@ -31,6 +31,7 @@ import org.l2jmobius.gameserver.datatables.ItemTable;
import org.l2jmobius.gameserver.enums.AISkillScope;
import org.l2jmobius.gameserver.enums.AIType;
import org.l2jmobius.gameserver.enums.DropType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.MpRewardAffectType;
import org.l2jmobius.gameserver.enums.MpRewardType;
import org.l2jmobius.gameserver.enums.Race;
@@ -118,6 +119,9 @@ public final class NpcTemplate extends CreatureTemplate implements IIdentifiable
private List _extendDrop;
+ private ElementalType _elementalType;
+ private long _attributeExp;
+
/**
* Constructor of Creature.
* @param set The StatsSet object to transfer data to the method
@@ -142,6 +146,8 @@ public final class NpcTemplate extends CreatureTemplate implements IIdentifiable
setRace(set.getEnum("race", Race.class, Race.NONE));
_sex = set.getEnum("sex", Sex.class, Sex.ETC);
+ _elementalType = set.getEnum("elementalType", ElementalType.class, ElementalType.NONE);
+
_chestId = set.getInt("chestId", 0);
_rhandId = set.getInt("rhandId", 0);
_lhandId = set.getInt("lhandId", 0);
@@ -150,6 +156,7 @@ public final class NpcTemplate extends CreatureTemplate implements IIdentifiable
_exp = set.getDouble("exp", 0);
_sp = set.getDouble("sp", 0);
_raidPoints = set.getDouble("raidPoints", 0);
+ _attributeExp = set.getLong("attribute_exp", 0);
_unique = set.getBoolean("unique", false);
_attackable = set.getBoolean("attackable", true);
@@ -354,6 +361,16 @@ public final class NpcTemplate extends CreatureTemplate implements IIdentifiable
return _raidPoints;
}
+ public long getAttributeExp()
+ {
+ return _attributeExp;
+ }
+
+ public ElementalType getElementalType()
+ {
+ return _elementalType;
+ }
+
public boolean isUnique()
{
return _unique;
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/EventType.java
index 77c1c74906..607e9dd022 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -37,6 +37,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureTeleport;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureTeleported;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureZoneEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureZoneExit;
+import org.l2jmobius.gameserver.model.events.impl.creature.OnElementalSpiritUpgrade;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAggroRangeEnter;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableAttack;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnAttackableFactionCall;
@@ -56,6 +57,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnNpcSkillSee;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnNpcSpawn;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnNpcTeleport;
import org.l2jmobius.gameserver.model.events.impl.creature.npc.OnNpcTeleportRequest;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnElementalSpiritLearn;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayableExpChanged;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerAbilityPointsChanged;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerAugment;
@@ -286,7 +288,10 @@ public enum EventType
ON_INSTANCE_DESTROY(OnInstanceDestroy.class, void.class),
ON_INSTANCE_ENTER(OnInstanceEnter.class, void.class),
ON_INSTANCE_LEAVE(OnInstanceLeave.class, void.class),
- ON_INSTANCE_STATUS_CHANGE(OnInstanceStatusChange.class, void.class);
+ ON_INSTANCE_STATUS_CHANGE(OnInstanceStatusChange.class, void.class),
+
+ ON_ELEMENTAL_SPIRIT_UPGRADE(OnElementalSpiritUpgrade.class, void.class),
+ ON_ELEMENTAL_SPIRIT_LEARN(OnElementalSpiritLearn.class, void.class);
private final Class extends IBaseEvent> _eventClass;
private final Class>[] _returnClass;
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/OnElementalSpiritUpgrade.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/OnElementalSpiritUpgrade.java
new file mode 100644
index 0000000000..4daf86f472
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/OnElementalSpiritUpgrade.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature;
+
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author JoeAlisson
+ */
+public class OnElementalSpiritUpgrade implements IBaseEvent
+{
+ private final ElementalSpirit _spirit;
+ private final PlayerInstance _player;
+
+ public OnElementalSpiritUpgrade(PlayerInstance player, ElementalSpirit spirit)
+ {
+ _player = player;
+ _spirit = spirit;
+ }
+
+ public ElementalSpirit getSpirit()
+ {
+ return _spirit;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_ELEMENTAL_SPIRIT_UPGRADE;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnElementalSpiritLearn.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnElementalSpiritLearn.java
new file mode 100644
index 0000000000..564e85edd5
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnElementalSpiritLearn.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author JoeAlisson
+ */
+public class OnElementalSpiritLearn implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnElementalSpiritLearn(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_ELEMENTAL_SPIRIT_LEARN;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritAbsorbItemHolder.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritAbsorbItemHolder.java
new file mode 100644
index 0000000000..1e6ecebe18
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritAbsorbItemHolder.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritAbsorbItemHolder
+{
+ private final int _id;
+ private final int _experience;
+
+ public ElementalSpiritAbsorbItemHolder(int itemId, int experience)
+ {
+ _id = itemId;
+ _experience = experience;
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public int getExperience()
+ {
+ return _experience;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritDataHolder.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritDataHolder.java
new file mode 100644
index 0000000000..0ae7c46f0c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritDataHolder.java
@@ -0,0 +1,179 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritDataHolder
+{
+ private int _charId;
+ private byte _type;
+ private byte _level = 1;
+ private byte _stage;
+ private long _experience;
+ private byte _attackPoints;
+ private byte _defensePoints;
+ private byte _critRatePoints;
+ private byte _critDamagePoints;
+ private boolean _inUse;
+
+ public ElementalSpiritDataHolder()
+ {
+ }
+
+ public ElementalSpiritDataHolder(byte type, int objectId)
+ {
+ _charId = objectId;
+ _type = type;
+ }
+
+ public int getCharId()
+ {
+ return _charId;
+ }
+
+ public void setCharId(int charId)
+ {
+ _charId = charId;
+ }
+
+ public byte getType()
+ {
+ return _type;
+ }
+
+ public void setType(byte type)
+ {
+ _type = type;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public void setLevel(byte level)
+ {
+ _level = level;
+ }
+
+ public byte getStage()
+ {
+ return _stage;
+ }
+
+ public void setStage(byte stage)
+ {
+ _stage = stage;
+ }
+
+ public long getExperience()
+ {
+ return _experience;
+ }
+
+ public void setExperience(long experience)
+ {
+ _experience = experience;
+ }
+
+ public byte getAttackPoints()
+ {
+ return _attackPoints;
+ }
+
+ public void setAttackPoints(byte attackPoints)
+ {
+ _attackPoints = attackPoints;
+ }
+
+ public byte getDefensePoints()
+ {
+ return _defensePoints;
+ }
+
+ public void setDefensePoints(byte defensePoints)
+ {
+ _defensePoints = defensePoints;
+ }
+
+ public byte getCritRatePoints()
+ {
+ return _critRatePoints;
+ }
+
+ public void setCritRatePoints(byte critRatePoints)
+ {
+ _critRatePoints = critRatePoints;
+ }
+
+ public byte getCritDamagePoints()
+ {
+ return _critDamagePoints;
+ }
+
+ public void setCritDamagePoints(byte critDamagePoints)
+ {
+ _critDamagePoints = critDamagePoints;
+ }
+
+ public void addExperience(long experience)
+ {
+ _experience += experience;
+ }
+
+ public void increaseLevel()
+ {
+ _level++;
+ }
+
+ public boolean isInUse()
+ {
+ return _inUse;
+ }
+
+ public void setInUse(boolean value)
+ {
+ _inUse = value;
+ }
+
+ public void addAttackPoints(byte attackPoints)
+ {
+ _attackPoints += attackPoints;
+ }
+
+ public void addDefensePoints(byte defensePoints)
+ {
+ _defensePoints += defensePoints;
+ }
+
+ public void addCritRatePoints(byte critRatePoints)
+ {
+ _critRatePoints = critRatePoints;
+ }
+
+ public void addCritDamagePoints(byte critDamagePoints)
+ {
+ _critDamagePoints += critDamagePoints;
+ }
+
+ public void increaseStage()
+ {
+ _stage++;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritTemplateHolder.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritTemplateHolder.java
new file mode 100644
index 0000000000..ceb6beac43
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/holders/ElementalSpiritTemplateHolder.java
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritTemplateHolder
+{
+ private final byte _type;
+ private final byte _stage;
+ private final int _npcId;
+ private final int _maxCharacteristics;
+ private final int _extractItem;
+
+ private final Map _levels;
+ private List _itemsToEvolve;
+ private List _absorbItems;
+
+ public ElementalSpiritTemplateHolder(byte type, byte stage, int npcId, int extractItem, int maxCharacteristics)
+ {
+ _type = type;
+ _stage = stage;
+ _npcId = npcId;
+ _extractItem = extractItem;
+ _maxCharacteristics = maxCharacteristics;
+ _levels = new HashMap<>(10);
+ }
+
+ public void addLevelInfo(int level, int attack, int defense, int criticalRate, int criticalDamage, long maxExperience)
+ {
+ final SpiritLevel spiritLevel = new SpiritLevel();
+ spiritLevel.attack = attack;
+ spiritLevel.defense = defense;
+ spiritLevel.criticalRate = criticalRate;
+ spiritLevel.criticalDamage = criticalDamage;
+ spiritLevel.maxExperience = maxExperience;
+ _levels.put((byte) level, spiritLevel);
+ }
+
+ public void addItemToEvolve(Integer itemId, Integer count)
+ {
+ if (_itemsToEvolve == null)
+ {
+ _itemsToEvolve = new ArrayList<>(2);
+ }
+ _itemsToEvolve.add(new ItemHolder(itemId, count));
+ }
+
+ public byte getType()
+ {
+ return _type;
+ }
+
+ public byte getStage()
+ {
+ return _stage;
+ }
+
+ public int getNpcId()
+ {
+ return _npcId;
+ }
+
+ public long getMaxExperienceAtLevel(byte level)
+ {
+ return _levels.get(level).maxExperience;
+ }
+
+ public int getMaxLevel()
+ {
+ return _levels.size();
+ }
+
+ public int getAttackAtLevel(byte level)
+ {
+ return _levels.get(level).attack;
+ }
+
+ public int getDefenseAtLevel(byte level)
+ {
+ return _levels.get(level).defense;
+ }
+
+ public int getCriticalRateAtLevel(byte level)
+ {
+ return _levels.get(level).criticalRate;
+ }
+
+ public int getCriticalDamageAtLevel(byte level)
+ {
+ return _levels.get(level).criticalDamage;
+ }
+
+ public int getMaxCharacteristics()
+ {
+ return _maxCharacteristics;
+ }
+
+ public List getItemsToEvolve()
+ {
+ return _itemsToEvolve == null ? Collections.emptyList() : _itemsToEvolve;
+ }
+
+ public void addAbsorbItem(Integer itemId, Integer experience)
+ {
+ if (_absorbItems == null)
+ {
+ _absorbItems = new ArrayList<>();
+ }
+ _absorbItems.add(new ElementalSpiritAbsorbItemHolder(itemId, experience));
+ }
+
+ public List getAbsorbItems()
+ {
+ return _absorbItems == null ? Collections.emptyList() : _absorbItems;
+ }
+
+ public int getExtractItem()
+ {
+ return _extractItem;
+ }
+
+ private static class SpiritLevel
+ {
+ public SpiritLevel()
+ {
+ }
+
+ long maxExperience;
+ int criticalDamage;
+ int criticalRate;
+ int defense;
+ int attack;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/Formulas.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/Formulas.java
index 3d75ea852e..92c5c50e1b 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/Formulas.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/Formulas.java
@@ -27,6 +27,7 @@ import org.l2jmobius.gameserver.data.xml.impl.KarmaData;
import org.l2jmobius.gameserver.enums.AttributeType;
import org.l2jmobius.gameserver.enums.BasicProperty;
import org.l2jmobius.gameserver.enums.DispelSlotType;
+import org.l2jmobius.gameserver.enums.ElementalType;
import org.l2jmobius.gameserver.enums.Position;
import org.l2jmobius.gameserver.enums.ShotType;
import org.l2jmobius.gameserver.model.actor.Creature;
@@ -1652,4 +1653,77 @@ public final class Formulas
return 1;
}
+
+ public static double calcSpiritElementalDamage(Creature attacker, Creature target)
+ {
+ if (attacker.isPlayer())
+ {
+ final PlayerInstance attackerPlayer = attacker.getActingPlayer();
+ ElementalType type = ElementalType.of(attackerPlayer.getActiveElementalSpiritType());
+
+ if (ElementalType.NONE == type)
+ {
+ return 0;
+ }
+
+ final double critRate = attackerPlayer.getElementalSpiritCritRate();
+ final boolean isCrit = Math.min(critRate, 380) > Rnd.get(1000);
+ final double critDamage = attackerPlayer.getElementalSpiritCritDamage();
+ final double attack = attackerPlayer.getActiveElementalSpiritAttack() - target.getElementalSpiritDefenseOf(type);
+ if (target.isPlayer())
+ {
+ return calcSpiritElementalPvPDamage(attack, critDamage, isCrit);
+ }
+ return calcSpiritElementalPvEDamage(type, target.getElementalSpiritType(), attack, critDamage, isCrit);
+ }
+
+ return 0;
+ }
+
+ private static double calcSpiritElementalPvPDamage(double attack, double critDamage, boolean isCrit)
+ {
+ double damage = (attack * 1.223) + Rnd.get(-20, +20);
+ if (isCrit)
+ {
+ damage += (attack * 1.223) + (((attack * 0.03) + 24) * critDamage) + Rnd.get(-5, 30);
+ }
+ return damage;
+ }
+
+ private static double calcSpiritElementalPvEDamage(ElementalType attackerType, ElementalType targetType, double attack, double critDamage, boolean isCrit)
+ {
+ double damage;
+ double baseDamage = (attack * 0.8) + Rnd.get(-25, 25);
+ double bonus = 1;
+ if (targetType == ElementalType.NONE)
+ {
+ damage = attack * 0.735;
+ }
+ else if (attackerType.getDominating() == targetType)
+ {
+ damage = (-1136 + baseDamage) * 0.6;
+ bonus = 0.6;
+ }
+ else if (targetType.getDominating() == attackerType)
+ {
+ damage = (185 + baseDamage) * 1.2;
+ bonus = 1.2;
+ }
+ else if (targetType == attackerType)
+ {
+ damage = baseDamage;
+ }
+ else
+ {
+ damage = (-477 + baseDamage) * 0.8;
+ bonus = 0.8;
+ }
+
+ if (isCrit)
+ {
+ damage += ((40 + ((9.2 + (attack * 0.048)) * critDamage)) * bonus) + Rnd.get(-10, 50);
+ }
+
+ return damage;
+ }
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/Stats.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/Stats.java
index d1defb05d5..24ff26bae8 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/Stats.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/stats/Stats.java
@@ -89,6 +89,19 @@ public enum Stats
HATE_ATTACK("attackHate"),
REAR_DAMAGE_RATE("rearDamage"),
+ // ELEMENTAL SPIRITS
+ ELEMENTAL_SPIRIT_FIRE_ATTACK("elementalSpiritFireAttack"),
+ ELEMENTAL_SPIRIT_WATER_ATTACK("elementalSpiritWaterAttack"),
+ ELEMENTAL_SPIRIT_WIND_ATTACK("elementalSpiritWindAttack"),
+ ELEMENTAL_SPIRIT_EARTH_ATTACK("elementalSpiritEarthAttack"),
+ ELEMENTAL_SPIRIT_FIRE_DEFENSE("elementalSpiritFireDefense"),
+ ELEMENTAL_SPIRIT_WATER_DEFENSE("elementalSpiritWaterDefense"),
+ ELEMENTAL_SPIRIT_WIND_DEFENSE("elementalSpiritWindDefense"),
+ ELEMENTAL_SPIRIT_EARTH_DEFENSE("elementalSpiritEarthDefense"),
+ ELEMENTAL_SPIRIT_CRITICAL_RATE("elementalSpiritCriticalRate"),
+ ELEMENTAL_SPIRIT_CRITICAL_DAMAGE("elementalSpiritCriticalDamage"),
+ ELEMENTAL_SPIRIT_BONUS_EXP("elementalSpiritExp"),
+
// PVP BONUS
PVP_PHYSICAL_ATTACK_DAMAGE("pvpPhysDmg"),
PVP_MAGICAL_SKILL_DAMAGE("pvpMagicalDmg"),
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index d055889cbd..c04f967752 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -60,7 +60,16 @@ import org.l2jmobius.gameserver.network.clientpackets.crystalization.RequestCrys
import org.l2jmobius.gameserver.network.clientpackets.crystalization.RequestCrystallizeItemCancel;
import org.l2jmobius.gameserver.network.clientpackets.dailymission.RequestOneDayRewardReceive;
import org.l2jmobius.gameserver.network.clientpackets.dailymission.RequestTodoList;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalInitTalent;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritAbsorb;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritAbsorbInfo;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritChangeType;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritEvolution;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritEvolutionInfo;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritExtract;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritExtractInfo;
import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritInfo;
+import org.l2jmobius.gameserver.network.clientpackets.elementalspirits.ExElementalSpiritSetTalent;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestItemEnsoul;
import org.l2jmobius.gameserver.network.clientpackets.ensoul.RequestTryEnSoulExtraction;
import org.l2jmobius.gameserver.network.clientpackets.equipmentupgrade.RequestUpgradeSystemResult;
@@ -424,21 +433,21 @@ public enum ExIncomingPackets implements IIncomingPackets
EX_PLEDGE_ITEM_INFO(0x14E, null, ConnectionState.IN_GAME),
EX_PLEDGE_ITEM_BUY(0x14F, null, ConnectionState.IN_GAME),
EX_ELEMENTAL_SPIRIT_INFO(0x150, ExElementalSpiritInfo::new, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_EXTRACT_INFO(0x151, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_EXTRACT(0x152, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_EVOLUTION_INFO(0x153, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_EVOLUTION(0x154, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_SET_TALENT(0x155, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_INIT_TALENT(0x156, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_ABSORB_INFO(0x157, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_ABSORB(0x158, null, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_EXTRACT_INFO(0x151, ExElementalSpiritExtractInfo::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_EXTRACT(0x152, ExElementalSpiritExtract::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_EVOLUTION_INFO(0x153, ExElementalSpiritEvolutionInfo::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_EVOLUTION(0x154, ExElementalSpiritEvolution::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_SET_TALENT(0x155, ExElementalSpiritSetTalent::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_INIT_TALENT(0x156, ExElementalInitTalent::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_ABSORB_INFO(0x157, ExElementalSpiritAbsorbInfo::new, ConnectionState.IN_GAME),
+ EX_ELEMENTAL_SPIRIT_ABSORB(0x158, ExElementalSpiritAbsorb::new, ConnectionState.IN_GAME),
EX_REQUEST_LOCKED_ITEM(0x159, null, ConnectionState.IN_GAME),
EX_REQUEST_UNLOCKED_ITEM(0x15A, null, ConnectionState.IN_GAME),
EX_LOCKED_ITEM_CANCEL(0x15B, null, ConnectionState.IN_GAME),
EX_UNLOCKED_ITEM_CANCEL(0x15C, null, ConnectionState.IN_GAME),
- REQUEST_BLOCK_LIST_FOR_AD(0x15D, null, ConnectionState.IN_GAME),
- REQUEST_USER_BAN_INFO(0x15E, null, ConnectionState.IN_GAME),
- EX_ELEMENTAL_SPIRIT_CHANGE_TYPE(0x15F, null, ConnectionState.IN_GAME), // 152
+ EX_ELEMENTAL_SPIRIT_CHANGE_TYPE(0x15D, ExElementalSpiritChangeType::new, ConnectionState.IN_GAME), // 152
+ REQUEST_BLOCK_LIST_FOR_AD(0x15E, null, ConnectionState.IN_GAME),
+ REQUEST_USER_BAN_INFO(0x15F, null, ConnectionState.IN_GAME),
EX_INTERACT_MODIFY(0x160, null, ConnectionState.IN_GAME), // 152
EX_TRY_ENCHANT_ARTIFACT(0x161, null, ConnectionState.IN_GAME), // 152
EX_XIGN_CODE(0x162, null, ConnectionState.IN_GAME); // 152
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalInitTalent.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalInitTalent.java
new file mode 100644
index 0000000000..df17e97b49
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalInitTalent.java
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.data.xml.impl.ElementalSpiritData;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritSetTalent;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalInitTalent implements IClientIncomingPacket
+{
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ if (player.isInBattle())
+ {
+ client.sendPacket(new SystemMessage(SystemMessageId.UNABLE_TO_RESET_SPIRIT_ATTRIBUTE_DURING_BATTLE));
+ client.sendPacket(new ElementalSpiritSetTalent(player, _type, false));
+ return;
+ }
+
+ if (player.reduceAdena("Talent", ElementalSpiritData.TALENT_INIT_FEE, player, true))
+ {
+ spirit.resetCharacteristics();
+ client.sendPacket(new SystemMessage(SystemMessageId.RESET_THE_SELECTED_SPIRIT_S_CHARACTERISTICS_SUCCESSFULLY));
+ client.sendPacket(new ElementalSpiritSetTalent(player, _type, true));
+ }
+ else
+ {
+ client.sendPacket(new ElementalSpiritSetTalent(player, _type, false));
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorb.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorb.java
new file mode 100644
index 0000000000..8d3ce46e9b
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorb.java
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.PrivateStoreType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritAbsorbItemHolder;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritAbsorb;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritAbsorb implements IClientIncomingPacket
+{
+ private byte _type;
+ private int _itemId;
+ private int _amount;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ packet.readD(); // items for now is always 1
+ _itemId = packet.readD();
+ _amount = packet.readD();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ final ElementalSpiritAbsorbItemHolder absorbItem = spirit.getAbsorbItem(_itemId);
+ if (absorbItem == null)
+ {
+ player.sendPacket(new ElementalSpiritAbsorb(player, _type, false));
+ return;
+ }
+
+ final boolean canAbsorb = checkConditions(player, spirit);
+ if (canAbsorb)
+ {
+ client.sendPacket(SystemMessageId.SUCCESFUL_ABSORPTION);
+ spirit.addExperience(absorbItem.getExperience() * _amount);
+ final UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ client.sendPacket(userInfo);
+ }
+ client.sendPacket(new ElementalSpiritAbsorb(player, _type, canAbsorb));
+ }
+
+ private boolean checkConditions(PlayerInstance player, ElementalSpirit spirit)
+ {
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessageId.CANNOT_EVOLVE_ABSORB_EXTRACT_WHILE_USING_THE_PRIVATE_STORE_WORKSHOP);
+ return false;
+ }
+ if (player.isInBattle())
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_ABSORB_DURING_BATTLE);
+ return false;
+ }
+ if ((spirit.getLevel() == spirit.getMaxLevel()) && (spirit.getExperience() == spirit.getExperienceToNextLevel()))
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_ABSORB_BECAUSE_REACHED_MAXIMUM_LEVEL);
+ return false;
+ }
+ if ((_amount < 1) || !player.destroyItemByItemId("Absorb", _itemId, _amount, player, true))
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_INGREDIENTS_TO_ABSORB);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorbInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorbInfo.java
new file mode 100644
index 0000000000..6db3148a54
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritAbsorbInfo.java
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritAbsorbInfo;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritAbsorbInfo implements IClientIncomingPacket
+{
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ packet.readC(); // unk
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ client.sendPacket(new ElementalSpiritAbsorbInfo(player, _type));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritChangeType.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritChangeType.java
new file mode 100644
index 0000000000..48157c3b11
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritChangeType.java
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritInfo;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritChangeType implements IClientIncomingPacket
+{
+ private byte _type;
+ private byte _element;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ _element = (byte) packet.readC(); // 1 - Fire, 2 - Water, 3 - Wind, 4 Earth
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ player.changeElementalSpirit(_element);
+ client.sendPacket(new ElementalSpiritInfo(player, _element, _type));
+ client.sendPacket(new SystemMessage(SystemMessageId.S1_WILL_BE_YOUR_ATTRIBUTE_ATTACK_FROM_NOW_ON).addElementalSpirit(_element));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolution.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolution.java
new file mode 100644
index 0000000000..9d9cb3850f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolution.java
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import java.util.stream.Collectors;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.InventoryBlockType;
+import org.l2jmobius.gameserver.enums.PrivateStoreType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.itemcontainer.PlayerInventory;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritEvolution;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritEvolution implements IClientIncomingPacket
+{
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ final boolean canEvolve = checkConditions(player, spirit);
+ if (canEvolve)
+ {
+ spirit.upgrade();
+ client.sendPacket(new SystemMessage(SystemMessageId.S1_EVOLVED_TO_S2_STAR).addElementalSpirit(_type).addInt(spirit.getStage()));
+ final UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ client.sendPacket(userInfo);
+ }
+ client.sendPacket(new ElementalSpiritEvolution(player, _type, canEvolve));
+ }
+
+ private boolean checkConditions(PlayerInstance player, ElementalSpirit spirit)
+ {
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessageId.CANNOT_EVOLVE_ABSORB_EXTRACT_WHILE_USING_THE_PRIVATE_STORE_WORKSHOP);
+ return false;
+ }
+ if (player.isInBattle())
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_EVOLVE_DURING_BATTLE);
+ return false;
+ }
+ if (!spirit.canEvolve())
+ {
+ player.sendPacket(SystemMessageId.THIS_SPIRIT_CANNOT_EVOLVE);
+ return false;
+ }
+ if (!consumeEvolveItems(player, spirit))
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_INGREDIENTS_FOR_EVOLUTION);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean consumeEvolveItems(PlayerInstance player, ElementalSpirit spirit)
+ {
+ final PlayerInventory inventory = player.getInventory();
+ try
+ {
+ inventory.setInventoryBlock(spirit.getItemsToEvolve().stream().map(ItemHolder::getId).collect(Collectors.toList()), InventoryBlockType.BLACKLIST);
+ for (ItemHolder itemHolder : spirit.getItemsToEvolve())
+ {
+ if (inventory.getInventoryItemCount(itemHolder.getId(), -1) < itemHolder.getCount())
+ {
+ return false;
+ }
+ }
+
+ for (ItemHolder itemHolder : spirit.getItemsToEvolve())
+ {
+ player.destroyItemByItemId("Evolve", itemHolder.getId(), itemHolder.getCount(), player, true);
+ }
+ return true;
+ }
+ finally
+ {
+ inventory.unblock();
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolutionInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolutionInfo.java
new file mode 100644
index 0000000000..95090ffdc1
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritEvolutionInfo.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritEvolutionInfo;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritEvolutionInfo implements IClientIncomingPacket
+{
+ private byte _id;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _id = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ client.sendPacket(new ElementalSpiritEvolutionInfo(player, _id));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtract.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtract.java
new file mode 100644
index 0000000000..76d035dddd
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtract.java
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.data.xml.impl.ElementalSpiritData;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.PrivateStoreType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritExtract;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritExtract implements IClientIncomingPacket
+{
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ client.sendPacket(SystemMessageId.NO_SPIRITS_ARE_AVAILABLE);
+ return;
+ }
+
+ final boolean canExtract = checkConditions(player, spirit);
+ if (canExtract)
+ {
+ final int amount = spirit.getExtractAmount();
+ client.sendPacket(new SystemMessage(SystemMessageId.EXTRACTED_S1_S2_SUCCESSFULLY).addItemName(spirit.getExtractItem()).addInt(amount));
+ spirit.resetStage();
+ player.addItem("Extract", spirit.getExtractItem(), amount, player, true);
+
+ final UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ client.sendPacket(userInfo);
+ }
+
+ client.sendPacket(new ElementalSpiritExtract(player, _type, canExtract));
+ }
+
+ private boolean checkConditions(PlayerInstance player, ElementalSpirit spirit)
+ {
+ if (spirit.getExtractAmount() < 1)
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_ATTRIBUTE_XP_FOR_EXTRACTION);
+ return false;
+ }
+ if (!player.getInventory().validateCapacity(1))
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_EXTRACT_BECAUSE_INVENTORY_IS_FULL);
+ return false;
+ }
+ if (player.getPrivateStoreType() != PrivateStoreType.NONE)
+ {
+ player.sendPacket(SystemMessageId.CANNOT_EVOLVE_ABSORB_EXTRACT_WHILE_USING_THE_PRIVATE_STORE_WORKSHOP);
+ return false;
+ }
+ if (player.isInBattle())
+ {
+ player.sendPacket(SystemMessageId.UNABLE_TO_EVOLVE_DURING_BATTLE);
+ return false;
+ }
+ if (!player.reduceAdena("Extract", ElementalSpiritData.EXTRACT_FEE, player, true))
+ {
+ player.sendPacket(SystemMessageId.NOT_ENOUGH_INGREDIENTS_TO_EXTRACT);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtractInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtractInfo.java
new file mode 100644
index 0000000000..b3a110c521
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritExtractInfo.java
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritExtractInfo;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritExtractInfo implements IClientIncomingPacket
+{
+
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ client.sendPacket(new ElementalSpiritExtractInfo(player, _type));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritInfo.java
index a9347a67c2..816272b4fd 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritInfo.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritInfo.java
@@ -1,50 +1,50 @@
-/*
- * This file is part of the L2J Mobius project.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
-
-import org.l2jmobius.commons.network.PacketReader;
-import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
-import org.l2jmobius.gameserver.network.GameClient;
-import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
-
-/**
- * @author Mobius
- */
-public class ExElementalSpiritInfo implements IClientIncomingPacket
-{
- @SuppressWarnings("unused")
- private int _id;
-
- @Override
- public boolean read(GameClient client, PacketReader packet)
- {
- _id = packet.readC();
- return true;
- }
-
- @Override
- public void run(GameClient client)
- {
- final PlayerInstance player = client.getPlayer();
- if (player == null)
- {
- return;
- }
-
- // player.sendPacket(new org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ExElementalSpiritInfo());
- }
-}
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritInfo;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritInfo implements IClientIncomingPacket
+{
+ private byte _type;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ client.sendPacket(new ElementalSpiritInfo(player, player.getActiveElementalSpiritType(), _type));
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritSetTalent.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritSetTalent.java
new file mode 100644
index 0000000000..2b26a8786f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/elementalspirits/ExElementalSpiritSetTalent.java
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.enums.UserInfoType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.SystemMessageId;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
+import org.l2jmobius.gameserver.network.serverpackets.elementalspirits.ElementalSpiritSetTalent;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritSetTalent implements IClientIncomingPacket
+{
+ private byte _type;
+ private byte _attackPoints;
+ private byte _defensePoints;
+ private byte _critRate;
+ private byte _critDamage;
+
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ _type = (byte) packet.readC();
+ packet.readC(); // Characteristics for now always 4
+
+ packet.readC(); // attack id
+ _attackPoints = (byte) packet.readC();
+
+ packet.readC(); // defense id
+ _defensePoints = (byte) packet.readC();
+
+ packet.readC(); // crit rate id
+ _critRate = (byte) packet.readC();
+
+ packet.readC(); // crit damage id
+ _critDamage = (byte) packet.readC();
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final PlayerInstance player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ final ElementalSpirit spirit = player.getElementalSpirit(ElementalType.of(_type));
+ boolean result = false;
+ if (spirit != null)
+ {
+ if ((_attackPoints > 0) && (spirit.getAvailableCharacteristicsPoints() >= _attackPoints))
+ {
+ spirit.addAttackPoints(_attackPoints);
+ result = true;
+ }
+
+ if ((_defensePoints > 0) && (spirit.getAvailableCharacteristicsPoints() >= _defensePoints))
+ {
+ spirit.addDefensePoints(_defensePoints);
+ result = true;
+ }
+
+ if ((_critRate > 0) && (spirit.getAvailableCharacteristicsPoints() >= _critRate))
+ {
+ spirit.addCritRatePoints(_critRate);
+ result = true;
+ }
+
+ if ((_critDamage > 0) && (spirit.getAvailableCharacteristicsPoints() >= _critDamage))
+ {
+ spirit.addCritDamage(_critDamage);
+ result = true;
+ }
+ }
+
+ if (result)
+ {
+ final UserInfo userInfo = new UserInfo(player);
+ userInfo.addComponentType(UserInfoType.ATT_SPIRITS);
+ client.sendPacket(userInfo);
+ client.sendPacket(new SystemMessage(SystemMessageId.CHARACTERISTICS_WERE_APPLIED_SUCCESSFULLY));
+ }
+ client.sendPacket(new ElementalSpiritSetTalent(player, _type, result));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ConfirmDlg.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ConfirmDlg.java
index adf7845f18..dd70213119 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ConfirmDlg.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ConfirmDlg.java
@@ -80,6 +80,7 @@ public class ConfirmDlg implements IClientOutgoingPacket
case SystemMessage.TYPE_ELEMENT_NAME:
case SystemMessage.TYPE_BYTE:
case SystemMessage.TYPE_FACTION_NAME:
+ case SystemMessage.TYPE_ELEMENTAL_SPIRIT:
{
packet.writeC(param.getIntValue());
break;
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/SystemMessage.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/SystemMessage.java
index 13a9444fe9..641446744f 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/SystemMessage.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/SystemMessage.java
@@ -80,6 +80,7 @@ public final class SystemMessage implements IClientOutgoingPacket
}
}
+ public static final byte TYPE_ELEMENTAL_SPIRIT = 26;
public static final byte TYPE_FACTION_NAME = 24; // c(short), faction id.
// id 22 d (shared with 1-3,17,22
// id 21 h
@@ -374,6 +375,12 @@ public final class SystemMessage implements IClientOutgoingPacket
return this;
}
+ public SystemMessage addElementalSpirit(int elementType)
+ {
+ append(new SMParam(TYPE_ELEMENTAL_SPIRIT, elementType));
+ return this;
+ }
+
public SMParam[] getParams()
{
return _params;
@@ -419,6 +426,7 @@ public final class SystemMessage implements IClientOutgoingPacket
case TYPE_ELEMENT_NAME:
case TYPE_BYTE:
case TYPE_FACTION_NAME:
+ case TYPE_ELEMENTAL_SPIRIT:
{
packet.writeC(param.getIntValue());
break;
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/UserInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/UserInfo.java
index 7199f724d9..d2ea90ce38 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/UserInfo.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/UserInfo.java
@@ -19,7 +19,6 @@ package org.l2jmobius.gameserver.network.serverpackets;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.data.xml.impl.ExperienceData;
-import org.l2jmobius.gameserver.enums.AttributeType;
import org.l2jmobius.gameserver.enums.UserInfoType;
import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import org.l2jmobius.gameserver.model.Party;
@@ -376,12 +375,12 @@ public class UserInfo extends AbstractMaskPacket
if (containsMask(UserInfoType.ATT_SPIRITS)) // 152
{
packet.writeH(26);
- packet.writeD(_player.getAttackElementValue(_player.getAttackElement())); // Attribute Attack Power
- packet.writeD(_player.getDefenseElementValue(AttributeType.FIRE)); // Fire defence
- packet.writeD(_player.getDefenseElementValue(AttributeType.WATER)); // Water defence
- packet.writeD(_player.getDefenseElementValue(AttributeType.WIND)); // Wind defence
- packet.writeD(_player.getDefenseElementValue(AttributeType.EARTH)); // Earth defence
- packet.writeD(0x00); // Enabled 1 - Disabled 0 // Third class player?
+ packet.writeD((int) _player.getActiveElementalSpiritAttack());
+ packet.writeD((int) _player.getFireSpiritDefense());
+ packet.writeD((int) _player.getWaterSpiritDefense());
+ packet.writeD((int) _player.getWindSpiritDefense());
+ packet.writeD((int) _player.getEarthSpiritDefense());
+ packet.writeD(_player.getActiveElementalSpiritType());
}
return true;
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/AbstractElementalSpiritPacket.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/AbstractElementalSpiritPacket.java
new file mode 100644
index 0000000000..f8e7ddf482
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/AbstractElementalSpiritPacket.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+abstract class AbstractElementalSpiritPacket implements IClientOutgoingPacket
+{
+ void writeSpiritInfo(PacketWriter packet, ElementalSpirit spirit)
+ {
+ packet.writeC(spirit.getStage());
+ packet.writeD(spirit.getNpcId());
+ packet.writeQ(spirit.getExperience());
+ packet.writeQ(spirit.getExperienceToNextLevel());
+ packet.writeQ(spirit.getExperienceToNextLevel());
+ packet.writeD(spirit.getLevel());
+ packet.writeD(spirit.getMaxLevel());
+ packet.writeD(spirit.getAvailableCharacteristicsPoints());
+ packet.writeD(spirit.getAttackPoints());
+ packet.writeD(spirit.getDefensePoints());
+ packet.writeD(spirit.getCriticalRatePoints());
+ packet.writeD(spirit.getCriticalDamagePoints());
+ packet.writeD(spirit.getMaxCharacteristics());
+ packet.writeD(spirit.getMaxCharacteristics());
+ packet.writeD(spirit.getMaxCharacteristics());
+ packet.writeD(spirit.getMaxCharacteristics());
+
+ packet.writeC(1); // unk
+
+ for (int j = 0; j < 1; j++)
+ {
+ packet.writeH(2);
+ packet.writeQ(100);
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorb.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorb.java
new file mode 100644
index 0000000000..95b61ff38c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorb.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritAbsorb extends UpdateElementalSpiritPacket
+{
+ public ElementalSpiritAbsorb(PlayerInstance player, byte type, boolean absorbed)
+ {
+ super(player, type, absorbed);
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_ABSORB.writeId(packet);
+ writeUpdate(packet);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorbInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorbInfo.java
new file mode 100644
index 0000000000..cc4937a891
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritAbsorbInfo.java
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ElementalSpiritAbsorbItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritAbsorbInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final byte _type;
+
+ public ElementalSpiritAbsorbInfo(PlayerInstance player, byte type)
+ {
+ _player = player;
+ _type = type;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_ABSORB_INFO.writeId(packet);
+
+ final ElementalSpirit spirit = _player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ packet.writeC(0x00);
+ packet.writeC(0x00);
+ return true;
+ }
+
+ packet.writeC(0x01);
+ packet.writeC(_type);
+ packet.writeC(spirit.getStage());
+ packet.writeQ(spirit.getExperience());
+ packet.writeQ(spirit.getExperienceToNextLevel()); // NextExp
+ packet.writeQ(spirit.getExperienceToNextLevel()); // MaxExp
+ packet.writeD(spirit.getLevel());
+ packet.writeD(spirit.getMaxLevel());
+
+ final List absorbItems = spirit.getAbsorbItems();
+ packet.writeD(absorbItems.size()); // AbsorbCount
+ for (ElementalSpiritAbsorbItemHolder absorbItem : absorbItems)
+ {
+ packet.writeD(absorbItem.getId());
+ packet.writeD(CommonUtil.zeroIfNullOrElse(_player.getInventory().getItemByItemId(absorbItem.getId()), item -> (int) item.getCount()));
+ packet.writeD(absorbItem.getExperience());
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolution.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolution.java
new file mode 100644
index 0000000000..9c9c14a986
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolution.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritEvolution extends UpdateElementalSpiritPacket
+{
+ public ElementalSpiritEvolution(PlayerInstance player, byte type, boolean evolved)
+ {
+ super(player, type, evolved);
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_EVOLUTION.writeId(packet);
+ writeUpdate(packet);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolutionInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolutionInfo.java
new file mode 100644
index 0000000000..720f17f176
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritEvolutionInfo.java
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import java.util.List;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritEvolutionInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final byte _type;
+
+ public ElementalSpiritEvolutionInfo(PlayerInstance player, byte type)
+ {
+ _player = player;
+ _type = type;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_EVOLUTION_INFO.writeId(packet);
+
+ final ElementalSpirit spirit = _player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ packet.writeC(0);
+ packet.writeD(0);
+ return true;
+ }
+
+ packet.writeC(_type);
+ packet.writeD(spirit.getNpcId());
+ packet.writeD(0x01); // unk
+ packet.writeD(spirit.getStage());
+ packet.writeF(100); // chance ??
+
+ final List items = spirit.getItemsToEvolve();
+ packet.writeD(items.size());
+ for (ItemHolder item : items)
+ {
+ packet.writeD(item.getId());
+ packet.writeQ(item.getCount());
+ }
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtract.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtract.java
new file mode 100644
index 0000000000..1f404a6c55
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtract.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritExtract extends UpdateElementalSpiritPacket
+{
+ public ElementalSpiritExtract(PlayerInstance player, byte type, boolean extracted)
+ {
+ super(player, type, extracted);
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_EXTRACT.writeId(packet);
+ writeUpdate(packet);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtractInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtractInfo.java
new file mode 100644
index 0000000000..102b1f5faa
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritExtractInfo.java
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritExtractInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final byte _type;
+
+ public ElementalSpiritExtractInfo(PlayerInstance player, byte type)
+ {
+ _player = player;
+ _type = type;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_EXTRACT_INFO.writeId(packet);
+
+ final ElementalSpirit spirit = _player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ packet.writeC(0);
+ packet.writeC(0);
+ return true;
+ }
+
+ packet.writeC(_type); // active elemental spirit
+ packet.writeC(1); // is extract ?
+
+ packet.writeC(1); // cost count
+ // for each cost count
+ packet.writeD(57); // item id
+ packet.writeD(1000000); // item count
+
+ packet.writeD(spirit.getExtractItem());
+ packet.writeD(spirit.getExtractAmount());
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritInfo.java
new file mode 100644
index 0000000000..068bde1181
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritInfo.java
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritInfo extends AbstractElementalSpiritPacket
+{
+ private final PlayerInstance _player;
+ private final byte _spiritType;
+ private final byte _type;
+
+ public ElementalSpiritInfo(PlayerInstance player, byte spiritType, byte packetType)
+ {
+ _player = player;
+ _spiritType = spiritType;
+ _type = packetType;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_INFO.writeId(packet);
+
+ final ElementalSpirit[] spirits = _player.getSpirits();
+ if (spirits == null)
+ {
+ packet.writeC(0);
+ packet.writeC(0);
+ packet.writeC(0);
+ return true;
+ }
+
+ packet.writeC(_type); // show spirit info window 1; Change type 2; Only update 0
+ packet.writeC(_spiritType);
+
+ packet.writeC(spirits.length); // spirit count
+
+ for (ElementalSpirit spirit : spirits)
+ {
+ packet.writeC(spirit.getType());
+ packet.writeC(0x01); // spirit active ?
+ // if active
+ writeSpiritInfo(packet, spirit);
+ }
+
+ packet.writeD(1); // Reset talent items count
+ for (int j = 0; j < 1; j++)
+ {
+ packet.writeD(57);
+ packet.writeQ(50000);
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritSetTalent.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritSetTalent.java
new file mode 100644
index 0000000000..dc19193137
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ElementalSpiritSetTalent.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author JoeAlisson
+ */
+public class ElementalSpiritSetTalent extends UpdateElementalSpiritPacket
+{
+ public ElementalSpiritSetTalent(PlayerInstance player, byte type, boolean result)
+ {
+ super(player, type, result);
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_SET_TALENT.writeId(packet);
+ writeUpdate(packet);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ExElementalSpiritGetExp.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ExElementalSpiritGetExp.java
new file mode 100644
index 0000000000..27a9046b12
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/ExElementalSpiritGetExp.java
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author JoeAlisson
+ */
+public class ExElementalSpiritGetExp implements IClientOutgoingPacket
+{
+ private final long _experience;
+ private final byte _type;
+
+ public ExElementalSpiritGetExp(byte type, long experience)
+ {
+ _type = type;
+ _experience = experience;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_ELEMENTAL_SPIRIT_GET_EXP.writeId(packet);
+
+ packet.writeC(_type);
+ packet.writeQ(_experience);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/UpdateElementalSpiritPacket.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/UpdateElementalSpiritPacket.java
new file mode 100644
index 0000000000..d97a364a6e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/elementalspirits/UpdateElementalSpiritPacket.java
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.elementalspirits;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.enums.ElementalType;
+import org.l2jmobius.gameserver.model.ElementalSpirit;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+
+/**
+ * @author JoeAlisson
+ */
+public abstract class UpdateElementalSpiritPacket extends AbstractElementalSpiritPacket
+{
+ private final PlayerInstance _player;
+ private final byte _type;
+ private final boolean _update;
+
+ UpdateElementalSpiritPacket(PlayerInstance player, byte type, boolean update)
+ {
+ _player = player;
+ _type = type;
+ _update = update;
+ }
+
+ protected void writeUpdate(PacketWriter packet)
+ {
+ packet.writeC(_update ? 1 : 0);
+ packet.writeC(_type);
+
+ if (_update)
+ {
+ final ElementalSpirit spirit = _player.getElementalSpirit(ElementalType.of(_type));
+ if (spirit == null)
+ {
+ return;
+ }
+
+ packet.writeC(_type);
+ writeSpiritInfo(packet, spirit);
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/readme.txt b/L2J_Mobius_Classic_2.4_SecretOfEmpire/readme.txt
index 9bcfa5b657..55a9959cef 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/readme.txt
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/readme.txt
@@ -79,6 +79,7 @@ Seven Signs: https://eu.4gameforum.com/threads/658543/
-Parsed new NPCs from client
-Updated skiltrees and skills from L2Wiki
-Updated experience values from L2Wiki
+-Elemental Spirits
-Land of Winds spawns
-Goddard territory spawns
-Goddard clanhalls