Переглянути джерело

BETA: '''Buffs'''/'''Debuffs''' now support empty effect list (before they were not being added on buff list)
* Removed `BigHead` effect its not needed any more now its handled by '''abnormalVisualEffect'''.
* Implemented 3 new effect scopes pveEffects, pvpEffects, endEffects.
* '''pveEffects''' will be activated when skill is casted from a player to a monster.
* '''pvpEffects''' will be activated when skill is casted from a player to a player.
* '''endEffects''' will be activated when buff is removed (supports only instant effects).
* Added a new effect `CallSkill`.
* Replaced `ChanceSkillTrigger` effect in some skills with new `CallSkill` effect.

Reviewed by: !UnAfraid, Adry_85

Nos 11 роки тому
батько
коміт
5ac65f9b50

+ 11 - 10
L2J_Server_BETA/java/com/l2jserver/gameserver/engines/DocumentBase.java

@@ -119,6 +119,7 @@ import com.l2jserver.gameserver.model.interfaces.IIdentifiable;
 import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.type.L2ArmorType;
 import com.l2jserver.gameserver.model.items.type.L2WeaponType;
+import com.l2jserver.gameserver.model.skills.EffectScope;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.funcs.FuncTemplate;
 import com.l2jserver.gameserver.model.skills.funcs.Lambda;
@@ -182,10 +183,10 @@ public abstract class DocumentBase
 	
 	protected void parseTemplate(Node n, Object template)
 	{
-		parseTemplate(n, template, false);
+		parseTemplate(n, template, null);
 	}
 	
-	protected void parseTemplate(Node n, Object template, boolean isChanneling)
+	protected void parseTemplate(Node n, Object template, EffectScope effectScope)
 	{
 		Condition condition = null;
 		n = n.getFirstChild();
@@ -257,7 +258,7 @@ public abstract class DocumentBase
 				{
 					throw new RuntimeException("Nested effects");
 				}
-				attachEffect(n, template, condition, isChanneling);
+				attachEffect(n, template, condition, effectScope);
 			}
 		}
 	}
@@ -297,10 +298,10 @@ public abstract class DocumentBase
 	
 	protected void attachEffect(Node n, Object template, Condition attachCond)
 	{
-		attachEffect(n, template, attachCond, false);
+		attachEffect(n, template, attachCond, null);
 	}
 	
-	protected void attachEffect(Node n, Object template, Condition attachCond, boolean isChanneling)
+	protected void attachEffect(Node n, Object template, Condition attachCond, EffectScope effectScope)
 	{
 		final NamedNodeMap attrs = n.getAttributes();
 		final StatsSet set = new StatsSet();
@@ -327,21 +328,21 @@ public abstract class DocumentBase
 		else if (template instanceof L2Skill)
 		{
 			final L2Skill skill = (L2Skill) template;
-			if (isChanneling)
+			if (effectScope != null)
 			{
-				skill.attachChanneling(effect);
+				skill.addEffect(effectScope, effect);
 			}
 			else if (set.getInt("self", 0) == 1)
 			{
-				skill.attachSelf(effect);
+				skill.addEffect(EffectScope.SELF, effect);
 			}
 			else if (skill.isPassive())
 			{
-				skill.attachPassive(effect);
+				skill.addEffect(EffectScope.PASSIVE, effect);
 			}
 			else
 			{
-				skill.attach(effect);
+				skill.addEffect(EffectScope.GENERAL, effect);
 			}
 		}
 	}

+ 319 - 17
L2J_Server_BETA/java/com/l2jserver/gameserver/engines/skills/DocumentSkill.java

@@ -32,6 +32,7 @@ import com.l2jserver.gameserver.datatables.EnchantSkillGroupsData;
 import com.l2jserver.gameserver.engines.DocumentBase;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.conditions.Condition;
+import com.l2jserver.gameserver.model.skills.EffectScope;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.L2SkillType;
 
@@ -504,14 +505,27 @@ public class DocumentSkill extends DocumentBase
 				}
 				else if ("channelingEffects".equalsIgnoreCase(n.getNodeName()))
 				{
-					parseTemplate(n, _currentSkill.currentSkills.get(i), true);
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+				}
+				else if ("pveEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+				}
+				else if ("pvpEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+				}
+				else if ("endEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
 				}
 			}
 		}
+		
 		for (int i = lastLvl; i < (lastLvl + enchantLevels1); i++)
 		{
 			_currentSkill.currentLevel = i - lastLvl;
-			boolean foundCond = false, foundFor = false;
+			boolean foundCond = false, foundFor = false, foundChannelingEffects = false, foundPveEffects = false, foundPvpEffects = false, foundEndEffects = false;
 			for (n = first; n != null; n = n.getNextSibling())
 			{
 				if ("enchant1cond".equalsIgnoreCase(n.getNodeName()))
@@ -530,9 +544,29 @@ public class DocumentSkill extends DocumentBase
 					foundFor = true;
 					parseTemplate(n, _currentSkill.currentSkills.get(i));
 				}
+				else if ("enchant1channelingEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundChannelingEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+				}
+				else if ("enchant1pveEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPveEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+				}
+				else if ("enchant1pvpEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPvpEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+				}
+				else if ("enchant1endEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundEndEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+				}
 			}
 			// If none found, the enchanted skill will take effects from maxLvL of norm skill
-			if (!foundCond || !foundFor)
+			if (!foundCond || !foundFor || !foundChannelingEffects || !foundPveEffects || !foundPvpEffects || !foundEndEffects)
 			{
 				_currentSkill.currentLevel = lastLvl - 1;
 				for (n = first; n != null; n = n.getNextSibling())
@@ -551,12 +585,28 @@ public class DocumentSkill extends DocumentBase
 					{
 						parseTemplate(n, _currentSkill.currentSkills.get(i));
 					}
+					else if (!foundChannelingEffects && "channelingEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+					}
+					else if (!foundPveEffects && "pveEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+					}
+					else if (!foundPvpEffects && "pvpEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+					}
+					else if (!foundEndEffects && "endEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+					}
 				}
 			}
 		}
 		for (int i = lastLvl + enchantLevels1; i < (lastLvl + enchantLevels1 + enchantLevels2); i++)
 		{
-			boolean foundCond = false, foundFor = false;
+			boolean foundCond = false, foundFor = false, foundChannelingEffects = false, foundPveEffects = false, foundPvpEffects = false, foundEndEffects = false;
 			_currentSkill.currentLevel = i - lastLvl - enchantLevels1;
 			for (n = first; n != null; n = n.getNextSibling())
 			{
@@ -576,9 +626,29 @@ public class DocumentSkill extends DocumentBase
 					foundFor = true;
 					parseTemplate(n, _currentSkill.currentSkills.get(i));
 				}
+				else if ("enchant2channelingEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundChannelingEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+				}
+				else if ("enchant2pveEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPveEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+				}
+				else if ("enchant2pvpEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPvpEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+				}
+				else if ("enchant2endEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundEndEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+				}
 			}
 			// If none found, the enchanted skill will take effects from maxLvL of norm skill
-			if (!foundCond || !foundFor)
+			if (!foundCond || !foundFor || !foundChannelingEffects || !foundPveEffects || !foundPvpEffects || !foundEndEffects)
 			{
 				_currentSkill.currentLevel = lastLvl - 1;
 				for (n = first; n != null; n = n.getNextSibling())
@@ -597,12 +667,28 @@ public class DocumentSkill extends DocumentBase
 					{
 						parseTemplate(n, _currentSkill.currentSkills.get(i));
 					}
+					else if (!foundChannelingEffects && "channelingEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+					}
+					else if (!foundPveEffects && "pveEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+					}
+					else if (!foundPvpEffects && "pvpEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+					}
+					else if (!foundEndEffects && "endEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+					}
 				}
 			}
 		}
 		for (int i = lastLvl + enchantLevels1 + enchantLevels2; i < (lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3); i++)
 		{
-			boolean foundCond = false, foundFor = false;
+			boolean foundCond = false, foundFor = false, foundChannelingEffects = false, foundPveEffects = false, foundPvpEffects = false, foundEndEffects = false;
 			_currentSkill.currentLevel = i - lastLvl - enchantLevels1 - enchantLevels2;
 			for (n = first; n != null; n = n.getNextSibling())
 			{
@@ -622,9 +708,29 @@ public class DocumentSkill extends DocumentBase
 					foundFor = true;
 					parseTemplate(n, _currentSkill.currentSkills.get(i));
 				}
+				else if ("enchant3channelingEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundChannelingEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+				}
+				else if ("enchant3pveEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPveEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+				}
+				else if ("enchant3pvpEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPvpEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+				}
+				else if ("enchant3endEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundEndEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+				}
 			}
 			// If none found, the enchanted skill will take effects from maxLvL of norm skill
-			if (!foundCond || !foundFor)
+			if (!foundCond || !foundFor || !foundChannelingEffects || !foundPveEffects || !foundPvpEffects || !foundEndEffects)
 			{
 				_currentSkill.currentLevel = lastLvl - 1;
 				for (n = first; n != null; n = n.getNextSibling())
@@ -643,12 +749,28 @@ public class DocumentSkill extends DocumentBase
 					{
 						parseTemplate(n, _currentSkill.currentSkills.get(i));
 					}
+					else if (!foundChannelingEffects && "channelingEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+					}
+					else if (!foundPveEffects && "pveEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+					}
+					else if (!foundPvpEffects && "pvpEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+					}
+					else if (!foundEndEffects && "endEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+					}
 				}
 			}
 		}
 		for (int i = lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3; i < (lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3 + enchantLevels4); i++)
 		{
-			boolean foundCond = false, foundFor = false;
+			boolean foundCond = false, foundFor = false, foundChannelingEffects = false, foundPveEffects = false, foundPvpEffects = false, foundEndEffects = false;
 			_currentSkill.currentLevel = i - lastLvl - enchantLevels1 - enchantLevels2 - enchantLevels3;
 			for (n = first; n != null; n = n.getNextSibling())
 			{
@@ -668,9 +790,29 @@ public class DocumentSkill extends DocumentBase
 					foundFor = true;
 					parseTemplate(n, _currentSkill.currentSkills.get(i));
 				}
+				else if ("enchant4channelingEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundChannelingEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+				}
+				else if ("enchant4pveEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPveEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+				}
+				else if ("enchant4pvpEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPvpEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+				}
+				else if ("enchant4endEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundEndEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+				}
 			}
 			// If none found, the enchanted skill will take effects from maxLvL of norm skill
-			if (!foundCond || !foundFor)
+			if (!foundCond || !foundFor || !foundChannelingEffects || !foundPveEffects || !foundPvpEffects || !foundEndEffects)
 			{
 				_currentSkill.currentLevel = lastLvl - 1;
 				for (n = first; n != null; n = n.getNextSibling())
@@ -689,12 +831,28 @@ public class DocumentSkill extends DocumentBase
 					{
 						parseTemplate(n, _currentSkill.currentSkills.get(i));
 					}
+					else if (!foundChannelingEffects && "channelingEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+					}
+					else if (!foundPveEffects && "pveEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+					}
+					else if (!foundPvpEffects && "pvpEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+					}
+					else if (!foundEndEffects && "endEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+					}
 				}
 			}
 		}
 		for (int i = lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3 + enchantLevels4; i < (lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3 + enchantLevels4 + enchantLevels5); i++)
 		{
-			boolean foundCond = false, foundFor = false;
+			boolean foundCond = false, foundFor = false, foundChannelingEffects = false, foundPveEffects = false, foundPvpEffects = false, foundEndEffects = false;
 			_currentSkill.currentLevel = i - lastLvl - enchantLevels1 - enchantLevels2 - enchantLevels3 - enchantLevels4;
 			for (n = first; n != null; n = n.getNextSibling())
 			{
@@ -714,9 +872,29 @@ public class DocumentSkill extends DocumentBase
 					foundFor = true;
 					parseTemplate(n, _currentSkill.currentSkills.get(i));
 				}
+				else if ("enchant5channelingEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundChannelingEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+				}
+				else if ("enchant5pveEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPveEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+				}
+				else if ("enchant5pvpEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPvpEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+				}
+				else if ("enchant5endEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundEndEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+				}
 			}
 			// If none found, the enchanted skill will take effects from maxLvL of norm skill
-			if (!foundCond || !foundFor)
+			if (!foundCond || !foundFor || !foundChannelingEffects || !foundPveEffects || !foundPvpEffects || !foundEndEffects)
 			{
 				_currentSkill.currentLevel = lastLvl - 1;
 				for (n = first; n != null; n = n.getNextSibling())
@@ -735,12 +913,28 @@ public class DocumentSkill extends DocumentBase
 					{
 						parseTemplate(n, _currentSkill.currentSkills.get(i));
 					}
+					else if (!foundChannelingEffects && "channelingEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+					}
+					else if (!foundPveEffects && "pveEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+					}
+					else if (!foundPvpEffects && "pvpEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+					}
+					else if (!foundEndEffects && "endEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+					}
 				}
 			}
 		}
 		for (int i = lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3 + enchantLevels4 + enchantLevels5; i < (lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3 + enchantLevels4 + enchantLevels5 + enchantLevels6); i++)
 		{
-			boolean foundCond = false, foundFor = false;
+			boolean foundCond = false, foundFor = false, foundChannelingEffects = false, foundPveEffects = false, foundPvpEffects = false, foundEndEffects = false;
 			_currentSkill.currentLevel = i - lastLvl - enchantLevels1 - enchantLevels2 - enchantLevels3 - enchantLevels4 - enchantLevels5;
 			for (n = first; n != null; n = n.getNextSibling())
 			{
@@ -760,9 +954,29 @@ public class DocumentSkill extends DocumentBase
 					foundFor = true;
 					parseTemplate(n, _currentSkill.currentSkills.get(i));
 				}
+				else if ("enchant6channelingEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundChannelingEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+				}
+				else if ("enchant6pveEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPveEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+				}
+				else if ("enchant6pvpEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPvpEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+				}
+				else if ("enchant6endEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundEndEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+				}
 			}
 			// If none found, the enchanted skill will take effects from maxLvL of norm skill
-			if (!foundCond || !foundFor)
+			if (!foundCond || !foundFor || !foundChannelingEffects || !foundPveEffects || !foundPvpEffects || !foundEndEffects)
 			{
 				_currentSkill.currentLevel = lastLvl - 1;
 				for (n = first; n != null; n = n.getNextSibling())
@@ -781,12 +995,28 @@ public class DocumentSkill extends DocumentBase
 					{
 						parseTemplate(n, _currentSkill.currentSkills.get(i));
 					}
+					else if (!foundChannelingEffects && "channelingEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+					}
+					else if (!foundPveEffects && "pveEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+					}
+					else if (!foundPvpEffects && "pvpEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+					}
+					else if (!foundEndEffects && "endEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+					}
 				}
 			}
 		}
 		for (int i = lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3 + enchantLevels4 + enchantLevels5 + enchantLevels6; i < (lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3 + enchantLevels4 + enchantLevels5 + enchantLevels6 + enchantLevels7); i++)
 		{
-			boolean foundCond = false, foundFor = false;
+			boolean foundCond = false, foundFor = false, foundChannelingEffects = false, foundPveEffects = false, foundPvpEffects = false, foundEndEffects = false;
 			_currentSkill.currentLevel = i - lastLvl - enchantLevels1 - enchantLevels2 - enchantLevels3 - enchantLevels4 - enchantLevels5 - enchantLevels6;
 			for (n = first; n != null; n = n.getNextSibling())
 			{
@@ -806,9 +1036,29 @@ public class DocumentSkill extends DocumentBase
 					foundFor = true;
 					parseTemplate(n, _currentSkill.currentSkills.get(i));
 				}
+				else if ("enchant7channelingEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundChannelingEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+				}
+				else if ("enchant7pveEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPveEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+				}
+				else if ("enchant7pvpEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPvpEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+				}
+				else if ("enchant7endEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundEndEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+				}
 			}
 			// If none found, the enchanted skill will take effects from maxLvL of norm skill
-			if (!foundCond || !foundFor)
+			if (!foundCond || !foundFor || !foundChannelingEffects || !foundPveEffects || !foundPvpEffects || !foundEndEffects)
 			{
 				_currentSkill.currentLevel = lastLvl - 1;
 				for (n = first; n != null; n = n.getNextSibling())
@@ -827,12 +1077,28 @@ public class DocumentSkill extends DocumentBase
 					{
 						parseTemplate(n, _currentSkill.currentSkills.get(i));
 					}
+					else if (!foundChannelingEffects && "channelingEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+					}
+					else if (!foundPveEffects && "pveEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+					}
+					else if (!foundPvpEffects && "pvpEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+					}
+					else if (!foundEndEffects && "endEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+					}
 				}
 			}
 		}
 		for (int i = lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3 + enchantLevels4 + enchantLevels5 + enchantLevels6 + enchantLevels7; i < (lastLvl + enchantLevels1 + enchantLevels2 + enchantLevels3 + enchantLevels4 + enchantLevels5 + enchantLevels6 + enchantLevels7 + enchantLevels8); i++)
 		{
-			boolean foundCond = false, foundFor = false;
+			boolean foundCond = false, foundFor = false, foundChannelingEffects = false, foundPveEffects = false, foundPvpEffects = false, foundEndEffects = false;
 			_currentSkill.currentLevel = i - lastLvl - enchantLevels1 - enchantLevels2 - enchantLevels3 - enchantLevels4 - enchantLevels5 - enchantLevels6 - enchantLevels7;
 			for (n = first; n != null; n = n.getNextSibling())
 			{
@@ -852,9 +1118,29 @@ public class DocumentSkill extends DocumentBase
 					foundFor = true;
 					parseTemplate(n, _currentSkill.currentSkills.get(i));
 				}
+				else if ("enchant8channelingEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundChannelingEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+				}
+				else if ("enchant8pveEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPveEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+				}
+				else if ("enchant8pvpEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundPvpEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+				}
+				else if ("enchant8endEffects".equalsIgnoreCase(n.getNodeName()))
+				{
+					foundEndEffects = true;
+					parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+				}
 			}
 			// If none found, the enchanted skill will take effects from maxLvL of norm skill
-			if (!foundCond || !foundFor)
+			if (!foundCond || !foundFor || !foundChannelingEffects || !foundPveEffects || !foundPvpEffects || !foundEndEffects)
 			{
 				_currentSkill.currentLevel = lastLvl - 1;
 				for (n = first; n != null; n = n.getNextSibling())
@@ -873,6 +1159,22 @@ public class DocumentSkill extends DocumentBase
 					{
 						parseTemplate(n, _currentSkill.currentSkills.get(i));
 					}
+					else if (!foundChannelingEffects && "channelingEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.CHANNELING);
+					}
+					else if (!foundPveEffects && "pveEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVE);
+					}
+					else if (!foundPvpEffects && "pvpEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.PVP);
+					}
+					else if (!foundEndEffects && "endEffects".equalsIgnoreCase(n.getNodeName()))
+					{
+						parseTemplate(n, _currentSkill.currentSkills.get(i), EffectScope.END);
+					}
 				}
 			}
 		}

+ 4 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/CharEffectList.java

@@ -43,6 +43,7 @@ import com.l2jserver.gameserver.model.olympiad.OlympiadGameManager;
 import com.l2jserver.gameserver.model.olympiad.OlympiadGameTask;
 import com.l2jserver.gameserver.model.skills.AbnormalType;
 import com.l2jserver.gameserver.model.skills.BuffInfo;
+import com.l2jserver.gameserver.model.skills.EffectScope;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.network.serverpackets.AbnormalStatusUpdate;
 import com.l2jserver.gameserver.network.serverpackets.ExOlympiadSpelledInfo;
@@ -640,6 +641,8 @@ public final class CharEffectList
 				}
 			}
 		}
+		
+		info.getSkill().applyEffectScope(EffectScope.END, info, true, false);
 	}
 	
 	/**
@@ -1352,7 +1355,7 @@ public final class CharEffectList
 	 */
 	public void add(BuffInfo info)
 	{
-		if ((info == null) || info.getEffects().isEmpty())
+		if (info == null)
 		{
 			return;
 		}

+ 2 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PetInstance.java

@@ -67,6 +67,7 @@ import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
 import com.l2jserver.gameserver.model.items.type.L2EtcItemType;
 import com.l2jserver.gameserver.model.skills.AbnormalType;
 import com.l2jserver.gameserver.model.skills.BuffInfo;
+import com.l2jserver.gameserver.model.skills.EffectScope;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.zone.ZoneId;
 import com.l2jserver.gameserver.network.SystemMessageId;
@@ -1150,7 +1151,7 @@ public class L2PetInstance extends L2Summon
 							continue;
 						}
 						
-						if (skill.hasEffects())
+						if (skill.hasEffects(EffectScope.GENERAL))
 						{
 							if (!SummonEffectsTable.getInstance().getPetEffects().contains(getControlObjectId()))
 							{

+ 2 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2ServitorInstance.java

@@ -42,6 +42,7 @@ import com.l2jserver.gameserver.model.actor.L2Summon;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
 import com.l2jserver.gameserver.model.skills.AbnormalType;
 import com.l2jserver.gameserver.model.skills.BuffInfo;
+import com.l2jserver.gameserver.model.skills.EffectScope;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.l2skills.L2SkillSummon;
 import com.l2jserver.gameserver.network.serverpackets.SetSummonRemainTime;
@@ -467,7 +468,7 @@ public class L2ServitorInstance extends L2Summon
 								continue;
 							}
 							
-							if (skill.hasEffects())
+							if (skill.hasEffects(EffectScope.GENERAL))
 							{
 								if (!SummonEffectsTable.getInstance().getServitorEffectsOwner().contains(getOwner().getObjectId()))
 								{

+ 33 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/EffectScope.java

@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004-2013 L2J Server
+ * 
+ * This file is part of L2J Server.
+ * 
+ * L2J Server 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.
+ * 
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.model.skills;
+
+/**
+ * @author Nos
+ */
+public enum EffectScope
+{
+	GENERAL,
+	SELF,
+	PASSIVE,
+	CHANNELING,
+	PVP,
+	PVE,
+	END
+}

+ 58 - 154
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/L2Skill.java

@@ -21,6 +21,7 @@ package com.l2jserver.gameserver.model.skills;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.EnumMap;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -193,11 +194,8 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 	private List<Condition> _itemPreCondition;
 	// Function lists
 	private List<FuncTemplate> _funcTemplates;
-	// Effect lists
-	private List<AbstractEffect> _effects;
-	private List<AbstractEffect> _effectSelf;
-	private List<AbstractEffect> _effectPassive;
-	private List<AbstractEffect> _effectChanneling;
+	
+	private final EnumMap<EffectScope, List<AbstractEffect>> _effectLists = new EnumMap<>(EffectScope.class);
 	
 	protected ChanceCondition _chanceCondition = null;
 	
@@ -1280,39 +1278,42 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		return funcs;
 	}
 	
-	public boolean hasEffects()
-	{
-		return (_effects != null) && !_effects.isEmpty();
-	}
-	
-	public List<AbstractEffect> getEffectTemplates()
-	{
-		return _effects;
-	}
-	
-	public boolean hasPassiveEffects()
-	{
-		return (_effectPassive != null) && !_effectPassive.isEmpty();
-	}
-	
-	public List<AbstractEffect> getEffectTemplatesPassive()
-	{
-		return _effectPassive;
-	}
-	
-	public List<AbstractEffect> getEffectTemplateChanneling()
+	public List<AbstractEffect> getEffects(EffectScope effectScope)
 	{
-		return _effectChanneling;
+		return _effectLists.get(effectScope);
 	}
 	
-	public boolean hasSelfEffects()
+	public boolean hasEffects(EffectScope effectScope)
 	{
-		return (_effectSelf != null) && !_effectSelf.isEmpty();
+		List<AbstractEffect> effects = _effectLists.get(effectScope);
+		return (effects != null) && !effects.isEmpty();
 	}
 	
-	public boolean hasChannelingEffects()
+	public void applyEffectScope(EffectScope effectScope, BuffInfo info, boolean applyInstantEffects, boolean addContinuousEffects)
 	{
-		return (_effectChanneling != null) && !_effectChanneling.isEmpty();
+		if ((effectScope != null) && hasEffects(effectScope))
+		{
+			for (AbstractEffect effect : getEffects(effectScope))
+			{
+				if (effect != null)
+				{
+					if (effect.isInstant())
+					{
+						if (applyInstantEffects && effect.calcSuccess(info))
+						{
+							effect.onStart(info);
+						}
+					}
+					else if (addContinuousEffects)
+					{
+						if (effect.canStart(info))
+						{
+							info.addEffect(effect);
+						}
+					}
+				}
+			}
+		}
 	}
 	
 	/**
@@ -1370,7 +1371,7 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		env.setTarget(effected);
 		env.setSkill(this);
 		final boolean addContinuousEffects = !passive && (_operateType.isToggle() || (_operateType.isContinuous() && Formulas.calcEffectSuccess(env)));
-		if (!self && !passive && hasEffects())
+		if (!self && !passive)
 		{
 			final BuffInfo info = new BuffInfo(env);
 			if (addContinuousEffects && (abnormalTime > 0))
@@ -1378,27 +1379,17 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 				info.setAbnormalTime(abnormalTime);
 			}
 			
-			for (AbstractEffect effect : _effects)
+			applyEffectScope(EffectScope.GENERAL, info, instant, addContinuousEffects);
+			
+			EffectScope pvpOrPveEffectScope = effector.isPlayable() && effected.isL2Attackable() ? EffectScope.PVE : effector.isPlayable() && effected.isPlayable() ? EffectScope.PVP : null;
+			applyEffectScope(pvpOrPveEffectScope, info, instant, addContinuousEffects);
+			
+			applyEffectScope(EffectScope.CHANNELING, info, instant, addContinuousEffects);
+			
+			if (addContinuousEffects)
 			{
-				if (effect != null)
-				{
-					if (effect.isInstant())
-					{
-						if (instant && effect.calcSuccess(info))
-						{
-							effect.onStart(info);
-						}
-					}
-					else if (addContinuousEffects)
-					{
-						if (effect.canStart(info))
-						{
-							info.addEffect(effect);
-						}
-					}
-				}
+				effected.getEffectList().add(info);
 			}
-			effected.getEffectList().add(info);
 			
 			// Support for buff sharing feature.
 			if (addContinuousEffects && effected.isPlayer() && effected.hasServitor() && isContinuous() && !isDebuff())
@@ -1407,7 +1398,7 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 			}
 		}
 		
-		if (self && hasSelfEffects())
+		if (self)
 		{
 			env.setTarget(effector);
 			final BuffInfo info = new BuffInfo(env);
@@ -1416,27 +1407,12 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 				info.setAbnormalTime(abnormalTime);
 			}
 			
-			for (AbstractEffect effect : _effectSelf)
+			applyEffectScope(EffectScope.SELF, info, instant, addContinuousEffects);
+			
+			if (addContinuousEffects)
 			{
-				if (effect != null)
-				{
-					if (effect.isInstant())
-					{
-						if (instant && effect.calcSuccess(info))
-						{
-							effect.onStart(info);
-						}
-					}
-					else if (addContinuousEffects)
-					{
-						if (effect.canStart(info))
-						{
-							info.addEffect(effect);
-						}
-					}
-				}
+				effector.getEffectList().add(info);
 			}
-			effector.getEffectList().add(info);
 			
 			// Support for buff sharing feature.
 			// Avoiding Servitor Share since it's implementation already "shares" the effect.
@@ -1446,60 +1422,13 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 			}
 		}
 		
-		if (passive && hasPassiveEffects())
+		if (passive)
 		{
 			env.setTarget(effector);
 			final BuffInfo info = new BuffInfo(env);
-			for (AbstractEffect effect : _effectPassive)
-			{
-				if (effect != null)
-				{
-					if (effect.canStart(info))
-					{
-						info.addEffect(effect);
-					}
-				}
-			}
+			applyEffectScope(EffectScope.PASSIVE, info, false, true);
 			effector.getEffectList().add(info);
 		}
-		
-		if (!self && !passive && hasChannelingEffects())
-		{
-			env.setTarget(effected);
-			final BuffInfo info = new BuffInfo(env);
-			if (addContinuousEffects && (abnormalTime > 0))
-			{
-				info.setAbnormalTime(abnormalTime);
-			}
-			
-			for (AbstractEffect effect : _effectChanneling)
-			{
-				if (effect != null)
-				{
-					if (effect.isInstant())
-					{
-						if (instant && effect.calcSuccess(info))
-						{
-							effect.onStart(info);
-						}
-					}
-					else if (addContinuousEffects)
-					{
-						if (effect.canStart(info))
-						{
-							info.addEffect(effect);
-						}
-					}
-				}
-			}
-			effector.getEffectList().add(info);
-			
-			// Support for buff sharing feature.
-			if (addContinuousEffects && effected.isPlayer() && effected.hasServitor() && isContinuous() && !isDebuff())
-			{
-				applyEffects(effector, effected.getSummon(), false, 0);
-			}
-		}
 	}
 	
 	public final void attach(FuncTemplate f)
@@ -1511,40 +1440,15 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		_funcTemplates.add(f);
 	}
 	
-	public final void attach(AbstractEffect effect)
-	{
-		if (_effects == null)
-		{
-			_effects = new ArrayList<>(1);
-		}
-		_effects.add(effect);
-	}
-	
-	public final void attachSelf(AbstractEffect effect)
-	{
-		if (_effectSelf == null)
-		{
-			_effectSelf = new ArrayList<>(1);
-		}
-		_effectSelf.add(effect);
-	}
-	
-	public final void attachPassive(AbstractEffect effect)
-	{
-		if (_effectPassive == null)
-		{
-			_effectPassive = new ArrayList<>(1);
-		}
-		_effectPassive.add(effect);
-	}
-	
-	public final void attachChanneling(AbstractEffect effectTemplate)
+	public final void addEffect(EffectScope effectScope, AbstractEffect effect)
 	{
-		if (_effectChanneling == null)
+		List<AbstractEffect> effects = _effectLists.get(effectScope);
+		if (effects == null)
 		{
-			_effectChanneling = new ArrayList<>(1);
+			effects = new ArrayList<>(1);
+			_effectLists.put(effectScope, effects);
 		}
-		_effectChanneling.add(effectTemplate);
+		effects.add(effect);
 	}
 	
 	public final void attach(Condition c, boolean itemOrWeapon)
@@ -1801,17 +1705,17 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 	 */
 	public boolean hasEffectType(L2EffectType... types)
 	{
-		if (hasEffects() && (types != null) && (types.length > 0))
+		if (hasEffects(EffectScope.GENERAL) && (types != null) && (types.length > 0))
 		{
 			if (_effectTypes == null)
 			{
-				_effectTypes = new byte[_effects.size()];
+				_effectTypes = new byte[getEffects(EffectScope.GENERAL).size()];
 				
 				final Env env = new Env();
 				env.setSkill(this);
 				
 				int i = 0;
-				for (AbstractEffect effect : _effects)
+				for (AbstractEffect effect : getEffects(EffectScope.GENERAL))
 				{
 					if (effect == null)
 					{