Selaa lähdekoodia

BETA: Skill and effect system complete rework:
* Renamed `L2Effect` to `AbstractEffect`.
* No more dynamic creation of effects (Huge performance and memory boost!).
* Removed all traces or reflection on run time!
* Removed `EffectTemplate`, merged with `AbstractEffect`.
* Reworked and externalized all the logic from `AbstractEffect` that handled effect ticking.
* Reviewed all "over time" skills:
* `Flag` effect does not have ticks and doesn't need onActionTime() defined.
* '''Fixed DOT (damage over time), MDOT (mana damage over time), HOT (heal over time), MHOT (mana heal over time) skills.'''
* Reported by: Tavo22, Snip
* `FakeDeath` effect should only last forever (or while conditions are met) if it's a toggle skill.
* `Relax` effect should only last forever (or while conditions are met) if it's a toggle skill.
* Removed `EffectState` enumerated and the nasty switch associated to it!
* Removed "lambda" support from effects, the default attribute `val` is now double.
* Removed val="0", now `val`'s default value is zero, no need to declare it explicitely.
* '''Removed noicon attribute from effects, icon is not related to effects, but to the skill.''
* Renamed `AbnormalEffect` enumerated to `AbnormalVisualEffect`.
* Removed `EffectDurationHolder` DTO.
* Removed getFirstEffect(int), skills can be stoped by skill ID or `AbnormalType`.
* Reworked (again) `CharEffectList`:
* Using maps as underlying implementation, '''reduced drastically iterations''' (Hash tables offer 0(1) in most operations).
* Using Javolution's `FastMap`, due Java lacks a default implementation that is ordered by insert order, thread-safe and concurrent safe.
* Separated all kind of skills into buffs, triggers, dances, debuffs, passive.
* Using Double-locked checking, useless instantiation of maps is avoided.
* Improved buff counting operations (no more iterations over every effect every time you get a new one to know if you reached maximum count).
* Removed getEffects() and all temporary list/map creations.
* '''Reworked the way buffs are inserted preventing iterations and correcting exceptions while finding the correct index to insert the buff.'''
* Reworked `Formulas`#calcEffectAbnormalTime(Env env)
* Fixed `L2CubicInstance`#useCubic<Skill Type>(..), this methods are not static, then they don't need to recieve a `L2CubicInstance` as parameter.
* Implemented `BuffInfo`, modeled from retail's implementation with minor changes to fit our implementation.
* Complex DTO that holds all the information for a given buff (or debuff or dance/song) set of effects issued by an skill.
* Controls the logic of the buffs.
* Removed a few of `L2EffectType`.
* Improved a bit `L2BabyPetInstance` skill casting related logic, reduced iterations and simplified the code.
* Implemented `EffectTaskInfo`, DTO to hold the effect task (Maybe this will change later).
* Implemented `EffectTickTask` runnable task to control ticking logic.
* Removed "after effect" implementation, totally useless.
* Suggested by: UnAfraid
* Removed all the `L2Skill`#getEffects(..) methods replaced with L2Skill#applyEffects(..).
* Moved "can be stolen" logic to `L2Skill`, it isn't related to the effect, but to the skill.
* Added "Refresh" button on admin panel to check buffs easily.
* Added admin command "admin_getbuff_ps" to check effects from passive skills.
* Improved performance in `DispelBySlot` and `DispelBySlotProbability` effects.
* Fixed minor typo in `DispelBySlot` and `DispelBySlotProbability` effects, there are values over `Byte.MAX_VALUE`.
* '''Added retail support for Herbs, when a lesser buff is replaced by an herb, it becomes inactive, but it's timer continues, when the Herb buff finishes if the lesser buff has time it becomes active untill completes it's time.'''
* Time does not pause, it just continues in the background.
* Effects does not stack.
* Reported by: Nos
* '''Fixed Herbs, they shouldn't display gauge bar (casting bar) upon usage.'''
* Reported by: Nos
* '''Fixed Herbs not removing lesser effect icon, leading to players belive that buffs stack...'''
* Reported by: Tavo22, evets, u3games, pandragon
* '''Fixing instant effects being added to the effect list, and removing buffs present on the list.'''
* Reported by: Tavo22
* '''Fixed "Short Buff" slot (slot for healing potions).'''
* Statified reset packet (reduced object creation, a lot!).
* Removed task to reset `ShortBuffStatusUpdate`, let's use buff ending task for that.
* Moved logic to `CharEffectList` instead of `L2PcInstance` + `ItemSkillsTemplate`.
* Reported by: JMD, Gries, Cresceus
* Fixed `StealAbnormal` effect logic and `Formulas`#calcCancelStealEffects(..).
* Improved buffs doesn't stack anymore with normal (lesser) buffs.
* Now all effects are excecuted including instant effects (if they are successfuly applied).
* Reported by: Adry_85
* `BlockChat` effect shouldn't be instant!
* Fixed system messages related to skills (success, fail, removal, ending).
* Improved `AdminBuffs`, more information is displayed:
* Blocked abnormal skill types (if any)
* Total buff count.
* Hidden buff count.
* Inactive effects (in red)
* Skill level next to the name.
* '''Rewritten''' `EffectMasterHandler` '''to avoid reflection where it's useless.'''
* Since `L2EffectType` is scheduled to be removed:
* `AbstractEffect`#getEffectType() is not abstract anymore, now returns L2EffectType.NONE by default.
* '''Fixing debuffs working on "white players" with control.'''
* Patch by: nBd (minor changes by Zoey76)
* Reported by: plasan, jungla56, St3eT, Tavo22, Konstantinos, pandragon
* '''Fixed exploit on restore summon feature that allows players to dupe summons.'''
* Unhardcoding `canSummon` condition.
* Reported by: Janiko
* '''Fixed Arcane Shield getting stuck after being stolen.'''
* Reported by: valanths1990, nBd, freestyler, Gries
* '''Fixed triggered skills that got stacked within the same ID and different level.'''
* Reported by: nBd, lucan, blacksea, Gries

Tested by: Nos, Captain, Janiko, Konstantinos, Lucan, UnAfraid, Zoey76

'''Note to developers 1:''' Instant effects shouldn't override onExit(!BuffInfo).
'''Note to developers 2:''' Is not required to call super.onStart() or super.onExit() to add/remove abnormal visual effects anymore, it's done on an indepent method.
'''Note to developers 3:''' Do not add "steal constructor", such thing is not required anymore.

Zoey76 11 vuotta sitten
vanhempi
sitoutus
5d0366705f
77 muutettua tiedostoa jossa 2818 lisäystä ja 2326 poistoa
  1. 0 4
      L2J_Server_BETA/dist/game/config/Character.properties
  2. 0 5
      L2J_Server_BETA/java/com/l2jserver/Config.java
  3. 16 16
      L2J_Server_BETA/java/com/l2jserver/gameserver/ai/L2AttackableAI.java
  4. 9 21
      L2J_Server_BETA/java/com/l2jserver/gameserver/ai/L2CharacterAI.java
  5. 8 19
      L2J_Server_BETA/java/com/l2jserver/gameserver/ai/L2FortSiegeGuardAI.java
  6. 8 19
      L2J_Server_BETA/java/com/l2jserver/gameserver/ai/L2SiegeGuardAI.java
  7. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/BotReportTable.java
  8. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/BuyListData.java
  9. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/CategoryData.java
  10. 0 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/CharSummonTable.java
  11. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/CrestTable.java
  12. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/SkillLearnData.java
  13. 6 7
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/SkillTable.java
  14. 1 8
      L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/SummonEffectsTable.java
  15. 19 14
      L2J_Server_BETA/java/com/l2jserver/gameserver/engines/DocumentBase.java
  16. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/enums/IllegalActionPunishmentType.java
  17. 6 6
      L2J_Server_BETA/java/com/l2jserver/gameserver/handler/EffectHandler.java
  18. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/instancemanager/DuelManager.java
  19. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/instancemanager/PetitionManager.java
  20. 5 7
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/ChanceSkillList.java
  21. 859 260
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/CharEffectList.java
  22. 50 116
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Character.java
  23. 11 26
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2BabyPetInstance.java
  24. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2CastleMagicianInstance.java
  25. 3 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2ChestInstance.java
  26. 24 43
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2CubicInstance.java
  27. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2NpcBufferInstance.java
  28. 236 154
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
  29. 32 33
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PetInstance.java
  30. 5 4
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2SepulcherMonsterInstance.java
  31. 32 33
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2ServitorInstance.java
  32. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2TamedBeastInstance.java
  33. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2TeleporterInstance.java
  34. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/status/PcStatus.java
  35. 15 14
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/tasks/cubics/CubicAction.java
  36. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/buylist/Product.java
  37. 3 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/conditions/ConditionPlayerActiveEffectId.java
  38. 71 0
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/conditions/ConditionPlayerCanSummon.java
  39. 3 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/conditions/ConditionTargetActiveEffectId.java
  40. 363 0
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/AbstractEffect.java
  41. 22 5
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/EffectTaskInfo.java
  42. 0 260
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/EffectTemplate.java
  43. 78 0
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/EffectTickTask.java
  44. 0 720
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/L2Effect.java
  45. 0 4
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/L2EffectType.java
  46. 3 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/BlockCheckerEngine.java
  47. 7 7
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/Duel.java
  48. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/TvTEvent.java
  49. 19 24
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/L2Item.java
  50. 9 18
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/L2Weapon.java
  51. 12 13
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/AbnormalVisualEffect.java
  52. 470 0
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/BuffInfo.java
  53. 25 13
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/BuffTimeTask.java
  54. 168 225
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/L2Skill.java
  55. 5 7
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/SkillChannelizer.java
  56. 0 18
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/stats/Env.java
  57. 52 58
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/stats/Formulas.java
  58. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/zone/type/L2AbnormalZone.java
  59. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/zone/type/L2DynamicZone.java
  60. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/zone/type/L2EffectZone.java
  61. 5 5
      L2J_Server_BETA/java/com/l2jserver/gameserver/model/zone/type/L2SiegeZone.java
  62. 3 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/SystemMessageId.java
  63. 14 11
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/Action.java
  64. 14 7
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/Attack.java
  65. 14 11
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/AttackRequest.java
  66. 14 6
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestActionUse.java
  67. 1 1
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/Say2.java
  68. 27 13
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/TradeRequest.java
  69. 12 16
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/AbnormalStatusUpdate.java
  70. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/AbstractNpcInfo.java
  71. 3 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/CharInfo.java
  72. 3 3
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/ConfirmDlg.java
  73. 11 9
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/ExOlympiadSpelledInfo.java
  74. 11 9
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/PartySpelled.java
  75. 2 0
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/ShortBuffStatusUpdate.java
  76. 0 6
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/SystemMessage.java
  77. 2 2
      L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/UserInfo.java

+ 0 - 4
L2J_Server_BETA/dist/game/config/Character.properties

@@ -113,10 +113,6 @@ AutoLearnDivineInspiration = False
 # Default: cast
 AltGameCancelByHit = cast
 
-# If True, when effects of the same stack group are used, lesser effects will be canceled if stronger effects are used. Otherwise stacking of things like multiple levels of the same buff will be allowed.
-# Default: True
-CancelLesserEffect = True
-
 # This option, if enabled, will allow magic to fail, and if disabled magic damage will always succeed with a 100% chance.
 # Default: True
 MagicFailures = True

+ 0 - 5
L2J_Server_BETA/java/com/l2jserver/Config.java

@@ -132,7 +132,6 @@ public final class Config
 	public static boolean AUTO_LEARN_DIVINE_INSPIRATION;
 	public static boolean ALT_GAME_CANCEL_BOW;
 	public static boolean ALT_GAME_CANCEL_CAST;
-	public static boolean EFFECT_CANCELING;
 	public static boolean ALT_GAME_MAGICFAILURES;
 	public static int PLAYER_FAKEDEATH_UP_PROTECTION;
 	public static boolean STORE_SKILL_COOLTIME;
@@ -1526,7 +1525,6 @@ public final class Config
 			AUTO_LEARN_DIVINE_INSPIRATION = Character.getBoolean("AutoLearnDivineInspiration", false);
 			ALT_GAME_CANCEL_BOW = Character.getString("AltGameCancelByHit", "Cast").equalsIgnoreCase("bow") || Character.getString("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");
 			ALT_GAME_CANCEL_CAST = Character.getString("AltGameCancelByHit", "Cast").equalsIgnoreCase("cast") || Character.getString("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");
-			EFFECT_CANCELING = Character.getBoolean("CancelLesserEffect", true);
 			ALT_GAME_MAGICFAILURES = Character.getBoolean("MagicFailures", true);
 			PLAYER_FAKEDEATH_UP_PROTECTION = Character.getInt("PlayerFakeDeathUpProtection", 0);
 			STORE_SKILL_COOLTIME = Character.getBoolean("StoreSkillCooltime", true);
@@ -3255,9 +3253,6 @@ public final class Config
 			case "guardattackaggromob":
 				GUARD_ATTACK_AGGRO_MOB = Boolean.parseBoolean(pValue);
 				break;
-			case "cancellessereffect":
-				EFFECT_CANCELING = Boolean.parseBoolean(pValue);
-				break;
 			case "maximumslotsfornodwarf":
 				INVENTORY_MAXIMUM_NO_DWARF = Integer.parseInt(pValue);
 				break;

+ 16 - 16
L2J_Server_BETA/java/com/l2jserver/gameserver/ai/L2AttackableAI.java

@@ -1395,7 +1395,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 		{
 			case BUFF:
 			{
-				if (caster.getFirstEffect(sk) == null)
+				if (!caster.isAffectedBySkill(sk.getId()))
 				{
 					clientStopMoving(null);
 					// L2Object target = attackTarget;
@@ -1438,7 +1438,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 			{
 				if (GeoData.getInstance().canSeeTarget(caster, attackTarget) && !canAOE(sk) && !attackTarget.isDead() && (dist2 <= srange))
 				{
-					if (attackTarget.getFirstEffect(sk) == null)
+					if (!attackTarget.isAffectedBySkill(sk.getId()))
 					{
 						clientStopMoving(null);
 						caster.doCast(sk);
@@ -1478,7 +1478,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				{
 					if (sk.getTargetType() == L2TargetType.ONE)
 					{
-						if ((attackTarget.getFirstEffect(L2EffectType.BUFF) != null) && GeoData.getInstance().canSeeTarget(caster, attackTarget) && !attackTarget.isDead() && (dist2 <= srange))
+						if ((attackTarget.getEffectList().getFirstEffect(L2EffectType.BUFF) != null) && GeoData.getInstance().canSeeTarget(caster, attackTarget) && !attackTarget.isDead() && (dist2 <= srange))
 						{
 							clientStopMoving(null);
 							caster.doCast(sk);
@@ -1630,7 +1630,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						{
 							if ((dist2 > range) || attackTarget.isMoving())
 							{
-								if (attackTarget.getFirstEffect(sk) == null)
+								if (!attackTarget.isAffectedBySkill(sk.getId()))
 								{
 									clientStopMoving(null);
 									caster.doCast(sk);
@@ -1668,7 +1668,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				{
 					if (GeoData.getInstance().canSeeTarget(caster, attackTarget) && !canAOE(sk) && (dist2 <= srange))
 					{
-						if (attackTarget.getFirstEffect(sk) == null)
+						if (!attackTarget.isAffectedBySkill(sk.getId()))
 						{
 							clientStopMoving(null);
 							caster.doCast(sk);
@@ -1706,7 +1706,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				{
 					if (GeoData.getInstance().canSeeTarget(caster, attackTarget) && !canAOE(sk) && !attackTarget.isDead() && (dist2 <= srange))
 					{
-						if (attackTarget.getFirstEffect(sk) == null)
+						if (!attackTarget.isAffectedBySkill(sk.getId()))
 						{
 							clientStopMoving(null);
 							caster.doCast(sk);
@@ -1888,7 +1888,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						{
 							continue;
 						}
-						if (getAttackTarget().getFirstEffect(sk) == null)
+						if (!getAttackTarget().isAffectedBySkill(sk.getId()))
 						{
 							clientStopMoving(null);
 							// L2Object target = getAttackTarget();
@@ -1913,7 +1913,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						{
 							continue;
 						}
-						if (getAttackTarget().getFirstEffect(sk) == null)
+						if (!getAttackTarget().isAffectedBySkill(sk.getId()))
 						{
 							clientStopMoving(null);
 							// L2Object target = getAttackTarget();
@@ -1937,7 +1937,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						{
 							continue;
 						}
-						if (getAttackTarget().getFirstEffect(sk) == null)
+						if (!getAttackTarget().isAffectedBySkill(sk.getId()))
 						{
 							clientStopMoving(null);
 							// L2Object target = getAttackTarget();
@@ -1962,7 +1962,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						{
 							continue;
 						}
-						if (getAttackTarget().getFirstEffect(L2EffectType.BUFF) != null)
+						if (getAttackTarget().getEffectList().getFirstEffect(L2EffectType.BUFF) != null)
 						{
 							clientStopMoving(null);
 							// L2Object target = getAttackTarget();
@@ -2123,7 +2123,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 					}
 					if (dist2 <= range)
 					{
-						if (getAttackTarget().getFirstEffect(sk) == null)
+						if (!getAttackTarget().isAffectedBySkill(sk.getId()))
 						{
 							return obj;
 						}
@@ -2159,7 +2159,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						{
 							if (dist2 <= range)
 							{
-								if (getAttackTarget().getFirstEffect(sk) == null)
+								if (!getAttackTarget().isAffectedBySkill(sk.getId()))
 								{
 									return obj;
 								}
@@ -2170,7 +2170,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 					{
 						if (dist2 <= range)
 						{
-							if (getAttackTarget().getFirstEffect(sk) == null)
+							if (!getAttackTarget().isAffectedBySkill(sk.getId()))
 							{
 								return obj;
 							}
@@ -2213,7 +2213,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 					}
 					if (dist2 <= range)
 					{
-						if (obj.getFirstEffect(sk) == null)
+						if (!obj.isAffectedBySkill(sk.getId()))
 						{
 							return obj;
 						}
@@ -2254,7 +2254,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 					{
 						if (dist2 <= range)
 						{
-							if (getAttackTarget().getFirstEffect(L2EffectType.BUFF) != null)
+							if (getAttackTarget().getEffectList().getFirstEffect(L2EffectType.BUFF) != null)
 							{
 								return obj;
 							}
@@ -2266,7 +2266,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 					
 					if (dist2 <= range)
 					{
-						if (getAttackTarget().getFirstEffect(L2EffectType.BUFF) != null)
+						if (getAttackTarget().getEffectList().getFirstEffect(L2EffectType.BUFF) != null)
 						{
 							return obj;
 						}

+ 9 - 21
L2J_Server_BETA/java/com/l2jserver/gameserver/ai/L2CharacterAI.java

@@ -48,7 +48,6 @@ import com.l2jserver.gameserver.model.actor.L2Playable;
 import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.interfaces.ILocational;
 import com.l2jserver.gameserver.model.items.L2Weapon;
@@ -1500,13 +1499,9 @@ public class L2CharacterAI extends AbstractAI
 						}
 					}
 					
-					for (L2Effect effect : target.getAllEffects())
+					if (target.isAffectedBySkill(sk.getId()))
 					{
-						if (effect.getSkill() == sk)
-						{
-							cancast = false;
-							break;
-						}
+						cancast = false;
 					}
 				}
 				if (cancast)
@@ -1533,7 +1528,7 @@ public class L2CharacterAI extends AbstractAI
 						}
 					}
 					
-					if (!target.getAllEffects().isEmpty())
+					if (!target.getEffectList().isEmpty())
 					{
 						cancast = true;
 					}
@@ -1565,7 +1560,7 @@ public class L2CharacterAI extends AbstractAI
 						}
 					}
 					
-					if (!target.getAllEffects().isEmpty())
+					if (!target.getEffectList().isEmpty())
 					{
 						cancast = true;
 					}
@@ -1584,6 +1579,7 @@ public class L2CharacterAI extends AbstractAI
 					{
 						continue;
 					}
+					
 					if (target instanceof L2Attackable)
 					{
 						L2Npc targets = ((L2Npc) target);
@@ -1594,13 +1590,9 @@ public class L2CharacterAI extends AbstractAI
 						}
 					}
 					
-					for (L2Effect effect : target.getAllEffects())
+					if (target.isAffectedBySkill(sk.getId()))
 					{
-						if (effect.getSkill() == sk)
-						{
-							cancast = false;
-							break;
-						}
+						cancast = false;
 					}
 				}
 				if (cancast)
@@ -1629,13 +1621,9 @@ public class L2CharacterAI extends AbstractAI
 				if ((actors.getFactionId() != null) && targets.getFactionId().equals(actors.getFactionId()))
 				{
 					count++;
-					for (L2Effect effect : target.getAllEffects())
+					if (target.isAffectedBySkill(sk.getId()))
 					{
-						if (effect.getSkill() == sk)
-						{
-							ccount++;
-							break;
-						}
+						ccount++;
 					}
 				}
 			}

+ 8 - 19
L2J_Server_BETA/java/com/l2jserver/gameserver/ai/L2FortSiegeGuardAI.java

@@ -41,7 +41,6 @@ import com.l2jserver.gameserver.model.actor.instance.L2FortBallistaInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2FortCommanderInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2NpcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.L2SkillType;
@@ -619,17 +618,12 @@ public class L2FortSiegeGuardAI extends L2CharacterAI implements Runnable
 							useSkillSelf = false;
 							break;
 						}
-						if (sk.getSkillType() == L2SkillType.BUFF)
+						
+						if ((sk.getSkillType() == L2SkillType.BUFF) && _actor.isAffectedBySkill(sk.getId()))
 						{
-							for (L2Effect effect : _actor.getAllEffects())
-							{
-								if (effect.getSkill() == sk)
-								{
-									useSkillSelf = false;
-									break;
-								}
-							}
+							useSkillSelf = false;
 						}
+						
 						if (useSkillSelf)
 						{
 							_actor.setTarget(_actor);
@@ -769,17 +763,12 @@ public class L2FortSiegeGuardAI extends L2CharacterAI implements Runnable
 								useSkillSelf = false;
 								break;
 							}
-							if (sk.getSkillType() == L2SkillType.BUFF)
+							
+							if ((sk.getSkillType() == L2SkillType.BUFF) && _actor.isAffectedBySkill(sk.getId()))
 							{
-								for (L2Effect effect : _actor.getAllEffects())
-								{
-									if (effect.getSkill() == sk)
-									{
-										useSkillSelf = false;
-										break;
-									}
-								}
+								useSkillSelf = false;
 							}
+							
 							if (useSkillSelf)
 							{
 								_actor.setTarget(_actor);

+ 8 - 19
L2J_Server_BETA/java/com/l2jserver/gameserver/ai/L2SiegeGuardAI.java

@@ -39,7 +39,6 @@ import com.l2jserver.gameserver.model.actor.instance.L2DefenderInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2NpcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.L2SkillType;
@@ -591,17 +590,12 @@ public class L2SiegeGuardAI extends L2CharacterAI implements Runnable
 							useSkillSelf = false;
 							break;
 						}
-						if (sk.getSkillType() == L2SkillType.BUFF)
+						
+						if ((sk.getSkillType() == L2SkillType.BUFF) && _actor.isAffectedBySkill(sk.getId()))
 						{
-							for (L2Effect effect : _actor.getAllEffects())
-							{
-								if (effect.getSkill() == sk)
-								{
-									useSkillSelf = false;
-									break;
-								}
-							}
+							useSkillSelf = false;
 						}
+						
 						if (useSkillSelf)
 						{
 							_actor.setTarget(_actor);
@@ -737,17 +731,12 @@ public class L2SiegeGuardAI extends L2CharacterAI implements Runnable
 								useSkillSelf = false;
 								break;
 							}
-							if (sk.getSkillType() == L2SkillType.BUFF)
+							
+							if ((sk.getSkillType() == L2SkillType.BUFF) && _actor.isAffectedBySkill(sk.getId()))
 							{
-								for (L2Effect effect : _actor.getAllEffects())
-								{
-									if (effect.getSkill() == sk)
-									{
-										useSkillSelf = false;
-										break;
-									}
-								}
+								useSkillSelf = false;
 							}
+							
 							if (useSkillSelf)
 							{
 								_actor.setTarget(_actor);

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/BotReportTable.java

@@ -344,7 +344,7 @@ public final class BotReportTable
 	{
 		if (ph != null)
 		{
-			ph._punish.getEffects(bot, bot);
+			ph._punish.applyEffects(bot, null, bot, null, false, false);
 			if (ph._systemMessageId > -1)
 			{
 				SystemMessageId id = SystemMessageId.getSystemMessageId(ph._systemMessageId);

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/BuyListData.java

@@ -178,6 +178,6 @@ public final class BuyListData extends DocumentParser
 	
 	private static class SingletonHolder
 	{
-		protected final static BuyListData _instance = new BuyListData();
+		protected static final BuyListData _instance = new BuyListData();
 	}
 }

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/CategoryData.java

@@ -121,6 +121,6 @@ public final class CategoryData extends DocumentParser
 	
 	private static class SingletonHolder
 	{
-		protected final static CategoryData _instance = new CategoryData();
+		protected static final CategoryData _instance = new CategoryData();
 	}
 }

+ 0 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/CharSummonTable.java

@@ -195,7 +195,6 @@ public class CharSummonTable
 			ps.setInt(2, skillId);
 			try (ResultSet rs = ps.executeQuery())
 			{
-				
 				L2NpcTemplate summonTemplate;
 				L2ServitorInstance summon;
 				L2SkillSummon skill;

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/CrestTable.java

@@ -45,7 +45,7 @@ import com.l2jserver.util.file.filter.BMPFilter;
  */
 public final class CrestTable
 {
-	private final static Logger _log = Logger.getLogger(CrestTable.class.getName());
+	private static final Logger _log = Logger.getLogger(CrestTable.class.getName());
 	
 	private final Map<Integer, L2Crest> _crests = new ConcurrentHashMap<>();
 	private final AtomicInteger _nextId = new AtomicInteger(1);

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/SkillLearnData.java

@@ -95,6 +95,6 @@ public final class SkillLearnData extends DocumentParser
 	
 	private static class SingletonHolder
 	{
-		protected final static SkillLearnData _instance = new SkillLearnData();
+		protected static final SkillLearnData _instance = new SkillLearnData();
 	}
 }

+ 6 - 7
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/SkillTable.java

@@ -32,9 +32,9 @@ import gnu.trove.list.array.TIntArrayList;
 import gnu.trove.map.hash.TIntIntHashMap;
 
 /**
- * 
+ * Skill table.
  */
-public class SkillTable
+public final class SkillTable
 {
 	private static Logger _log = Logger.getLogger(SkillTable.class.getName());
 	
@@ -60,7 +60,7 @@ public class SkillTable
 		DocumentEngine.getInstance().loadAllSkills(_skills);
 		
 		_skillMaxLevel.clear();
-		for (final L2Skill skill : _skills.values())
+		for (L2Skill skill : _skills.values())
 		{
 			final int skillId = skill.getId();
 			final int skillLvl = skill.getLevel();
@@ -106,7 +106,7 @@ public class SkillTable
 		return (skillId * 1021) + skillLevel;
 	}
 	
-	public final L2Skill getInfo(final int skillId, final int level)
+	public L2Skill getInfo(int skillId, int level)
 	{
 		final L2Skill result = _skills.get(getSkillHashCode(skillId, level));
 		if (result != null)
@@ -130,12 +130,12 @@ public class SkillTable
 		return null;
 	}
 	
-	public final int getMaxLevel(final int skillId)
+	public int getMaxLevel(int skillId)
 	{
 		return _skillMaxLevel.get(skillId);
 	}
 	
-	public final boolean isEnchantable(final int skillId)
+	public boolean isEnchantable(int skillId)
 	{
 		return _enchantable.binarySearch(skillId) >= 0;
 	}
@@ -176,7 +176,6 @@ public class SkillTable
 		BUILD_HEADQUARTERS(247, 1),
 		WYVERN_BREATH(4289, 1),
 		STRIDER_SIEGE_ASSAULT(325, 1),
-		FAKE_PETRIFICATION(4616, 1),
 		FIREWORK(5965, 1),
 		LARGE_FIREWORK(2025, 1),
 		BLESSING_OF_PROTECTION(5182, 1),

+ 1 - 8
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/SummonEffectsTable.java

@@ -63,13 +63,11 @@ public class SummonEffectsTable
 	public class SummonEffect
 	{
 		L2Skill _skill;
-		int _effectCount;
 		int _effectCurTime;
 		
-		public SummonEffect(L2Skill skill, int effectCount, int effectCurTime)
+		public SummonEffect(L2Skill skill, int effectCurTime)
 		{
 			_skill = skill;
-			_effectCount = effectCount;
 			_effectCurTime = effectCurTime;
 		}
 		
@@ -78,11 +76,6 @@ public class SummonEffectsTable
 			return _skill;
 		}
 		
-		public int getEffectCount()
-		{
-			return _effectCount;
-		}
-		
 		public int getEffectCurTime()
 		{
 			return _effectCurTime;

+ 19 - 14
L2J_Server_BETA/java/com/l2jserver/gameserver/engines/DocumentBase.java

@@ -55,6 +55,7 @@ import com.l2jserver.gameserver.model.conditions.ConditionPlayerCallPc;
 import com.l2jserver.gameserver.model.conditions.ConditionPlayerCanEscape;
 import com.l2jserver.gameserver.model.conditions.ConditionPlayerCanPossessHolything;
 import com.l2jserver.gameserver.model.conditions.ConditionPlayerCanRefuelAirship;
+import com.l2jserver.gameserver.model.conditions.ConditionPlayerCanSummon;
 import com.l2jserver.gameserver.model.conditions.ConditionPlayerCanSweep;
 import com.l2jserver.gameserver.model.conditions.ConditionPlayerCanTransform;
 import com.l2jserver.gameserver.model.conditions.ConditionPlayerCanUntransform;
@@ -113,7 +114,7 @@ import com.l2jserver.gameserver.model.conditions.ConditionTargetWeight;
 import com.l2jserver.gameserver.model.conditions.ConditionUsingItemType;
 import com.l2jserver.gameserver.model.conditions.ConditionUsingSkill;
 import com.l2jserver.gameserver.model.conditions.ConditionWithSkill;
-import com.l2jserver.gameserver.model.effects.EffectTemplate;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
 import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.type.L2ArmorType;
 import com.l2jserver.gameserver.model.items.type.L2WeaponType;
@@ -251,7 +252,7 @@ public abstract class DocumentBase
 			}
 			else if ("effect".equalsIgnoreCase(n.getNodeName()))
 			{
-				if (template instanceof EffectTemplate)
+				if (template instanceof AbstractEffect)
 				{
 					throw new RuntimeException("Nested effects");
 				}
@@ -276,9 +277,9 @@ public abstract class DocumentBase
 		{
 			((L2Skill) template).attach(ft);
 		}
-		else if (template instanceof EffectTemplate)
+		else if (template instanceof AbstractEffect)
 		{
-			((EffectTemplate) template).attach(ft);
+			((AbstractEffect) template).attach(ft);
 		}
 	}
 	
@@ -309,32 +310,32 @@ public abstract class DocumentBase
 		}
 		
 		final StatsSet parameters = parseParameters(n.getFirstChild(), template);
-		final Lambda lambda = getLambda(n, template);
 		final Condition applayCond = parseCondition(n.getFirstChild(), template);
-		final EffectTemplate effectTemplate = new EffectTemplate(attachCond, applayCond, lambda, set, parameters);
-		parseTemplate(n, effectTemplate);
+		
+		final AbstractEffect effect = AbstractEffect.createEffect(attachCond, applayCond, set, parameters);
+		parseTemplate(n, effect);
 		if (template instanceof L2Item)
 		{
-			((L2Item) template).attach(effectTemplate);
+			((L2Item) template).attach(effect);
 		}
 		else if (template instanceof L2Skill)
 		{
-			final L2Skill sk = (L2Skill) template;
+			final L2Skill skill = (L2Skill) template;
 			if (isChanneling)
 			{
-				sk.attachChanneling(effectTemplate);
+				skill.attachChanneling(effect);
 			}
 			else if (set.getInt("self", 0) == 1)
 			{
-				sk.attachSelf(effectTemplate);
+				skill.attachSelf(effect);
 			}
-			else if (sk.isPassive())
+			else if (skill.isPassive())
 			{
-				sk.attachPassive(effectTemplate);
+				skill.attachPassive(effect);
 			}
 			else
 			{
-				sk.attach(effectTemplate);
+				skill.attach(effect);
 			}
 		}
 	}
@@ -785,6 +786,10 @@ public abstract class DocumentBase
 			{
 				cond = joinAnd(cond, new ConditionPlayerCanRefuelAirship(Integer.parseInt(a.getNodeValue())));
 			}
+			else if ("canSummon".equalsIgnoreCase(a.getNodeName()))
+			{
+				cond = joinAnd(cond, new ConditionPlayerCanSummon(Boolean.parseBoolean(a.getNodeValue())));
+			}
 			else if ("canSweep".equalsIgnoreCase(a.getNodeName()))
 			{
 				cond = joinAnd(cond, new ConditionPlayerCanSweep(Boolean.parseBoolean(a.getNodeValue())));

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/enums/IllegalActionPunishmentType.java

@@ -30,7 +30,7 @@ public enum IllegalActionPunishmentType
 	KICKBAN,
 	JAIL;
 	
-	public final static IllegalActionPunishmentType findByName(String name)
+	public static final IllegalActionPunishmentType findByName(String name)
 	{
 		for (IllegalActionPunishmentType type : values())
 		{
@@ -39,6 +39,6 @@ public enum IllegalActionPunishmentType
 				return type;
 			}
 		}
-		return null;
+		return NONE;
 	}
 }

+ 6 - 6
L2J_Server_BETA/java/com/l2jserver/gameserver/handler/EffectHandler.java

@@ -22,15 +22,15 @@ import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
 
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
 import com.l2jserver.gameserver.scripting.L2ScriptEngineManager;
 
 /**
  * @author BiggBoss, UnAfraid
  */
-public final class EffectHandler implements IHandler<Class<? extends L2Effect>, String>
+public final class EffectHandler implements IHandler<Class<? extends AbstractEffect>, String>
 {
-	private final Map<String, Class<? extends L2Effect>> _handlers;
+	private final Map<String, Class<? extends AbstractEffect>> _handlers;
 	
 	protected EffectHandler()
 	{
@@ -38,19 +38,19 @@ public final class EffectHandler implements IHandler<Class<? extends L2Effect>,
 	}
 	
 	@Override
-	public void registerHandler(Class<? extends L2Effect> handler)
+	public void registerHandler(Class<? extends AbstractEffect> handler)
 	{
 		_handlers.put(handler.getSimpleName(), handler);
 	}
 	
 	@Override
-	public synchronized void removeHandler(Class<? extends L2Effect> handler)
+	public synchronized void removeHandler(Class<? extends AbstractEffect> handler)
 	{
 		_handlers.remove(handler.getSimpleName());
 	}
 	
 	@Override
-	public final Class<? extends L2Effect> getHandler(String name)
+	public Class<? extends AbstractEffect> getHandler(String name)
 	{
 		return _handlers.get(name);
 	}

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/instancemanager/DuelManager.java

@@ -23,8 +23,8 @@ import java.util.List;
 import javolution.util.FastList;
 
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.entity.Duel;
+import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
 
 public final class DuelManager
@@ -155,7 +155,7 @@ public final class DuelManager
 	 * @param player
 	 * @param buff
 	 */
-	public void onBuff(L2PcInstance player, L2Effect buff)
+	public void onBuff(L2PcInstance player, L2Skill buff)
 	{
 		if ((player == null) || !player.isInDuel() || (buff == null))
 		{

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/instancemanager/PetitionManager.java

@@ -461,7 +461,7 @@ public final class PetitionManager
 	 * Gets the single instance of {@code PetitionManager}.
 	 * @return single instance of {@code PetitionManager}
 	 */
-	public final static PetitionManager getInstance()
+	public static final PetitionManager getInstance()
 	{
 		return SingletonHolder._instance;
 	}

+ 5 - 7
L2J_Server_BETA/java/com/l2jserver/gameserver/model/ChanceSkillList.java

@@ -28,10 +28,9 @@ import com.l2jserver.gameserver.handler.ISkillHandler;
 import com.l2jserver.gameserver.handler.SkillHandler;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Playable;
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
 import com.l2jserver.gameserver.model.interfaces.IChanceSkillTrigger;
 import com.l2jserver.gameserver.model.skills.L2Skill;
-import com.l2jserver.gameserver.model.skills.L2SkillType;
 import com.l2jserver.gameserver.model.skills.targets.L2TargetType;
 import com.l2jserver.gameserver.network.serverpackets.MagicSkillLaunched;
 import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
@@ -49,7 +48,6 @@ public class ChanceSkillList extends FastMap<IChanceSkillTrigger, ChanceConditio
 	
 	public ChanceSkillList(L2Character owner)
 	{
-		super();
 		shared();
 		_owner = owner;
 	}
@@ -147,13 +145,13 @@ public class ChanceSkillList extends FastMap<IChanceSkillTrigger, ChanceConditio
 				}
 				else
 				{
-					makeCast((L2Effect) e.getKey(), target);
+					makeCast((AbstractEffect) e.getKey(), target);
 				}
 			}
 		}
 	}
 	
-	private void makeCast(L2Effect effect, L2Character target)
+	private void makeCast(AbstractEffect effect, L2Character target)
 	{
 		try
 		{
@@ -168,8 +166,8 @@ public class ChanceSkillList extends FastMap<IChanceSkillTrigger, ChanceConditio
 				return;
 			}
 			
-			final L2Character caster = triggered.getTargetType() == L2TargetType.SELF ? _owner : effect.getEffector();
-			if ((caster == null) || (triggered.getSkillType() == L2SkillType.NOTDONE) || caster.isSkillDisabled(triggered))
+			final L2Character caster = triggered.getTargetType() == L2TargetType.SELF ? _owner : target;
+			if ((caster == null) || caster.isSkillDisabled(triggered))
 			{
 				return;
 			}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 859 - 260
L2J_Server_BETA/java/com/l2jserver/gameserver/model/CharEffectList.java


+ 50 - 116
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Character.java

@@ -84,9 +84,8 @@ import com.l2jserver.gameserver.model.actor.tasks.character.UsePotionTask;
 import com.l2jserver.gameserver.model.actor.templates.L2CharTemplate;
 import com.l2jserver.gameserver.model.actor.transform.Transform;
 import com.l2jserver.gameserver.model.actor.transform.TransformTemplate;
-import com.l2jserver.gameserver.model.effects.AbnormalEffect;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
 import com.l2jserver.gameserver.model.effects.EffectFlag;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.entity.Instance;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
@@ -104,6 +103,9 @@ import com.l2jserver.gameserver.model.items.type.L2WeaponType;
 import com.l2jserver.gameserver.model.options.OptionsSkillHolder;
 import com.l2jserver.gameserver.model.options.OptionsSkillType;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.skills.AbnormalType;
+import com.l2jserver.gameserver.model.skills.AbnormalVisualEffect;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.L2SkillType;
 import com.l2jserver.gameserver.model.skills.SkillChannelized;
@@ -1924,7 +1926,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 		if (skillTime > 0)
 		{
 			// Send a Server->Client packet SetupGauge with the color of the gauge and the casting time
-			if (isPlayer())
+			if (isPlayer() && !simultaneously)
 			{
 				sendPacket(new SetupGauge(SetupGauge.BLUE, skillTime));
 			}
@@ -2874,7 +2876,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 	 * Active abnormal effects flags in the binary mask and send Server->Client UserInfo/CharInfo packet.
 	 * @param mask
 	 */
-	public final void startAbnormalEffect(AbnormalEffect mask)
+	public final void startAbnormalEffect(AbnormalVisualEffect mask)
 	{
 		_AbnormalEffects |= mask.getMask();
 		updateAbnormalEffect();
@@ -2884,9 +2886,9 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 	 * Active special effects flags in the binary mask and send Server->Client UserInfo/CharInfo packet.
 	 * @param mask
 	 */
-	public final void startSpecialEffect(AbnormalEffect[] mask)
+	public final void startSpecialEffect(AbnormalVisualEffect[] mask)
 	{
-		for (AbnormalEffect special : mask)
+		for (AbnormalVisualEffect special : mask)
 		{
 			_SpecialEffects |= special.getMask();
 		}
@@ -2960,7 +2962,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 	 * Modify the abnormal effect map according to the mask.
 	 * @param mask
 	 */
-	public final void stopAbnormalEffect(AbnormalEffect mask)
+	public final void stopAbnormalEffect(AbnormalVisualEffect mask)
 	{
 		_AbnormalEffects &= ~mask.getMask();
 		updateAbnormalEffect();
@@ -2970,9 +2972,9 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 	 * Modify the special effect map according to the mask.
 	 * @param mask
 	 */
-	public final void stopSpecialEffect(AbnormalEffect[] mask)
+	public final void stopSpecialEffect(AbnormalVisualEffect[] mask)
 	{
-		for (AbnormalEffect special : mask)
+		for (AbnormalVisualEffect special : mask)
 		{
 			_SpecialEffects &= ~special.getMask();
 		}
@@ -2999,13 +3001,16 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 		_effectList.stopAllEffects();
 	}
 	
+	/**
+	 * Stops all effects, except those that last through death.
+	 */
 	public void stopAllEffectsExceptThoseThatLastThroughDeath()
 	{
 		_effectList.stopAllEffectsExceptThoseThatLastThroughDeath();
 	}
 	
 	/**
-	 * Stop and remove the effects corresponding to the skill Id.
+	 * Stop and remove the effects corresponding to the skill ID.
 	 * @param removed if {@code true} the effect will be set as removed, and a system message will be sent
 	 * @param skillId the skill Id
 	 */
@@ -3014,19 +3019,6 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 		_effectList.stopSkillEffects(removed, skillId);
 	}
 	
-	/**
-	 * Stop and remove all L2Effect of the selected type (ex : BUFF, DMG_OVER_TIME...) from the L2Character and update client magic icon.<br>
-	 * <B><U>Concept</U>:</B><br>
-	 * All active skills effects in progress on the L2Character are identified in ConcurrentHashMap(Integer,L2Effect) <B>_effects</B>.<br>
-	 * The Integer key of _effects is the L2Skill Identifier that has created the L2Effect.<br>
-	 * <B><U>Actions</U>:</B>
-	 * <ul>
-	 * <li>Remove Func added by this effect from the L2Character Calculator (Stop L2Effect)</li>
-	 * <li>Remove the L2Effect from _effects of the L2Character</li>
-	 * <li>Update active skills in progress icons on player client</li>
-	 * </ul>
-	 * @param type The type of effect to stop ((ex : BUFF, DMG_OVER_TIME...)
-	 */
 	public final void stopEffects(L2EffectType type)
 	{
 		_effectList.stopEffects(type);
@@ -3120,7 +3112,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 	{
 		if (removeEffects)
 		{
-			stopEffects(L2EffectType.TRANSFORMATION);
+			getEffectList().stopSkillEffects(false, AbnormalType.TRANSFORM);
 		}
 		
 		// if this is a player instance, then untransform, also set the transform_id column equal to 0 if not cursed.
@@ -3175,31 +3167,31 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 		int ae = _AbnormalEffects;
 		if (!isFlying() && isStunned())
 		{
-			ae |= AbnormalEffect.STUN.getMask();
+			ae |= AbnormalVisualEffect.STUN.getMask();
 		}
 		if (!isFlying() && isRooted())
 		{
-			ae |= AbnormalEffect.ROOT.getMask();
+			ae |= AbnormalVisualEffect.ROOT.getMask();
 		}
 		if (isSleeping())
 		{
-			ae |= AbnormalEffect.SLEEP.getMask();
+			ae |= AbnormalVisualEffect.SLEEP.getMask();
 		}
 		if (isConfused())
 		{
-			ae |= AbnormalEffect.FEAR.getMask();
+			ae |= AbnormalVisualEffect.FEAR.getMask();
 		}
 		if (isMuted())
 		{
-			ae |= AbnormalEffect.MUTED.getMask();
+			ae |= AbnormalVisualEffect.MUTED.getMask();
 		}
 		if (isPhysicalMuted())
 		{
-			ae |= AbnormalEffect.MUTED.getMask();
+			ae |= AbnormalVisualEffect.MUTED.getMask();
 		}
 		if (isAfraid())
 		{
-			ae |= AbnormalEffect.SKULL_FEAR.getMask();
+			ae |= AbnormalVisualEffect.SKULL_FEAR.getMask();
 		}
 		return ae;
 	}
@@ -3218,59 +3210,18 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 		int se = _SpecialEffects;
 		if (isFlying() && isStunned())
 		{
-			se |= AbnormalEffect.S_AIR_STUN.getMask();
+			se |= AbnormalVisualEffect.S_AIR_STUN.getMask();
 		}
 		if (isFlying() && isRooted())
 		{
-			se |= AbnormalEffect.S_AIR_ROOT.getMask();
+			se |= AbnormalVisualEffect.S_AIR_ROOT.getMask();
 		}
 		return se;
 	}
 	
-	public final List<L2Effect> getAllEffects()
-	{
-		return _effectList.getAllEffects();
-	}
-	
-	/**
-	 * Return L2Effect in progress on the L2Character corresponding to the L2Skill Identifier.<br>
-	 * <B><U>Concept</U>:</B><br>
-	 * All active skills effects in progress on the L2Character are identified in <B>_effects</B>.
-	 * @param skillId The L2Skill Identifier of the L2Effect to return from the _effects
-	 * @return The L2Effect corresponding to the L2Skill Identifier
-	 */
-	public final L2Effect getFirstEffect(int skillId)
-	{
-		return _effectList.getFirstEffect(skillId);
-	}
-	
-	/**
-	 * Return the first L2Effect in progress on the L2Character created by the L2Skill.<br>
-	 * <B><U>Concept</U>:</B><br>
-	 * All active skills effects in progress on the L2Character are identified in <B>_effects</B>.
-	 * @param skill The L2Skill whose effect must be returned
-	 * @return The first L2Effect created by the L2Skill
-	 */
-	public final L2Effect getFirstEffect(L2Skill skill)
-	{
-		return _effectList.getFirstEffect(skill);
-	}
-	
-	/**
-	 * Return the first L2Effect in progress on the L2Character corresponding to the Effect Type (ex : BUFF, STUN, ROOT...).<br>
-	 * <B><U>Concept</U>:</B><br>
-	 * All active skills effects in progress on the L2Character are identified in <B>_effects</B>.
-	 * @param tp The Effect Type of skills whose effect must be returned
-	 * @return The first L2Effect corresponding to the Effect Type
-	 */
-	public final L2Effect getFirstEffect(L2EffectType tp)
-	{
-		return _effectList.getFirstEffect(tp);
-	}
-	
-	public final L2Effect getFirstPassiveEffect(L2EffectType type)
+	public boolean isAffectedBySkill(int skillId)
 	{
-		return _effectList.getFirstPassiveEffect(type);
+		return _effectList.isAffectedBySkill(skillId);
 	}
 	
 	// TODO: NEED TO ORGANIZE AND MOVE TO PROPER PLACE
@@ -3660,17 +3611,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 				}
 			}
 			
-			if (owner instanceof L2Effect)
-			{
-				if (!((L2Effect) owner).isPreventExitUpdate())
-				{
-					broadcastModifiedStats(modifiedStats);
-				}
-			}
-			else
-			{
-				broadcastModifiedStats(modifiedStats);
-			}
+			broadcastModifiedStats(modifiedStats);
 		}
 	}
 	
@@ -4868,7 +4809,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 					abortAttack();
 					abortCast();
 					getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
-					skill.getEffects(target, this);
+					skill.applyEffects(target, null, this, null, false, false);
 				}
 				else
 				{
@@ -5332,7 +5273,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 			{
 				addChanceTrigger(newSkill);
 			}
-			newSkill.getPassiveEffects(this);
+			newSkill.applyEffects(this, null, this, null, false, true);
 		}
 		return oldSkill;
 	}
@@ -5376,20 +5317,13 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 				}
 			}
 			
-			// Remove passive effects.
-			_effectList.removePassiveEffects(skillId);
-			
-			if (cancelEffect || oldSkill.isToggle())
+			// Stop effects.
+			if (cancelEffect || oldSkill.isToggle() || oldSkill.isPassive())
 			{
-				// for now, to support transformations, we have to let their
-				// effects stay when skill is removed
-				L2Effect e = getFirstEffect(oldSkill);
-				if ((e == null) || (e.getEffectType() != L2EffectType.TRANSFORMATION))
-				{
-					removeStatsOwner(oldSkill);
-					stopSkillEffects(true, oldSkill.getId());
-				}
+				removeStatsOwner(oldSkill);
+				stopSkillEffects(true, oldSkill.getId());
 			}
+			
 			if (isPlayer())
 			{
 				// TODO: Unhardcode it!
@@ -5706,17 +5640,9 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 			{
 				if (tgt.isPlayable())
 				{
-					L2Character target = (L2Character) tgt;
-					if (skill.getSkillType() == L2SkillType.BUFF)
-					{
-						SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT);
-						smsg.addSkillName(skill);
-						target.sendPacket(smsg);
-					}
-					
-					if (isPlayer() && target.isSummon())
+					if (isPlayer() && tgt.isSummon())
 					{
-						((L2Summon) target).updateAndBroadcastStatus(1);
+						((L2Summon) tgt).updateAndBroadcastStatus(1);
 					}
 				}
 				else if (isPlayable() && tgt.isL2Attackable())
@@ -6048,7 +5974,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 			L2Weapon activeWeapon = getActiveWeaponItem();
 			
 			// Check if the toggle skill effects are already in progress on the L2Character
-			if (skill.isToggle() && (getFirstEffect(skill.getId()) != null))
+			if (skill.isToggle() && isAffectedBySkill(skill.getId()))
 			{
 				return;
 			}
@@ -6084,7 +6010,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 								abortAttack();
 								abortCast();
 								getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
-								tempSkill.getEffects(target, this);
+								tempSkill.applyEffects(target, null, this, null, false, false);
 							}
 							else if (_log.isLoggable(Level.WARNING))
 							{
@@ -6099,7 +6025,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 								abortAttack();
 								abortCast();
 								getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
-								tempSkill.getEffects(target, this);
+								tempSkill.applyEffects(target, null, this, null, false, false);
 							}
 							else if (_log.isLoggable(Level.WARNING))
 							{
@@ -6760,8 +6686,16 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
 	 */
 	public int getMaxBuffCount()
 	{
-		final L2Effect effect = getFirstPassiveEffect(L2EffectType.ENLARGE_ABNORMAL_SLOT);
-		return Config.BUFFS_MAX_AMOUNT + (effect == null ? 0 : (int) effect.calc());
+		int count = Config.BUFFS_MAX_AMOUNT;
+		if (isAffectedBySkill(L2Skill.SKILL_DIVINE_INSPIRATION))
+		{
+			final BuffInfo info = getEffectList().getBuffInfoBySkillId(L2Skill.SKILL_DIVINE_INSPIRATION);
+			for (AbstractEffect effect : info.getEffects())
+			{
+				count += (int) effect.getValue();
+			}
+		}
+		return count;
 	}
 	
 	/**

+ 11 - 26
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2BabyPetInstance.java

@@ -18,8 +18,8 @@
  */
 package com.l2jserver.gameserver.model.actor.instance;
 
-import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Future;
 
 import javolution.util.FastList;
@@ -32,10 +32,10 @@ import com.l2jserver.gameserver.enums.InstanceType;
 import com.l2jserver.gameserver.model.L2PetData.L2PetSkillLearn;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
@@ -238,7 +238,7 @@ public final class L2BabyPetInstance extends L2PetInstance
 	private class CastTask implements Runnable
 	{
 		private final L2BabyPetInstance _baby;
-		private final List<L2Skill> _currentBuffs = new FastList<>();
+		private final List<L2Skill> _currentBuffs = new CopyOnWriteArrayList<>();
 		
 		public CastTask(L2BabyPetInstance baby)
 		{
@@ -290,7 +290,7 @@ public final class L2BabyPetInstance extends L2PetInstance
 					}
 				}
 				
-				if (_baby.getFirstEffect(BUFF_CONTROL) == null) // Buff Control is not active
+				if (!_baby.isAffectedBySkill(BUFF_CONTROL)) // Buff Control is not active
 				{
 					// searching for usable buffs
 					if ((_buffs != null) && !_buffs.isEmpty())
@@ -312,36 +312,21 @@ public final class L2BabyPetInstance extends L2PetInstance
 					// buffs found, checking owner buffs
 					if (!_currentBuffs.isEmpty())
 					{
-						Iterator<L2Skill> iter;
-						L2Skill currentSkill;
-						for (L2Effect e : owner.getAllEffects())
+						for (BuffInfo info : owner.getEffectList().getBuffs().values())
 						{
-							if (e == null)
-							{
-								continue;
-							}
-							
-							currentSkill = e.getSkill();
-							// skipping debuffs, passives, toggles
-							if (currentSkill.isDebuff() || currentSkill.isPassive() || currentSkill.isToggle())
-							{
-								continue;
-							}
-							
+							final L2Skill currentSkill = info.getSkill();
 							// if buff does not need to be casted - remove it from list
-							iter = _currentBuffs.iterator();
-							while (iter.hasNext())
+							for (L2Skill buff : _currentBuffs)
 							{
-								skill = iter.next();
-								if ((currentSkill.getId() == skill.getId()) && (currentSkill.getLevel() >= skill.getLevel()))
+								if ((currentSkill.getId() == buff.getId()) && (currentSkill.getLevel() >= buff.getLevel()))
 								{
-									iter.remove();
+									_currentBuffs.remove(buff);
 								}
 								else
 								{
-									if (!skill.getAbnormalType().isNone() && (currentSkill.getAbnormalType() == skill.getAbnormalType()) && (currentSkill.getAbnormalLvl() >= skill.getAbnormalLvl()))
+									if (!buff.getAbnormalType().isNone() && (currentSkill.getAbnormalType() == buff.getAbnormalType()) && (currentSkill.getAbnormalLvl() >= buff.getAbnormalLvl()))
 									{
-										iter.remove();
+										_currentBuffs.remove(buff);
 									}
 								}
 							}

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

@@ -347,7 +347,7 @@ public class L2CastleMagicianInstance extends L2NpcInstance implements L2SquadTr
 					return;
 				}
 				
-				if (clanLeader.getFirstEffect(L2EffectType.CLAN_GATE) != null)
+				if (clanLeader.getEffectList().getFirstEffect(L2EffectType.CLAN_GATE) != null)
 				{
 					if (!validateGateCondition(clanLeader, player))
 					{

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2ChestInstance.java

@@ -224,10 +224,10 @@ public final class L2ChestInstance extends L2MonsterInstance
 		
 		L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLevel);
 		
-		if (player.getFirstEffect(skill) == null)
+		if (!player.isAffectedBySkill(skillId))
 		{
-			skill.getEffects(this, player);
-			broadcastPacket(new MagicSkillUse(this, player, skill.getId(), skillLevel, skill.getHitTime(), 0));
+			skill.applyEffects(this, null, player, null, false, false);
+			broadcastPacket(new MagicSkillUse(this, player, skillId, skillLevel, skill.getHitTime(), 0));
 			return true;
 		}
 		return false;

+ 24 - 43
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2CubicInstance.java

@@ -37,7 +37,6 @@ import com.l2jserver.gameserver.model.actor.L2Playable;
 import com.l2jserver.gameserver.model.actor.tasks.cubics.CubicAction;
 import com.l2jserver.gameserver.model.actor.tasks.cubics.CubicDisappear;
 import com.l2jserver.gameserver.model.actor.tasks.cubics.CubicHeal;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.entity.TvTEvent;
 import com.l2jserver.gameserver.model.entity.TvTEventTeam;
@@ -465,7 +464,7 @@ public final class L2CubicInstance implements IIdentifiable
 		}
 	}
 	
-	public void useCubicContinuous(L2CubicInstance activeCubic, L2Skill skill, L2Object[] targets)
+	public void useCubicContinuous(L2Skill skill, L2Object[] targets)
 	{
 		for (L2Character target : (L2Character[]) targets)
 		{
@@ -476,33 +475,23 @@ public final class L2CubicInstance implements IIdentifiable
 			
 			if (skill.isBad())
 			{
-				byte shld = Formulas.calcShldUse(activeCubic.getOwner(), target, skill);
-				boolean acted = Formulas.calcCubicSkillSuccess(activeCubic, target, skill, shld);
+				byte shld = Formulas.calcShldUse(getOwner(), target, skill);
+				boolean acted = Formulas.calcCubicSkillSuccess(this, target, skill, shld);
 				if (!acted)
 				{
-					activeCubic.getOwner().sendPacket(SystemMessageId.ATTACK_FAILED);
+					getOwner().sendPacket(SystemMessageId.ATTACK_FAILED);
 					continue;
 				}
 				
 			}
 			
-			// if this is a debuff let the duel manager know about it
-			// so the debuff can be removed after the duel
-			// (player & target must be in the same duel)
-			if ((target.isPlayer()) && target.getActingPlayer().isInDuel() && (skill.getSkillType() == L2SkillType.DEBUFF) && (activeCubic.getOwner().getDuelId() == target.getActingPlayer().getDuelId()))
-			{
-				DuelManager dm = DuelManager.getInstance();
-				for (L2Effect debuff : skill.getEffects(activeCubic.getOwner(), target))
-				{
-					if (debuff != null)
-					{
-						dm.onBuff(target.getActingPlayer(), debuff);
-					}
-				}
-			}
-			else
+			// Apply effects
+			skill.applyEffects(getOwner(), this, target, null, false, false);
+			
+			// If this is a bad skill notify the duel manager, so it can be removed after the duel (player & target must be in the same duel).
+			if (target.isPlayer() && target.getActingPlayer().isInDuel() && skill.isBad() && (getOwner().getDuelId() == target.getActingPlayer().getDuelId()))
 			{
-				skill.getEffects(activeCubic, target, null);
+				DuelManager.getInstance().onBuff(target.getActingPlayer(), skill);
 			}
 		}
 	}
@@ -611,7 +600,7 @@ public final class L2CubicInstance implements IIdentifiable
 		}
 	}
 	
-	public void useCubicDisabler(L2SkillType type, L2CubicInstance activeCubic, L2Skill skill, L2Object[] targets)
+	public void useCubicDisabler(L2SkillType type, L2Skill skill, L2Object[] targets)
 	{
 		if (Config.DEBUG)
 		{
@@ -625,29 +614,19 @@ public final class L2CubicInstance implements IIdentifiable
 				continue;
 			}
 			
-			byte shld = Formulas.calcShldUse(activeCubic.getOwner(), target, skill);
+			byte shld = Formulas.calcShldUse(getOwner(), target, skill);
 			
 			if (skill.hasEffectType(L2EffectType.STUN, L2EffectType.PARALYZE, L2EffectType.ROOT))
 			{
-				if (Formulas.calcCubicSkillSuccess(activeCubic, target, skill, shld))
+				if (Formulas.calcCubicSkillSuccess(this, target, skill, shld))
 				{
-					// if this is a debuff let the duel manager know about it
-					// so the debuff can be removed after the duel
-					// (player & target must be in the same duel)
-					if ((target instanceof L2PcInstance) && ((L2PcInstance) target).isInDuel() && (skill.getSkillType() == L2SkillType.DEBUFF) && (activeCubic.getOwner().getDuelId() == ((L2PcInstance) target).getDuelId()))
-					{
-						DuelManager dm = DuelManager.getInstance();
-						for (L2Effect debuff : skill.getEffects(activeCubic.getOwner(), target))
-						{
-							if (debuff != null)
-							{
-								dm.onBuff(((L2PcInstance) target), debuff);
-							}
-						}
-					}
-					else
+					// Apply effects
+					skill.applyEffects(getOwner(), this, target, null, false, false);
+					
+					// If this is a bad skill notify the duel manager, so it can be removed after the duel (player & target must be in the same duel).
+					if (target.isPlayer() && target.getActingPlayer().isInDuel() && skill.isBad() && (getOwner().getDuelId() == target.getActingPlayer().getDuelId()))
 					{
-						skill.getEffects(activeCubic, target, null);
+						DuelManager.getInstance().onBuff(target.getActingPlayer(), skill);
 					}
 					
 					if (Config.DEBUG)
@@ -666,13 +645,15 @@ public final class L2CubicInstance implements IIdentifiable
 			
 			if (skill.hasEffectType(L2EffectType.AGGRESSION))
 			{
-				if (Formulas.calcCubicSkillSuccess(activeCubic, target, skill, shld))
+				if (Formulas.calcCubicSkillSuccess(this, target, skill, shld))
 				{
 					if (target.isL2Attackable())
 					{
-						target.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, activeCubic.getOwner(), (int) ((150 * skill.getPower()) / (target.getLevel() + 7)));
+						target.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, getOwner(), (int) ((150 * skill.getPower()) / (target.getLevel() + 7)));
 					}
-					skill.getEffects(activeCubic, target, null);
+					
+					// Apply effects
+					skill.applyEffects(getOwner(), this, target, null, false, false);
 					
 					if (Config.DEBUG)
 					{

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

@@ -165,7 +165,7 @@ public class L2NpcBufferInstance extends L2Npc
 				final L2Skill skill = SkillTable.getInstance().getInfo(npcBuffGroupInfo.getSkill().getSkillId(), npcBuffGroupInfo.getSkill().getSkillLvl());
 				if (skill != null)
 				{
-					skill.getEffects(player, target);
+					skill.applyEffects(player, null, target, null, false, false);
 				}
 			}
 			

+ 236 - 154
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -121,6 +121,7 @@ import com.l2jserver.gameserver.model.BlockList;
 import com.l2jserver.gameserver.model.L2AccessLevel;
 import com.l2jserver.gameserver.model.L2Clan;
 import com.l2jserver.gameserver.model.L2ClanMember;
+import com.l2jserver.gameserver.model.L2CommandChannel;
 import com.l2jserver.gameserver.model.L2ContactList;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
 import com.l2jserver.gameserver.model.L2ManufactureItem;
@@ -176,7 +177,6 @@ import com.l2jserver.gameserver.model.actor.tasks.player.RecoGiveTask;
 import com.l2jserver.gameserver.model.actor.tasks.player.RentPetTask;
 import com.l2jserver.gameserver.model.actor.tasks.player.ResetChargesTask;
 import com.l2jserver.gameserver.model.actor.tasks.player.ResetSoulsTask;
-import com.l2jserver.gameserver.model.actor.tasks.player.ShortBuffTask;
 import com.l2jserver.gameserver.model.actor.tasks.player.SitDownTask;
 import com.l2jserver.gameserver.model.actor.tasks.player.StandUpTask;
 import com.l2jserver.gameserver.model.actor.tasks.player.TeleportWatchdogTask;
@@ -189,10 +189,8 @@ import com.l2jserver.gameserver.model.base.ClassId;
 import com.l2jserver.gameserver.model.base.ClassLevel;
 import com.l2jserver.gameserver.model.base.PlayerClass;
 import com.l2jserver.gameserver.model.base.SubClass;
-import com.l2jserver.gameserver.model.effects.AbnormalEffect;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
 import com.l2jserver.gameserver.model.effects.EffectFlag;
-import com.l2jserver.gameserver.model.effects.EffectTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.entity.Castle;
 import com.l2jserver.gameserver.model.entity.Duel;
@@ -234,6 +232,9 @@ import com.l2jserver.gameserver.model.punishment.PunishmentType;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.model.quest.State;
+import com.l2jserver.gameserver.model.skills.AbnormalType;
+import com.l2jserver.gameserver.model.skills.AbnormalVisualEffect;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.L2SkillType;
 import com.l2jserver.gameserver.model.skills.l2skills.L2SkillSiegeFlag;
@@ -302,7 +303,6 @@ import com.l2jserver.gameserver.network.serverpackets.RelationChanged;
 import com.l2jserver.gameserver.network.serverpackets.Ride;
 import com.l2jserver.gameserver.network.serverpackets.ServerClose;
 import com.l2jserver.gameserver.network.serverpackets.SetupGauge;
-import com.l2jserver.gameserver.network.serverpackets.ShortBuffStatusUpdate;
 import com.l2jserver.gameserver.network.serverpackets.ShortCutInit;
 import com.l2jserver.gameserver.network.serverpackets.SkillCoolTime;
 import com.l2jserver.gameserver.network.serverpackets.SkillList;
@@ -348,8 +348,8 @@ public final class L2PcInstance extends L2Playable
 	private static final String DELETE_CHAR_SKILLS = "DELETE FROM character_skills WHERE charId=? AND class_index=?";
 	
 	// Character Skill Save SQL String Definitions:
-	private static final String ADD_SKILL_SAVE = "INSERT INTO character_skills_save (charId,skill_id,skill_level,effect_count,effect_cur_time,reuse_delay,systime,restore_type,class_index,buff_index) VALUES (?,?,?,?,?,?,?,?,?,?)";
-	private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,effect_count,effect_cur_time, reuse_delay, systime, restore_type FROM character_skills_save WHERE charId=? AND class_index=? ORDER BY buff_index ASC";
+	private static final String ADD_SKILL_SAVE = "INSERT INTO character_skills_save (charId,skill_id,skill_level,remaining_time,reuse_delay,systime,restore_type,class_index,buff_index) VALUES (?,?,?,?,?,?,?,?,?)";
+	private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,remaining_time, reuse_delay, systime, restore_type FROM character_skills_save WHERE charId=? AND class_index=? ORDER BY buff_index ASC";
 	private static final String DELETE_SKILL_SAVE = "DELETE FROM character_skills_save WHERE charId=? AND class_index=?";
 	
 	// Character Item Reuse Time String Definition:
@@ -728,6 +728,8 @@ public final class L2PcInstance extends L2Playable
 	// Used for protection after teleport
 	private long _protectEndTime = 0;
 	
+	private L2ItemInstance _lure = null;
+	
 	public boolean isSpawnProtected()
 	{
 		return _protectEndTime > GameTimeController.getInstance().getGameTicks();
@@ -903,9 +905,6 @@ public final class L2PcInstance extends L2Playable
 	/** Herbs Task Time **/
 	private int _herbstask = 0;
 	
-	/** ShortBuff clearing Task */
-	private ScheduledFuture<?> _shortBuffTask = null;
-	
 	// L2JMOD Wedding
 	private boolean _married = false;
 	private int _partnerId = 0;
@@ -2865,15 +2864,9 @@ public final class L2PcInstance extends L2Playable
 			}
 			
 			// fix when learning toggle skills
-			if (sk.isToggle())
+			if (sk.isToggle() && isAffectedBySkill(sk.getId()))
 			{
-				final L2Effect toggleEffect = getFirstEffect(sk.getId());
-				if (toggleEffect != null)
-				{
-					// stop old toggle skill effect, and give new toggle skill effect back
-					toggleEffect.exit();
-					sk.getEffects(this, this);
-				}
+				stopSkillEffects(true, sk.getId());
 			}
 			
 			addSkill(sk, true);
@@ -2881,7 +2874,7 @@ public final class L2PcInstance extends L2Playable
 		
 		if (Config.AUTO_LEARN_SKILLS && (skillCounter > 0))
 		{
-			sendMessage("You have learned " + skillCounter + " new skills");
+			sendMessage("You have learned " + skillCounter + " new skills.");
 		}
 		return skillCounter;
 	}
@@ -3615,8 +3608,9 @@ public final class L2PcInstance extends L2Playable
 					}
 				}
 			}
-			// Auto use herbs - autoloot
-			if (item.getItemType() == L2EtcItemType.HERB) // If item is herb dont add it to iv :]
+			
+			// Auto-use herbs.
+			if (item.getItemType() == L2EtcItemType.HERB)
 			{
 				if (!isCastingNow())
 				{
@@ -4384,9 +4378,8 @@ public final class L2PcInstance extends L2Playable
 			return false;
 		}
 		
-		if ((skill.getSkillType() == L2SkillType.SUMMON) && (hasSummon() || isMounted() || inObserverMode()))
+		if (isMounted() || inObserverMode())
 		{
-			sendPacket(SystemMessageId.SUMMON_ONLY_ONE);
 			return false;
 		}
 		
@@ -5047,7 +5040,7 @@ public final class L2PcInstance extends L2Playable
 		}
 		
 		_transformation = transformation;
-		stopAllToggles();
+		getEffectList().stopAllToggles();
 		transformation.onTransform(this);
 		sendSkillList();
 		sendPacket(new SkillCoolTime(this));
@@ -5066,7 +5059,7 @@ public final class L2PcInstance extends L2Playable
 			setQueuedSkill(null, false, false);
 			_transformation.onUntransform(this);
 			_transformation = null;
-			stopEffects(L2EffectType.TRANSFORMATION);
+			getEffectList().stopSkillEffects(false, AbnormalType.TRANSFORM);
 			sendSkillList();
 			sendPacket(new SkillCoolTime(this));
 			broadcastUserInfo();
@@ -5886,7 +5879,7 @@ public final class L2PcInstance extends L2Playable
 	 */
 	public boolean isLucky()
 	{
-		return ((getLevel() <= 9) && (getFirstPassiveEffect(L2EffectType.LUCKY) != null));
+		return (getLevel() <= 9) && isAffectedBySkill(L2Skill.SKILL_LUCKY);
 	}
 	
 	/**
@@ -6690,7 +6683,7 @@ public final class L2PcInstance extends L2Playable
 			return false;
 		}
 		
-		stopAllToggles();
+		getEffectList().stopAllToggles();
 		setMount(pet.getId(), pet.getLevel());
 		setMountObjectID(pet.getControlObjectId());
 		clearPetData();
@@ -6711,7 +6704,7 @@ public final class L2PcInstance extends L2Playable
 			return false;
 		}
 		
-		stopAllToggles();
+		getEffectList().stopAllToggles();
 		setMount(npcId, getLevel());
 		clearPetData();
 		setMountObjectID(controlItemObjId);
@@ -7822,75 +7815,67 @@ public final class L2PcInstance extends L2Playable
 			// reuse delays for matching skills. 'restore_type'= 0.
 			if (storeEffects)
 			{
-				for (L2Effect effect : getAllEffects())
+				for (BuffInfo info : getEffectList().getEffects())
 				{
-					if (effect == null)
+					if (info == null)
 					{
 						continue;
 					}
 					
-					switch (effect.getEffectType())
+					final L2Skill skill = info.getSkill();
+					if (skill.isToggle())
 					{
-						case HEAL_OVER_TIME:
-						case CPHEAL_OVER_TIME:
-						case HIDE:
-							continue;
+						continue;
 					}
 					
-					L2Skill skill = effect.getSkill();
-					if (storedSkills.contains(skill.getReuseHashCode()))
+					// Dances and songs are not kept in retail.
+					if (skill.isDance() && !Config.ALT_STORE_DANCES)
 					{
 						continue;
 					}
 					
-					// Dances and songs are not kept in retail.
-					if (skill.isDance() && !Config.ALT_STORE_DANCES)
+					if (storedSkills.contains(skill.getReuseHashCode()))
 					{
 						continue;
 					}
 					
 					storedSkills.add(skill.getReuseHashCode());
 					
-					if (effect.isInUse() && !skill.isToggle())
+					statement.setInt(1, getObjectId());
+					statement.setInt(2, skill.getId());
+					statement.setInt(3, skill.getLevel());
+					statement.setInt(4, info.getTime());
+					
+					if (_reuseTimeStampsSkills.containsKey(skill.getReuseHashCode()))
 					{
-						statement.setInt(1, getObjectId());
-						statement.setInt(2, skill.getId());
-						statement.setInt(3, skill.getLevel());
-						statement.setInt(4, effect.getTickCount());
-						statement.setInt(5, effect.getTime());
-						
-						if (_reuseTimeStampsSkills.containsKey(skill.getReuseHashCode()))
-						{
-							TimeStamp t = _reuseTimeStampsSkills.get(skill.getReuseHashCode());
-							statement.setLong(6, t.hasNotPassed() ? t.getReuse() : 0);
-							statement.setDouble(7, t.hasNotPassed() ? t.getStamp() : 0);
-						}
-						else
-						{
-							statement.setLong(6, 0);
-							statement.setDouble(7, 0);
-						}
-						
-						statement.setInt(8, 0);
-						statement.setInt(9, getClassIndex());
-						statement.setInt(10, ++buff_index);
-						statement.execute();
+						TimeStamp t = _reuseTimeStampsSkills.get(skill.getReuseHashCode());
+						statement.setLong(5, t.hasNotPassed() ? t.getReuse() : 0);
+						statement.setDouble(6, t.hasNotPassed() ? t.getStamp() : 0);
+					}
+					else
+					{
+						statement.setLong(5, 0);
+						statement.setDouble(6, 0);
 					}
+					
+					statement.setInt(7, 0);
+					statement.setInt(8, getClassIndex());
+					statement.setInt(9, ++buff_index);
+					statement.execute();
 				}
 			}
 			
 			// Store the reuse delays of remaining skills which
 			// lost effect but still under reuse delay. 'restore_type' 1.
-			int hash;
-			TimeStamp t;
 			for (Entry<Integer, TimeStamp> ts : _reuseTimeStampsSkills.entrySet())
 			{
-				hash = ts.getKey();
+				final int hash = ts.getKey();
 				if (storedSkills.contains(hash))
 				{
 					continue;
 				}
-				t = ts.getValue();
+				
+				final TimeStamp t = ts.getValue();
 				if ((t != null) && t.hasNotPassed())
 				{
 					storedSkills.add(hash);
@@ -7899,12 +7884,11 @@ public final class L2PcInstance extends L2Playable
 					statement.setInt(2, t.getSkillId());
 					statement.setInt(3, t.getSkillLvl());
 					statement.setInt(4, -1);
-					statement.setInt(5, -1);
-					statement.setLong(6, t.getReuse());
-					statement.setDouble(7, t.getStamp());
-					statement.setInt(8, 1);
-					statement.setInt(9, getClassIndex());
-					statement.setInt(10, ++buff_index);
+					statement.setLong(5, t.getReuse());
+					statement.setDouble(6, t.getStamp());
+					statement.setInt(7, 1);
+					statement.setInt(8, getClassIndex());
+					statement.setInt(9, ++buff_index);
 					statement.execute();
 				}
 			}
@@ -8164,8 +8148,7 @@ public final class L2PcInstance extends L2Playable
 			{
 				while (rset.next())
 				{
-					int effectCount = rset.getInt("effect_count");
-					int effectCurTime = rset.getInt("effect_cur_time");
+					int remainingTime = rset.getInt("remaining_time");
 					long reuseDelay = rset.getLong("reuse_delay");
 					long systime = rset.getLong("systime");
 					int restoreType = rset.getInt("restore_type");
@@ -8176,10 +8159,10 @@ public final class L2PcInstance extends L2Playable
 						continue;
 					}
 					
-					final long remainingTime = systime - System.currentTimeMillis();
-					if (remainingTime > 10)
+					final long time = systime - System.currentTimeMillis();
+					if (time > 10)
 					{
-						disableSkill(skill, remainingTime);
+						disableSkill(skill, time);
 						addTimeStamp(skill, reuseDelay, systime);
 					}
 					
@@ -8201,20 +8184,30 @@ public final class L2PcInstance extends L2Playable
 						env.setCharacter(this);
 						env.setTarget(this);
 						env.setSkill(skill);
-						final L2Effect[] effects = new L2Effect[skill.getEffectTemplates().size()];
-						int index = 0;
-						for (EffectTemplate et : skill.getEffectTemplates())
+						
+						final BuffInfo info = new BuffInfo(env);
+						info.setAbnormalTime(remainingTime);
+						for (AbstractEffect effect : skill.getEffectTemplates())
 						{
-							L2Effect effect = et.getEffect(env);
 							if (effect != null)
 							{
-								effect.setCount(effectCount);
-								effect.setFirstTime(effectCurTime);
-								effect.scheduleEffect();
-								effects[index++] = effect;
+								if (effect.isInstant())
+								{
+									if (effect.calcSuccess(info))
+									{
+										effect.onStart(info);
+									}
+								}
+								else
+								{
+									if (effect.onStart(info))
+									{
+										info.addEffect(effect);
+									}
+								}
 							}
 						}
-						getEffectList().add(effects);
+						getEffectList().add(info);
 					}
 				}
 			}
@@ -8875,20 +8868,12 @@ public final class L2PcInstance extends L2Playable
 			return false;
 		}
 		
-		// Check if the skill type is TOGGLE
-		if (skill.isToggle())
+		// Check if the skill type is toggle.
+		if (skill.isToggle() && isAffectedBySkill(skill.getId()))
 		{
-			// Get effects of the skill
-			L2Effect effect = getFirstEffect(skill.getId());
-			
-			if (effect != null)
-			{
-				effect.exit();
-				
-				// Send a Server->Client packet ActionFailed to the L2PcInstance
-				sendPacket(ActionFailed.STATIC_PACKET);
-				return false;
-			}
+			stopSkillEffects(true, skill.getId());
+			sendPacket(ActionFailed.STATIC_PACKET);
+			return false;
 		}
 		
 		// Check if the player uses "Fake Death" skill
@@ -9316,6 +9301,144 @@ public final class L2PcInstance extends L2Playable
 	public boolean checkPvpSkill(L2Object target, L2Skill skill, boolean srcIsSummon)
 	{
 		final L2PcInstance targetPlayer = target != null ? target.getActingPlayer() : null;
+		if (skill.isDebuff())
+		{
+			if (this == targetPlayer)
+			{
+				return false;
+			}
+			
+			final boolean isCtrlPressed = (getCurrentSkill() != null) && getCurrentSkill().isCtrlPressed();
+			final boolean isInsideSiegeZone = isInsideZone(ZoneId.SIEGE);
+			if (targetPlayer != null)
+			{
+				if (isInDuel())
+				{
+					if (!targetPlayer.isInDuel())
+					{
+						return false;
+					}
+					
+					if ((getDuelId() != 0) && (getDuelId() == targetPlayer.getDuelId()))
+					{
+						return true;
+					}
+				}
+				
+				if (isInOlympiadMode())
+				{
+					if (!targetPlayer.isInOlympiadMode())
+					{
+						return false;
+					}
+					
+					if ((getOlympiadGameId() != 0) && (getOlympiadGameId() == targetPlayer.getOlympiadGameId()))
+					{
+						return true;
+					}
+				}
+				
+				if (targetPlayer.isInOlympiadMode())
+				{
+					return false;
+				}
+				
+				if (targetPlayer.isInsideZone(ZoneId.PEACE))
+				{
+					return false;
+				}
+				
+				// On retail, you can't debuff party members at all unless you're in duel.
+				if (isInParty() && targetPlayer.isInParty() && (getParty().getLeader() == targetPlayer.getParty().getLeader()))
+				{
+					return false;
+				}
+				
+				final L2Party activeCharParty = getParty();
+				if (activeCharParty != null)
+				{
+					final L2CommandChannel chan = activeCharParty.getCommandChannel();
+					if ((chan != null) && chan.containsPlayer(targetPlayer))
+					{
+						return false;
+					}
+				}
+				
+				// During Fortress/Castle Sieges, they can't debuff eachothers if they are in the same side.
+				if (isInsideSiegeZone && isInSiege() && (getSiegeState() != 0) && (targetPlayer.getSiegeState() != 0))
+				{
+					final Siege siege = SiegeManager.getInstance().getSiege(getX(), getY(), getZ());
+					if (siege != null)
+					{
+						if ((siege.checkIsDefender(getClan()) && siege.checkIsDefender(targetPlayer.getClan())) || (siege.checkIsAttacker(getClan()) && siege.checkIsAttacker(targetPlayer.getClan())))
+						{
+							sendPacket(SystemMessage.getSystemMessage(SystemMessageId.FORCED_ATTACK_IS_IMPOSSIBLE_AGAINST_SIEGE_SIDE_TEMPORARY_ALLIED_MEMBERS));
+							return false;
+						}
+					}
+				}
+				
+				// You can debuff anyone except party members while in an arena...
+				if (isInsideZone(ZoneId.PVP) && targetPlayer.isInsideZone(ZoneId.PVP))
+				{
+					return true;
+				}
+				
+				final L2Clan aClan = getClan();
+				final L2Clan tClan = targetPlayer.getClan();
+				
+				if ((aClan != null) && (tClan != null))
+				{
+					if (aClan.isAtWarWith(tClan.getId()) && tClan.isAtWarWith(aClan.getId()))
+					{
+						return true;
+					}
+				}
+				
+				if ((getClanId() != 0) && (getClanId() == targetPlayer.getClanId()))
+				{
+					return false;
+				}
+				
+				if ((getAllyId() != 0) && (getAllyId() == targetPlayer.getAllyId()))
+				{
+					return false;
+				}
+				
+				// On retail, it is impossible to debuff a "peaceful" player.
+				if ((targetPlayer.getPvpFlag() == 0) && (targetPlayer.getKarma() == 0))
+				{
+					return false;
+				}
+				
+				if ((targetPlayer.getPvpFlag() > 0) || (targetPlayer.getKarma() > 0))
+				{
+					if (!isCtrlPressed)
+					{
+						switch (skill.getTargetType())
+						{
+							case AREA:
+							case AURA:
+							case BEHIND_AREA:
+							case BEHIND_AURA:
+							case FRONT_AREA:
+							case FRONT_AURA:
+							{
+								if ((getPvpFlag() > 0) || (getKarma() > 0))
+								{
+									return true;
+								}
+								return false;
+							}
+							default:
+								return true;
+						}
+					}
+					return true;
+				}
+			}
+		}
+		
 		if ((targetPlayer != null) && (target != this) && !(isInDuel() && (targetPlayer.getDuelId() == getDuelId())) && !isInsideZone(ZoneId.PVP) && !targetPlayer.isInsideZone(ZoneId.PVP))
 		{
 			SkillUseHolder skilldat = getCurrentSkill();
@@ -9425,24 +9548,10 @@ public final class L2PcInstance extends L2Playable
 	
 	public final void stopAllEffectsNotStayOnSubclassChange()
 	{
-		for (L2Effect effect : getEffectList().getAllEffects())
-		{
-			if ((effect != null) && !effect.getSkill().isStayOnSubclassChange())
-			{
-				effect.exit(true);
-			}
-		}
+		getEffectList().stopAllEffectsNotStayOnSubclassChange();
 		updateAndBroadcastStatus(2);
 	}
 	
-	/**
-	 * Stop all toggle-type effects
-	 */
-	public final void stopAllToggles()
-	{
-		getEffectList().stopAllToggles();
-	}
-	
 	public final void stopCubics()
 	{
 		if (!_cubics.isEmpty())
@@ -9788,7 +9897,8 @@ public final class L2PcInstance extends L2Playable
 	{
 		setLastLocation();
 		
-		stopEffects(L2EffectType.HIDE);
+		// Remove Hide.
+		getEffectList().stopSkillEffects(true, AbnormalType.HIDE);
 		
 		_observerMode = true;
 		setTarget(null);
@@ -9820,7 +9930,8 @@ public final class L2PcInstance extends L2Playable
 			getSummon().unSummon(this);
 		}
 		
-		stopEffects(L2EffectType.HIDE);
+		// Remove Hide.
+		getEffectList().stopSkillEffects(true, AbnormalType.HIDE);
 		
 		if (!_cubics.isEmpty())
 		{
@@ -10601,7 +10712,7 @@ public final class L2PcInstance extends L2Playable
 			}
 			
 			restoreEffects();
-			updateEffectIcons();
+			
 			sendPacket(new EtcStatusUpdate(this));
 			
 			// if player has quest 422: Repent Your Sins, remove it
@@ -11602,9 +11713,11 @@ public final class L2PcInstance extends L2Playable
 			getSkillChannelized().abortChannelization();
 		}
 		
+		// Stop all toggles.
+		getEffectList().stopAllToggles();
+		
 		// Remove from world regions zones
 		final L2WorldRegion oldRegion = getWorldRegion();
-		
 		if (oldRegion != null)
 		{
 			oldRegion.removeFromZones(this);
@@ -12187,10 +12300,10 @@ public final class L2PcInstance extends L2Playable
 	private int getRandomFishLvl()
 	{
 		int skilllvl = getSkillLevel(1315);
-		final L2Effect e = getFirstEffect(2274);
-		if (e != null)
+		final BuffInfo info = getEffectList().getBuffInfoBySkillId(2274);
+		if (info != null)
 		{
-			skilllvl = (int) e.getSkill().getPower();
+			skilllvl = (int) info.getSkill().getPower();
 		}
 		if (skilllvl <= 0)
 		{
@@ -12390,9 +12503,6 @@ public final class L2PcInstance extends L2Playable
 		return _mountObjectID;
 	}
 	
-	private L2ItemInstance _lure = null;
-	private int _shortBuffTaskSkillId = 0;
-	
 	/**
 	 * @return the current skill in use or return null.
 	 */
@@ -12639,34 +12749,6 @@ public final class L2PcInstance extends L2Playable
 		}
 	}
 	
-	/**
-	 * @param magicId
-	 * @param level
-	 * @param time
-	 */
-	public void shortBuffStatusUpdate(int magicId, int level, int time)
-	{
-		if (_shortBuffTask != null)
-		{
-			_shortBuffTask.cancel(false);
-			_shortBuffTask = null;
-		}
-		_shortBuffTask = ThreadPoolManager.getInstance().scheduleGeneral(new ShortBuffTask(this), time * 1000);
-		setShortBuffTaskSkillId(magicId);
-		
-		sendPacket(new ShortBuffStatusUpdate(magicId, level, time));
-	}
-	
-	public int getShortBuffTaskSkillId()
-	{
-		return _shortBuffTaskSkillId;
-	}
-	
-	public void setShortBuffTaskSkillId(int id)
-	{
-		_shortBuffTaskSkillId = id;
-	}
-	
 	public int getDeathPenaltyBuffLevel()
 	{
 		return _deathPenaltyBuffLevel;
@@ -13148,13 +13230,13 @@ public final class L2PcInstance extends L2Playable
 		return _eventEffectId;
 	}
 	
-	public void startEventEffect(AbnormalEffect mask)
+	public void startEventEffect(AbnormalVisualEffect mask)
 	{
 		_eventEffectId |= mask.getMask();
 		broadcastUserInfo();
 	}
 	
-	public void stopEventEffect(AbnormalEffect mask)
+	public void stopEventEffect(AbnormalVisualEffect mask)
 	{
 		_eventEffectId &= ~mask.getMask();
 		broadcastUserInfo();

+ 32 - 33
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PetInstance.java

@@ -58,8 +58,7 @@ import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Summon;
 import com.l2jserver.gameserver.model.actor.stat.PetStat;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
-import com.l2jserver.gameserver.model.effects.EffectTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
 import com.l2jserver.gameserver.model.itemcontainer.PcInventory;
 import com.l2jserver.gameserver.model.itemcontainer.PetInventory;
@@ -67,6 +66,7 @@ import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.L2Weapon;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
 import com.l2jserver.gameserver.model.items.type.L2EtcItemType;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.stats.Env;
 import com.l2jserver.gameserver.model.zone.ZoneId;
@@ -84,8 +84,8 @@ public class L2PetInstance extends L2Summon
 {
 	protected static final Logger _logPet = Logger.getLogger(L2PetInstance.class.getName());
 	
-	private static final String ADD_SKILL_SAVE = "INSERT INTO character_pet_skills_save (petObjItemId,skill_id,skill_level,effect_count,effect_cur_time,buff_index) VALUES (?,?,?,?,?,?)";
-	private static final String RESTORE_SKILL_SAVE = "SELECT petObjItemId,skill_id,skill_level,effect_count,effect_cur_time,buff_index FROM character_pet_skills_save WHERE petObjItemId=? ORDER BY buff_index ASC";
+	private static final String ADD_SKILL_SAVE = "INSERT INTO character_pet_skills_save (petObjItemId,skill_id,skill_level,remaining_time,buff_index) VALUES (?,?,?,?,?)";
+	private static final String RESTORE_SKILL_SAVE = "SELECT petObjItemId,skill_id,skill_level,remaining_time,buff_index FROM character_pet_skills_save WHERE petObjItemId=? ORDER BY buff_index ASC";
 	private static final String DELETE_SKILL_SAVE = "DELETE FROM character_pet_skills_save WHERE petObjItemId=?";
 	
 	private final Map<Integer, TimeStamp> _reuseTimeStampsSkills = new FastMap<>();
@@ -1074,23 +1074,14 @@ public class L2PetInstance extends L2Summon
 			// Store all effect data along with calculated remaining
 			if (storeEffects)
 			{
-				for (L2Effect effect : getAllEffects())
+				for (BuffInfo info : getEffectList().getEffects())
 				{
-					if (effect == null)
+					if (info == null)
 					{
 						continue;
 					}
 					
-					switch (effect.getEffectType())
-					{
-						case HEAL_OVER_TIME:
-						case CPHEAL_OVER_TIME:
-							// TODO: Fix me.
-						case HIDE:
-							continue;
-					}
-					
-					L2Skill skill = effect.getSkill();
+					L2Skill skill = info.getSkill();
 					if (storedSkills.contains(skill.getReuseHashCode()))
 					{
 						continue;
@@ -1098,14 +1089,13 @@ public class L2PetInstance extends L2Summon
 					
 					storedSkills.add(skill.getReuseHashCode());
 					
-					if (effect.isInUse() && !skill.isToggle())
+					if (!skill.isToggle())
 					{
 						ps2.setInt(1, getControlObjectId());
 						ps2.setInt(2, skill.getId());
 						ps2.setInt(3, skill.getLevel());
-						ps2.setInt(4, effect.getTickCount());
-						ps2.setInt(5, effect.getTime());
-						ps2.setInt(6, ++buff_index);
+						ps2.setInt(4, info.getTime());
+						ps2.setInt(5, ++buff_index);
 						ps2.execute();
 						
 						if (!SummonEffectsTable.getInstance().getPetEffects().contains(getControlObjectId()))
@@ -1113,7 +1103,7 @@ public class L2PetInstance extends L2Summon
 							SummonEffectsTable.getInstance().getPetEffects().put(getControlObjectId(), new FastList<SummonEffect>());
 						}
 						
-						SummonEffectsTable.getInstance().getPetEffects().get(getControlObjectId()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, effect.getTickCount(), effect.getTime()));
+						SummonEffectsTable.getInstance().getPetEffects().get(getControlObjectId()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, info.getTime()));
 					}
 				}
 			}
@@ -1138,8 +1128,7 @@ public class L2PetInstance extends L2Summon
 				{
 					while (rset.next())
 					{
-						int effectCount = rset.getInt("effect_count");
-						int effectCurTime = rset.getInt("effect_cur_time");
+						int effectCurTime = rset.getInt("remaining_time");
 						
 						final L2Skill skill = SkillTable.getInstance().getInfo(rset.getInt("skill_id"), rset.getInt("skill_level"));
 						if (skill == null)
@@ -1154,7 +1143,7 @@ public class L2PetInstance extends L2Summon
 								SummonEffectsTable.getInstance().getPetEffects().put(getControlObjectId(), new FastList<SummonEffect>());
 							}
 							
-							SummonEffectsTable.getInstance().getPetEffects().get(getControlObjectId()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, effectCount, effectCurTime));
+							SummonEffectsTable.getInstance().getPetEffects().get(getControlObjectId()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, effectCurTime));
 						}
 					}
 				}
@@ -1184,20 +1173,30 @@ public class L2PetInstance extends L2Summon
 						env.setCharacter(this);
 						env.setTarget(this);
 						env.setSkill(se.getSkill());
-						final L2Effect[] effects = new L2Effect[se.getSkill().getEffectTemplates().size()];
-						int index = 0;
-						for (EffectTemplate et : se.getSkill().getEffectTemplates())
+						
+						final BuffInfo info = new BuffInfo(env);
+						info.setAbnormalTime(se.getEffectCurTime());
+						for (AbstractEffect effect : se.getSkill().getEffectTemplates())
 						{
-							L2Effect effect = et.getEffect(env);
 							if (effect != null)
 							{
-								effect.setCount(se.getEffectCount());
-								effect.setFirstTime(se.getEffectCurTime());
-								effect.scheduleEffect();
-								effects[index++] = effect;
+								if (effect.isInstant())
+								{
+									if (effect.calcSuccess(info))
+									{
+										effect.onStart(info);
+									}
+								}
+								else
+								{
+									if (effect.onStart(info))
+									{
+										info.addEffect(effect);
+									}
+								}
 							}
 						}
-						getEffectList().add(effects);
+						getEffectList().add(info);
 					}
 				}
 			}

+ 5 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2SepulcherMonsterInstance.java

@@ -21,13 +21,12 @@ package com.l2jserver.gameserver.model.actor.instance;
 import java.util.concurrent.Future;
 
 import com.l2jserver.gameserver.ThreadPoolManager;
-import com.l2jserver.gameserver.datatables.SkillTable;
 import com.l2jserver.gameserver.enums.InstanceType;
 import com.l2jserver.gameserver.instancemanager.FourSepulchersManager;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
+import com.l2jserver.gameserver.model.holders.SkillHolder;
 import com.l2jserver.gameserver.model.quest.QuestState;
-import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.network.serverpackets.NpcSay;
 
 /**
@@ -35,6 +34,8 @@ import com.l2jserver.gameserver.network.serverpackets.NpcSay;
  */
 public class L2SepulcherMonsterInstance extends L2MonsterInstance
 {
+	protected static final SkillHolder FAKE_PETRIFICATION = new SkillHolder(4616, 1);
+	
 	public int mysteriousBoxId = 0;
 	
 	protected Future<?> _victimSpawnKeyBoxTask = null;
@@ -510,8 +511,8 @@ public class L2SepulcherMonsterInstance extends L2MonsterInstance
 		@Override
 		public void run()
 		{
-			L2Skill fp = SkillTable.FrequentSkill.FAKE_PETRIFICATION.getSkill(); // Invulnerable by petrification
-			fp.getEffects(activeChar, activeChar);
+			// Invulnerable by petrification
+			FAKE_PETRIFICATION.getSkill().applyEffects(activeChar, null, activeChar, null, false, false);
 		}
 	}
 	

+ 32 - 33
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2ServitorInstance.java

@@ -40,8 +40,8 @@ import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Summon;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
-import com.l2jserver.gameserver.model.effects.EffectTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.l2skills.L2SkillSummon;
 import com.l2jserver.gameserver.model.stats.Env;
@@ -53,8 +53,8 @@ public class L2ServitorInstance extends L2Summon
 {
 	protected static final Logger log = Logger.getLogger(L2ServitorInstance.class.getName());
 	
-	private static final String ADD_SKILL_SAVE = "INSERT INTO character_summon_skills_save (ownerId,ownerClassIndex,summonSkillId,skill_id,skill_level,effect_count,effect_cur_time,buff_index) VALUES (?,?,?,?,?,?,?,?)";
-	private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,effect_count,effect_cur_time,buff_index FROM character_summon_skills_save WHERE ownerId=? AND ownerClassIndex=? AND summonSkillId=? ORDER BY buff_index ASC";
+	private static final String ADD_SKILL_SAVE = "INSERT INTO character_summon_skills_save (ownerId,ownerClassIndex,summonSkillId,skill_id,skill_level,remaining_time,buff_index) VALUES (?,?,?,?,?,?,?)";
+	private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,remaining_time,buff_index FROM character_summon_skills_save WHERE ownerId=? AND ownerClassIndex=? AND summonSkillId=? ORDER BY buff_index ASC";
 	private static final String DELETE_SKILL_SAVE = "DELETE FROM character_summon_skills_save WHERE ownerId=? AND ownerClassIndex=? AND summonSkillId=?";
 	
 	private float _expPenalty = 0; // exp decrease multiplier (i.e. 0.3 (= 30%) for shadow)
@@ -374,23 +374,14 @@ public class L2ServitorInstance extends L2Summon
 			{
 				try (PreparedStatement ps2 = con.prepareStatement(ADD_SKILL_SAVE))
 				{
-					for (L2Effect effect : getAllEffects())
+					for (BuffInfo info : getEffectList().getEffects())
 					{
-						if (effect == null)
+						if (info == null)
 						{
 							continue;
 						}
 						
-						switch (effect.getEffectType())
-						{
-							case HEAL_OVER_TIME:
-							case CPHEAL_OVER_TIME:
-								// TODO: Fix me.
-							case HIDE:
-								continue;
-						}
-						
-						L2Skill skill = effect.getSkill();
+						L2Skill skill = info.getSkill();
 						if (storedSkills.contains(skill.getReuseHashCode()))
 						{
 							continue;
@@ -398,16 +389,15 @@ public class L2ServitorInstance extends L2Summon
 						
 						storedSkills.add(skill.getReuseHashCode());
 						
-						if (effect.isInUse() && !skill.isToggle())
+						if (!skill.isToggle())
 						{
 							ps2.setInt(1, getOwner().getObjectId());
 							ps2.setInt(2, getOwner().getClassIndex());
 							ps2.setInt(3, getReferenceSkill());
 							ps2.setInt(4, skill.getId());
 							ps2.setInt(5, skill.getLevel());
-							ps2.setInt(6, effect.getTickCount());
-							ps2.setInt(7, effect.getTime());
-							ps2.setInt(8, ++buff_index);
+							ps2.setInt(6, info.getTime());
+							ps2.setInt(7, ++buff_index);
 							ps2.execute();
 							
 							if (!SummonEffectsTable.getInstance().getServitorEffectsOwner().contains(getOwner().getObjectId()))
@@ -423,7 +413,7 @@ public class L2ServitorInstance extends L2Summon
 								SummonEffectsTable.getInstance().getServitorEffects(getOwner()).put(getReferenceSkill(), new FastList<SummonEffect>());
 							}
 							
-							SummonEffectsTable.getInstance().getServitorEffects(getOwner()).get(getReferenceSkill()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, effect.getTickCount(), effect.getTime()));
+							SummonEffectsTable.getInstance().getServitorEffects(getOwner()).get(getReferenceSkill()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, info.getTime()));
 						}
 					}
 				}
@@ -456,8 +446,7 @@ public class L2ServitorInstance extends L2Summon
 					{
 						while (rset.next())
 						{
-							int effectCount = rset.getInt("effect_count");
-							int effectCurTime = rset.getInt("effect_cur_time");
+							int effectCurTime = rset.getInt("remaining_time");
 							
 							final L2Skill skill = SkillTable.getInstance().getInfo(rset.getInt("skill_id"), rset.getInt("skill_level"));
 							if (skill == null)
@@ -480,7 +469,7 @@ public class L2ServitorInstance extends L2Summon
 									SummonEffectsTable.getInstance().getServitorEffects(getOwner()).put(getReferenceSkill(), new FastList<SummonEffect>());
 								}
 								
-								SummonEffectsTable.getInstance().getServitorEffects(getOwner()).get(getReferenceSkill()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, effectCount, effectCurTime));
+								SummonEffectsTable.getInstance().getServitorEffects(getOwner()).get(getReferenceSkill()).add(SummonEffectsTable.getInstance().new SummonEffect(skill, effectCurTime));
 							}
 						}
 					}
@@ -516,20 +505,30 @@ public class L2ServitorInstance extends L2Summon
 						env.setCharacter(this);
 						env.setTarget(this);
 						env.setSkill(se.getSkill());
-						final L2Effect[] effects = new L2Effect[se.getSkill().getEffectTemplates().size()];
-						int index = 0;
-						for (EffectTemplate et : se.getSkill().getEffectTemplates())
+						
+						final BuffInfo info = new BuffInfo(env);
+						info.setAbnormalTime(se.getEffectCurTime());
+						for (AbstractEffect effect : se.getSkill().getEffectTemplates())
 						{
-							L2Effect effect = et.getEffect(env);
 							if (effect != null)
 							{
-								effect.setCount(se.getEffectCount());
-								effect.setFirstTime(se.getEffectCurTime());
-								effect.scheduleEffect();
-								effects[index++] = effect;
+								if (effect.isInstant())
+								{
+									if (effect.calcSuccess(info))
+									{
+										effect.onStart(info);
+									}
+								}
+								else
+								{
+									if (effect.onStart(info))
+									{
+										info.addEffect(effect);
+									}
+								}
 							}
 						}
-						getEffectList().add(effects);
+						getEffectList().add(info);
 					}
 				}
 			}

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

@@ -365,7 +365,7 @@ public final class L2TamedBeastInstance extends L2FeedableBeastInstance
 			for (L2Skill skill : getTemplate().getSkills().values())
 			{
 				// if the skill is a debuff, check if the attacker has it already [ attacker.getEffect(L2Skill skill) ]
-				if ((skill.getSkillType() == L2SkillType.DEBUFF) && (Rnd.get(3) < 1) && ((attacker != null) && (attacker.getFirstEffect(skill) != null)))
+				if ((skill.getSkillType() == L2SkillType.DEBUFF) && (Rnd.get(3) < 1) && ((attacker != null) && attacker.isAffectedBySkill(skill.getId())))
 				{
 					sitCastAndFollow(skill, attacker);
 				}
@@ -546,7 +546,7 @@ public final class L2TamedBeastInstance extends L2FeedableBeastInstance
 					{
 						buffToGive = skill;
 					}
-					if (owner.getFirstEffect(skill) != null)
+					if (owner.isAffectedBySkill(skill.getId()))
 					{
 						totalBuffsOnOwner++;
 					}

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

@@ -66,7 +66,7 @@ public final class L2TeleporterInstance extends L2Npc
 		StringTokenizer st = new StringTokenizer(command, " ");
 		String actualCommand = st.nextToken(); // Get actual command
 		
-		if ((player.getFirstEffect(6201) != null) || (player.getFirstEffect(6202) != null) || (player.getFirstEffect(6203) != null))
+		if (player.isAffectedBySkill(6201) || player.isAffectedBySkill(6202) || player.isAffectedBySkill(6203))
 		{
 			final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
 			

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/status/PcStatus.java

@@ -170,7 +170,7 @@ public class PcStatus extends PlayableStatus
 				if (mpDam > getActiveChar().getCurrentMp())
 				{
 					getActiveChar().sendPacket(SystemMessageId.MP_BECAME_0_ARCANE_SHIELD_DISAPPEARING);
-					getActiveChar().getFirstEffect(1556).stopEffectTask();
+					getActiveChar().stopSkillEffects(false, 1556);
 					value = mpDam - getActiveChar().getCurrentMp();
 					getActiveChar().setCurrentMp(0);
 				}

+ 15 - 14
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/tasks/cubics/CubicAction.java

@@ -27,8 +27,8 @@ import com.l2jserver.gameserver.handler.ISkillHandler;
 import com.l2jserver.gameserver.handler.SkillHandler;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2CubicInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.L2SkillType;
 import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
@@ -70,6 +70,7 @@ public final class CubicAction implements Runnable
 				_cubic.cancelDisappear();
 				return;
 			}
+			
 			if (!AttackStanceTaskManager.getInstance().hasAttackStanceTask(_cubic.getOwner()))
 			{
 				if (_cubic.getOwner().hasSummon())
@@ -86,29 +87,29 @@ public final class CubicAction implements Runnable
 					return;
 				}
 			}
+			
 			// The cubic has already reached its limit and it will stay idle until its duration ends.
 			if ((_cubic.getCubicMaxCount() > -1) && (_currentCount.get() >= _cubic.getCubicMaxCount()))
 			{
 				_cubic.stopAction();
 				return;
 			}
-			// Smart Cubic debuff cancel is 100%
-			boolean UseCubicCure = false;
-			L2Skill skill = null;
 			
+			// Smart Cubic debuff cancel is 100%
+			boolean useCubicCure = false;
 			if ((_cubic.getId() >= L2CubicInstance.SMART_CUBIC_EVATEMPLAR) && (_cubic.getId() <= L2CubicInstance.SMART_CUBIC_SPECTRALMASTER))
 			{
-				for (L2Effect e : _cubic.getOwner().getAllEffects())
+				for (BuffInfo info : _cubic.getOwner().getEffectList().getDebuffs().values())
 				{
-					if ((e != null) && e.getSkill().isDebuff() && e.getSkill().canBeDispeled())
+					if (info.getSkill().canBeDispeled())
 					{
-						UseCubicCure = true;
-						e.exit();
+						useCubicCure = true;
+						info.getEffected().getEffectList().stopSkillEffects(true, info.getSkill());
 					}
 				}
 			}
 			
-			if (UseCubicCure)
+			if (useCubicCure)
 			{
 				// Smart Cubic debuff cancel is needed, no other skill is used in this activation period
 				MagicSkillUse msu = new MagicSkillUse(_cubic.getOwner(), _cubic.getOwner(), L2CubicInstance.SKILL_CUBIC_CURE, 1, 0, 0);
@@ -119,7 +120,7 @@ public final class CubicAction implements Runnable
 			}
 			else if (Rnd.get(1, 100) < _chance)
 			{
-				skill = _cubic.getSkills().get(Rnd.get(_cubic.getSkills().size()));
+				L2Skill skill = _cubic.getSkills().get(Rnd.get(_cubic.getSkills().size()));
 				if (skill != null)
 				{
 					if (skill.getId() == L2CubicInstance.SKILL_CUBIC_HEAL)
@@ -160,7 +161,7 @@ public final class CubicAction implements Runnable
 							{
 								_log.info("L2CubicInstance: Action.run() handler " + type);
 							}
-							_cubic.useCubicContinuous(_cubic, skill, targets);
+							_cubic.useCubicContinuous(skill, targets);
 						}
 						else
 						{
@@ -193,7 +194,7 @@ public final class CubicAction implements Runnable
 							{
 								_log.info("L2CubicInstance: Action.run() handler " + type);
 							}
-							_cubic.useCubicDisabler(type, _cubic, skill, targets);
+							_cubic.useCubicDisabler(type, skill, targets);
 						}
 						else if (skill.hasEffectType(L2EffectType.DMG_OVER_TIME, L2EffectType.DMG_OVER_TIME_PERCENT))
 						{
@@ -201,7 +202,7 @@ public final class CubicAction implements Runnable
 							{
 								_log.info("L2CubicInstance: Action.run() handler " + type);
 							}
-							_cubic.useCubicContinuous(_cubic, skill, targets);
+							_cubic.useCubicContinuous(skill, targets);
 						}
 						else if (skill.hasEffectType(L2EffectType.AGGRESSION))
 						{
@@ -209,7 +210,7 @@ public final class CubicAction implements Runnable
 							{
 								_log.info("L2CubicInstance: Action.run() handler " + type);
 							}
-							_cubic.useCubicDisabler(type, _cubic, skill, targets);
+							_cubic.useCubicDisabler(type, skill, targets);
 						}
 						
 						// The cubic has done an action, increase the current count

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/buylist/Product.java

@@ -35,7 +35,7 @@ import com.l2jserver.gameserver.model.items.L2Item;
  */
 public final class Product
 {
-	private final static Logger _log = Logger.getLogger(Product.class.getName());
+	private static final Logger _log = Logger.getLogger(Product.class.getName());
 	
 	private final int _buyListId;
 	private final L2Item _item;

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/model/conditions/ConditionPlayerActiveEffectId.java

@@ -18,7 +18,7 @@
  */
 package com.l2jserver.gameserver.model.conditions;
 
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.stats.Env;
 
 /**
@@ -54,7 +54,7 @@ public class ConditionPlayerActiveEffectId extends Condition
 	@Override
 	public boolean testImpl(Env env)
 	{
-		final L2Effect e = env.getCharacter().getFirstEffect(_effectId);
-		return ((e != null) && ((_effectLvl == -1) || (_effectLvl <= e.getSkill().getLevel())));
+		final BuffInfo info = env.getCharacter().getEffectList().getBuffInfoBySkillId(_effectId);
+		return ((info != null) && ((_effectLvl == -1) || (_effectLvl <= info.getSkill().getLevel())));
 	}
 }

+ 71 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/conditions/ConditionPlayerCanSummon.java

@@ -0,0 +1,71 @@
+/*
+ * 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.conditions;
+
+import com.l2jserver.Config;
+import com.l2jserver.gameserver.datatables.CharSummonTable;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.stats.Env;
+import com.l2jserver.gameserver.network.SystemMessageId;
+
+/**
+ * Player Can Summon condition implementation.
+ * @author Zoey76
+ */
+public class ConditionPlayerCanSummon extends Condition
+{
+	private final boolean _val;
+	
+	public ConditionPlayerCanSummon(boolean val)
+	{
+		_val = val;
+	}
+	
+	@Override
+	public boolean testImpl(Env env)
+	{
+		final L2PcInstance player = env.getPlayer();
+		if (player == null)
+		{
+			return false;
+		}
+		
+		boolean canSummon = true;
+		if (Config.RESTORE_SERVITOR_ON_RECONNECT && CharSummonTable.getInstance().getServitors().containsKey(player.getObjectId()))
+		{
+			player.sendPacket(SystemMessageId.SUMMON_ONLY_ONE);
+			canSummon = false;
+		}
+		else if (Config.RESTORE_PET_ON_RECONNECT && CharSummonTable.getInstance().getPets().containsKey(player.getObjectId()))
+		{
+			player.sendPacket(SystemMessageId.SUMMON_ONLY_ONE);
+			canSummon = false;
+		}
+		else if (player.hasSummon())
+		{
+			player.sendPacket(SystemMessageId.SUMMON_ONLY_ONE);
+			canSummon = false;
+		}
+		else if (player.isFlyingMounted() || player.isMounted())
+		{
+			canSummon = false;
+		}
+		return (_val == canSummon);
+	}
+}

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/model/conditions/ConditionTargetActiveEffectId.java

@@ -18,7 +18,7 @@
  */
 package com.l2jserver.gameserver.model.conditions;
 
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.stats.Env;
 
 /**
@@ -53,8 +53,8 @@ public class ConditionTargetActiveEffectId extends Condition
 	@Override
 	public boolean testImpl(Env env)
 	{
-		final L2Effect e = env.getTarget().getFirstEffect(_effectId);
-		if ((e != null) && ((_effectLvl == -1) || (_effectLvl <= e.getSkill().getLevel())))
+		final BuffInfo info = env.getTarget().getEffectList().getBuffInfoBySkillId(_effectId);
+		if ((info != null) && ((_effectLvl == -1) || (_effectLvl <= info.getSkill().getLevel())))
 		{
 			return true;
 		}

+ 363 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/AbstractEffect.java

@@ -0,0 +1,363 @@
+/*
+ * 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.effects;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.l2jserver.gameserver.handler.EffectHandler;
+import com.l2jserver.gameserver.model.ChanceCondition;
+import com.l2jserver.gameserver.model.StatsSet;
+import com.l2jserver.gameserver.model.conditions.Condition;
+import com.l2jserver.gameserver.model.interfaces.IChanceSkillTrigger;
+import com.l2jserver.gameserver.model.skills.AbnormalVisualEffect;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
+import com.l2jserver.gameserver.model.skills.funcs.Func;
+import com.l2jserver.gameserver.model.skills.funcs.FuncTemplate;
+import com.l2jserver.gameserver.model.stats.Env;
+
+/**
+ * Abstract effect implementation.
+ * @author Zoey76
+ */
+public abstract class AbstractEffect implements IChanceSkillTrigger
+{
+	protected static final Logger _log = Logger.getLogger(AbstractEffect.class.getName());
+	
+	// Conditions
+	private final Condition _attachCond;
+	// private final Condition _applyCond; // TODO: Use or cleanup.
+	// Abnormal visual effect
+	private final AbnormalVisualEffect _abnormalEffect;
+	private final AbnormalVisualEffect[] _specialEffect;
+	private final AbnormalVisualEffect _eventEffect;
+	private List<FuncTemplate> _funcTemplates;
+	private final String _name;
+	private final double _val;
+	private final boolean _isSelfEffect;
+	/** Ticks. */
+	private final int _ticks;
+	private final int _triggeredId;
+	private final int _triggeredLevel;
+	private final ChanceCondition _chanceCondition;
+	private final StatsSet _parameters;
+	
+	/**
+	 * Abstract effect constructor.
+	 * @param attachCond
+	 * @param applyCond
+	 * @param set
+	 * @param params
+	 */
+	protected AbstractEffect(Condition attachCond, Condition applyCond, StatsSet set, StatsSet params)
+	{
+		_attachCond = attachCond;
+		// _applyCond = applyCond;
+		_name = set.getString("name");
+		_val = set.getDouble("val", 0);
+		_isSelfEffect = set.getInt("self", 0) == 1;
+		_ticks = set.getInt("ticks", 0);
+		_abnormalEffect = AbnormalVisualEffect.getByName(set.getString("abnormalVisualEffect", ""));
+		final String[] specialEffects = set.getString("special", "").split(",");
+		_specialEffect = new AbnormalVisualEffect[specialEffects.length];
+		for (int i = 0; i < specialEffects.length; i++)
+		{
+			_specialEffect[i] = AbnormalVisualEffect.getByName(specialEffects[i]);
+		}
+		_eventEffect = AbnormalVisualEffect.getByName(set.getString("event", ""));
+		_triggeredId = set.getInt("triggeredId", 0);
+		_triggeredLevel = set.getInt("triggeredLevel", 1);
+		_chanceCondition = ChanceCondition.parse(set.getString("chanceType", null), set.getInt("activationChance", -1), set.getInt("activationMinDamage", -1), set.getString("activationElements", null), set.getString("activationSkills", null), set.getBoolean("pvpChanceOnly", false));
+		_parameters = params;
+	}
+	
+	public static final AbstractEffect createEffect(Condition attachCond, Condition applyCond, StatsSet set, StatsSet params)
+	{
+		final String name = set.getString("name");
+		final Class<? extends AbstractEffect> handler = EffectHandler.getInstance().getHandler(name);
+		if (handler == null)
+		{
+			_log.warning(AbstractEffect.class.getSimpleName() + ": Requested unexistent effect handler: " + name);
+			return null;
+		}
+		
+		final Constructor<?> constructor;
+		try
+		{
+			constructor = handler.getConstructor(Condition.class, Condition.class, StatsSet.class, StatsSet.class);
+		}
+		catch (NoSuchMethodException | SecurityException e1)
+		{
+			_log.warning(AbstractEffect.class.getSimpleName() + ": Requested unexistent constructor for effect handler: " + name);
+			e1.printStackTrace();
+			return null;
+		}
+		
+		try
+		{
+			return (AbstractEffect) constructor.newInstance(attachCond, applyCond, set, params);
+		}
+		catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
+		{
+			e.printStackTrace();
+		}
+		return null;
+	}
+	
+	/**
+	 * Tests the attach condition.
+	 * @param env the data
+	 * @return {@code true} if there isn't a condition to test or it's passed, {@code false} otherwise
+	 */
+	public boolean testConditions(Env env)
+	{
+		return (_attachCond == null) || _attachCond.test(env);
+	}
+	
+	/**
+	 * Attachs a function template.
+	 * @param f the function
+	 */
+	public void attach(FuncTemplate f)
+	{
+		if (_funcTemplates == null)
+		{
+			_funcTemplates = new ArrayList<>(1);
+		}
+		_funcTemplates.add(f);
+	}
+	
+	/**
+	 * Gets the effect name.
+	 * @return the name
+	 */
+	public String getName()
+	{
+		return _name;
+	}
+	
+	/**
+	 * Verify if this is a self-effect.
+	 * @return {@code true} if it is a self-effect, {@code false} otherwise
+	 */
+	public boolean isSelfEffect()
+	{
+		return _isSelfEffect;
+	}
+	
+	/**
+	 * Gets the generic value.
+	 * @return the value
+	 */
+	public double getValue()
+	{
+		return _val;
+	}
+	
+	/**
+	 * Gets the effect ticks
+	 * @return the ticks
+	 */
+	public int getTicks()
+	{
+		return _ticks;
+	}
+	
+	public AbnormalVisualEffect getAbnormalEffect()
+	{
+		return _abnormalEffect;
+	}
+	
+	public AbnormalVisualEffect[] getSpecialEffect()
+	{
+		return _specialEffect;
+	}
+	
+	public AbnormalVisualEffect getEventEffect()
+	{
+		return _eventEffect;
+	}
+	
+	public List<FuncTemplate> getFuncTemplates()
+	{
+		return _funcTemplates;
+	}
+	
+	@Override
+	public int getTriggeredChanceId()
+	{
+		return _triggeredId;
+	}
+	
+	@Override
+	public int getTriggeredChanceLevel()
+	{
+		return _triggeredLevel;
+	}
+	
+	@Override
+	public ChanceCondition getTriggeredChanceCondition()
+	{
+		return _chanceCondition;
+	}
+	
+	/**
+	 * Verify if this effect template has parameters.
+	 * @return {@code true} if this effect template has parameters, {@code false} otherwise
+	 */
+	public boolean hasParameters()
+	{
+		return _parameters != null;
+	}
+	
+	/**
+	 * Get the parameters.
+	 * @return the parameters of this effect template
+	 */
+	public StatsSet getParameters()
+	{
+		return _parameters;
+	}
+	
+	/**
+	 * Calculates whether this effects land or not.<br>
+	 * If it lands will be scheduled and added to the character effect list.<br>
+	 * Override in effect implementation to change behavior. <br>
+	 * <b>Warning:</b> Must be used only for instant effects continuous effects will not call this they have their success handled by activate_rate.
+	 * @param info the buff info
+	 * @return {@code true} if this effect land, {@code false} otherwise
+	 */
+	public boolean calcSuccess(BuffInfo info)
+	{
+		return true;
+	}
+	
+	/**
+	 * Get this effect's type.<br>
+	 * TODO: Remove.
+	 * @return the effect type
+	 */
+	public L2EffectType getEffectType()
+	{
+		return L2EffectType.NONE;
+	}
+	
+	/**
+	 * Called on effect start.
+	 * @param info the buff info
+	 * @return {@code true} if all the start conditions are meet, {@code false} otherwise
+	 */
+	public boolean onStart(BuffInfo info)
+	{
+		return true;
+	}
+	
+	/**
+	 * Called on each tick.<br>
+	 * If the abnormal time is lesser than zero it will last forever.
+	 * @param info the buff info
+	 * @return if {@code true} this effect will continue forever, if {@code false} it will stop after abnormal time has passed
+	 */
+	public boolean onActionTime(BuffInfo info)
+	{
+		return false;
+	}
+	
+	/**
+	 * Called when the effect is exited.
+	 * @param info the buff info
+	 */
+	public void onExit(BuffInfo info)
+	{
+		
+	}
+	
+	/**
+	 * Get this effect's stats functions.
+	 * @param env the data
+	 * @return a list of stat functions.
+	 */
+	public List<Func> getStatFuncs(Env env)
+	{
+		if (getFuncTemplates() == null)
+		{
+			return Collections.<Func> emptyList();
+		}
+		
+		final List<Func> funcs = new ArrayList<>(getFuncTemplates().size());
+		for (FuncTemplate t : getFuncTemplates())
+		{
+			final Func f = t.getFunc(env, this);
+			if (f != null)
+			{
+				funcs.add(f);
+			}
+		}
+		return funcs;
+	}
+	
+	/**
+	 * Get the effect flags.
+	 * @return bit flag for current effect
+	 */
+	public int getEffectFlags()
+	{
+		return EffectFlag.NONE.getMask();
+	}
+	
+	@Override
+	public String toString()
+	{
+		return "Effect " + _name;
+	}
+	
+	public void decreaseForce()
+	{
+		
+	}
+	
+	public void increaseEffect()
+	{
+		
+	}
+	
+	public boolean checkCondition(Object obj)
+	{
+		return true;
+	}
+	
+	@Override
+	public boolean triggersChanceSkill()
+	{
+		return _triggeredId > 0;
+	}
+	
+	/**
+	 * Verify if this effect is an instant effect.
+	 * @return {@code true} if this effect is instant, {@code false} otherwise
+	 */
+	public boolean isInstant()
+	{
+		return false;
+	}
+}

+ 22 - 5
L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/EffectState.java → L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/EffectTaskInfo.java

@@ -18,13 +18,30 @@
  */
 package com.l2jserver.gameserver.model.effects;
 
+import java.util.concurrent.ScheduledFuture;
+
 /**
- * Effect state enum.
+ * Effect Task Info DTO.
  * @author Zoey76
  */
-public enum EffectState
+public class EffectTaskInfo
 {
-	CREATED,
-	ACTING,
-	FINISHING
+	private final EffectTickTask _effectTask;
+	private final ScheduledFuture<?> _scheduledFuture;
+	
+	public EffectTaskInfo(EffectTickTask effectTask, ScheduledFuture<?> scheduledFuture)
+	{
+		_effectTask = effectTask;
+		_scheduledFuture = scheduledFuture;
+	}
+	
+	public EffectTickTask getEffectTask()
+	{
+		return _effectTask;
+	}
+	
+	public ScheduledFuture<?> getScheduledFuture()
+	{
+		return _scheduledFuture;
+	}
 }

+ 0 - 260
L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/EffectTemplate.java

@@ -1,260 +0,0 @@
-/*
- * 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.effects;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jserver.gameserver.handler.EffectHandler;
-import com.l2jserver.gameserver.model.ChanceCondition;
-import com.l2jserver.gameserver.model.StatsSet;
-import com.l2jserver.gameserver.model.conditions.Condition;
-import com.l2jserver.gameserver.model.skills.funcs.FuncTemplate;
-import com.l2jserver.gameserver.model.skills.funcs.Lambda;
-import com.l2jserver.gameserver.model.stats.Env;
-
-/**
- * Effect template class.
- * @author mkizub, Zoey76
- */
-public class EffectTemplate
-{
-	private static final Logger _log = Logger.getLogger(EffectTemplate.class.getName());
-	
-	private final Class<?> _handler;
-	private final Constructor<?> _constructor;
-	private final Condition _attachCond;
-	// private final Condition _applyCond; // TODO: Use or cleanup.
-	private final Lambda _lambda;
-	/** Effect's total tick count. */
-	private final int _totalTickCount;
-	/** Effect specific abnormal time. */
-	private final int _abnormalTime;
-	private final AbnormalEffect _abnormalEffect;
-	private final AbnormalEffect[] _specialEffect;
-	private final AbnormalEffect _eventEffect;
-	private List<FuncTemplate> _funcTemplates;
-	private final boolean _showIcon;
-	private final String _name;
-	private final int _triggeredId;
-	private final int _triggeredLevel;
-	private final ChanceCondition _chanceCondition;
-	private final StatsSet _parameters;
-	
-	public EffectTemplate(Condition attachCond, Condition applyCond, Lambda lambda, StatsSet set, StatsSet params)
-	{
-		_attachCond = attachCond;
-		// _applyCond = applyCond;
-		_lambda = lambda;
-		_name = set.getString("name");
-		_totalTickCount = set.getInt("ticks", 0);
-		_abnormalTime = set.getInt("abnormalTime", 0);
-		_abnormalEffect = AbnormalEffect.getByName(set.getString("abnormalVisualEffect", ""));
-		final String[] specialEffects = set.getString("special", "").split(",");
-		_specialEffect = new AbnormalEffect[specialEffects.length];
-		for (int i = 0; i < specialEffects.length; i++)
-		{
-			_specialEffect[i] = AbnormalEffect.getByName(specialEffects[i]);
-		}
-		_eventEffect = AbnormalEffect.getByName(set.getString("event", ""));
-		_showIcon = set.getInt("noicon", 0) == 0;
-		_triggeredId = set.getInt("triggeredId", 0);
-		_triggeredLevel = set.getInt("triggeredLevel", 1);
-		_chanceCondition = ChanceCondition.parse(set.getString("chanceType", null), set.getInt("activationChance", -1), set.getInt("activationMinDamage", -1), set.getString("activationElements", null), set.getString("activationSkills", null), set.getBoolean("pvpChanceOnly", false));
-		_parameters = params;
-		_handler = EffectHandler.getInstance().getHandler(_name);
-		if (_handler == null)
-		{
-			throw new RuntimeException(getClass().getSimpleName() + ": Requested unexistent effect handler: " + _name);
-		}
-		
-		try
-		{
-			_constructor = _handler.getConstructor(Env.class, EffectTemplate.class);
-		}
-		catch (NoSuchMethodException e)
-		{
-			throw new RuntimeException(e);
-		}
-	}
-	
-	public L2Effect getEffect(Env env)
-	{
-		return getEffect(env, false);
-	}
-	
-	public L2Effect getEffect(Env env, boolean ignoreTest)
-	{
-		if (!ignoreTest && ((_attachCond != null) && !_attachCond.test(env)))
-		{
-			return null;
-		}
-		
-		try
-		{
-			return (L2Effect) _constructor.newInstance(env, this);
-		}
-		catch (IllegalAccessException | InstantiationException e)
-		{
-			_log.log(Level.WARNING, "", e);
-			return null;
-		}
-		catch (InvocationTargetException e)
-		{
-			_log.log(Level.WARNING, "Error creating new instance of Class " + _handler + " Exception was: " + e.getTargetException().getMessage(), e.getTargetException());
-			return null;
-		}
-	}
-	
-	/**
-	 * Creates an L2Effect instance from an existing one and an Env object.
-	 * @param env
-	 * @param stolen
-	 * @return the stolen effect
-	 */
-	public L2Effect getStolenEffect(Env env, L2Effect stolen)
-	{
-		Constructor<?> stolenCons;
-		try
-		{
-			stolenCons = _handler.getConstructor(Env.class, L2Effect.class);
-		}
-		catch (NoSuchMethodException e)
-		{
-			throw new RuntimeException(e);
-		}
-		
-		try
-		{
-			final L2Effect effect = (L2Effect) stolenCons.newInstance(env, stolen);
-			// if (_applyCond != null)
-			// {
-			// effect.setCondition(_applyCond);
-			// }
-			return effect;
-		}
-		catch (IllegalAccessException | InstantiationException e)
-		{
-			_log.log(Level.WARNING, "", e);
-			return null;
-		}
-		catch (InvocationTargetException e)
-		{
-			_log.log(Level.WARNING, "Error creating new instance of Class " + _handler + " Exception was: " + e.getTargetException().getMessage(), e.getTargetException());
-			return null;
-		}
-	}
-	
-	public void attach(FuncTemplate f)
-	{
-		if (_funcTemplates == null)
-		{
-			_funcTemplates = new ArrayList<>(1);
-		}
-		_funcTemplates.add(f);
-	}
-	
-	public Lambda getLambda()
-	{
-		return _lambda;
-	}
-	
-	public int getTotalTickCount()
-	{
-		return _totalTickCount;
-	}
-	
-	public int getAbnormalTime()
-	{
-		return _abnormalTime;
-	}
-	
-	public String getName()
-	{
-		return _name;
-	}
-	
-	public AbnormalEffect getAbnormalEffect()
-	{
-		return _abnormalEffect;
-	}
-	
-	public AbnormalEffect[] getSpecialEffect()
-	{
-		return _specialEffect;
-	}
-	
-	public AbnormalEffect getEventEffect()
-	{
-		return _eventEffect;
-	}
-	
-	public List<FuncTemplate> getFuncTemplates()
-	{
-		return _funcTemplates;
-	}
-	
-	public boolean isIconDisplay()
-	{
-		return _showIcon;
-	}
-	
-	public int getTriggeredId()
-	{
-		return _triggeredId;
-	}
-	
-	public int getTriggeredLevel()
-	{
-		return _triggeredLevel;
-	}
-	
-	public ChanceCondition getChanceCondition()
-	{
-		return _chanceCondition;
-	}
-	
-	/**
-	 * Get the parameters.
-	 * @return the parameters of this effect template
-	 */
-	public StatsSet getParameters()
-	{
-		return _parameters;
-	}
-	
-	/**
-	 * Verify if this effect template has parameters.
-	 * @return {@code true} if this effect template has parameters, {@code false} otherwise
-	 */
-	public boolean hasParameters()
-	{
-		return _parameters != null;
-	}
-	
-	@Override
-	public String toString()
-	{
-		return "Effect template[" + _handler + "]";
-	}
-}

+ 78 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/EffectTickTask.java

@@ -0,0 +1,78 @@
+/*
+ * 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.effects;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.l2jserver.gameserver.model.skills.BuffInfo;
+
+/**
+ * Effect tick task.
+ * @author Zoey76
+ */
+public class EffectTickTask implements Runnable
+{
+	private final BuffInfo _info;
+	private final AbstractEffect _effect;
+	private final AtomicInteger _tickCount = new AtomicInteger();
+	
+	/**
+	 * EffectTickTask constructor.
+	 * @param info the buff info
+	 * @param effect the effect
+	 */
+	public EffectTickTask(BuffInfo info, AbstractEffect effect)
+	{
+		_info = info;
+		_effect = effect;
+	}
+	
+	/**
+	 * Gets the buff info.
+	 * @return the buff info
+	 */
+	public BuffInfo getBuffInfo()
+	{
+		return _info;
+	}
+	
+	/**
+	 * Gets the effect.
+	 * @return the effect
+	 */
+	public AbstractEffect getEffect()
+	{
+		return _effect;
+	}
+	
+	/**
+	 * Gets the current tick count.
+	 * @return the tick count
+	 */
+	public int getTickCount()
+	{
+		return _tickCount.get();
+	}
+	
+	@Override
+	public void run()
+	{
+		_info.onTick(_effect, _tickCount.incrementAndGet());
+	}
+}

+ 0 - 720
L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/L2Effect.java

@@ -1,720 +0,0 @@
-/*
- * 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.effects;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jserver.gameserver.GameTimeController;
-import com.l2jserver.gameserver.ThreadPoolManager;
-import com.l2jserver.gameserver.datatables.SkillTable;
-import com.l2jserver.gameserver.model.ChanceCondition;
-import com.l2jserver.gameserver.model.actor.L2Character;
-import com.l2jserver.gameserver.model.interfaces.IChanceSkillTrigger;
-import com.l2jserver.gameserver.model.skills.L2Skill;
-import com.l2jserver.gameserver.model.skills.funcs.Func;
-import com.l2jserver.gameserver.model.skills.funcs.FuncTemplate;
-import com.l2jserver.gameserver.model.skills.funcs.Lambda;
-import com.l2jserver.gameserver.model.stats.Env;
-import com.l2jserver.gameserver.model.stats.Formulas;
-import com.l2jserver.gameserver.network.SystemMessageId;
-import com.l2jserver.gameserver.network.serverpackets.AbnormalStatusUpdate;
-import com.l2jserver.gameserver.network.serverpackets.ExOlympiadSpelledInfo;
-import com.l2jserver.gameserver.network.serverpackets.MagicSkillLaunched;
-import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
-import com.l2jserver.gameserver.network.serverpackets.PartySpelled;
-import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
-
-/**
- * Abstract effect implementation.
- * @author Zoey76
- */
-public abstract class L2Effect implements IChanceSkillTrigger
-{
-	protected static final Logger _log = Logger.getLogger(L2Effect.class.getName());
-	/** The character that creates this effect. */
-	private final L2Character _effector;
-	/** The character that is affected by this effect. */
-	private final L2Character _effected;
-	/** The skill that launched this effect. */
-	private final L2Skill _skill;
-	/** The value on an update. */
-	private final Lambda _lambda;
-	/** The current state. */
-	private EffectState _state;
-	/** The game ticks at the start of this effect. */
-	protected int _periodStartTicks;
-	protected int _periodFirstTime;
-	/** The effect template. */
-	private final EffectTemplate _template;
-	/** Effect tick count. */
-	private int _tickCount;
-	/** Effect's abnormal time. */
-	private final int _abnormalTime;
-	/** If {@code true} then it's a self-effect. */
-	private boolean _isSelfEffect = false;
-	/** If {@code true} then prevent exit update. */
-	private boolean _preventExitUpdate;
-	private volatile ScheduledFuture<?> _currentFuture;
-	/** If {@code true} then this effect is in use. */
-	private boolean _inUse = false;
-	/** If {@code true} then this effect's start condition are meet. */
-	private boolean _startConditionsCorrect = true;
-	/** If {@code true} then this effect has been cancelled. */
-	private boolean _isRemoved = false;
-	
-	protected final class EffectTask implements Runnable
-	{
-		@Override
-		public void run()
-		{
-			try
-			{
-				_periodFirstTime = 0;
-				_periodStartTicks = GameTimeController.getInstance().getGameTicks();
-				scheduleEffect();
-			}
-			catch (Exception e)
-			{
-				_log.log(Level.SEVERE, "", e);
-			}
-		}
-	}
-	
-	/**
-	 * @param env DTO with required data
-	 * @param template the effect template
-	 */
-	protected L2Effect(Env env, EffectTemplate template)
-	{
-		_state = EffectState.CREATED;
-		_skill = env.getSkill();
-		_template = template;
-		_effected = env.getTarget();
-		_effector = env.getCharacter();
-		_lambda = template.getLambda();
-		_tickCount = 0;
-		_abnormalTime = Formulas.calcEffectAbnormalTime(env, template);
-		_periodStartTicks = GameTimeController.getInstance().getGameTicks();
-		_periodFirstTime = 0;
-	}
-	
-	/**
-	 * Special constructor to "steal" buffs.<br>
-	 * Must be implemented on every child class that can be stolen.
-	 * @param env DTO with required data
-	 * @param effect the stolen effect, used as "template"
-	 */
-	protected L2Effect(Env env, L2Effect effect)
-	{
-		_template = effect._template;
-		_state = EffectState.CREATED;
-		_skill = env.getSkill();
-		_effected = env.getTarget();
-		_effector = env.getCharacter();
-		_lambda = _template.getLambda();
-		_tickCount = effect.getTickCount();
-		_abnormalTime = effect.getAbnormalTime();
-		_periodStartTicks = effect.getPeriodStartTicks();
-		_periodFirstTime = effect.getTime();
-	}
-	
-	/**
-	 * Get the current tick count.
-	 * @return the tick count
-	 */
-	public int getTickCount()
-	{
-		return _tickCount;
-	}
-	
-	public void setCount(int newTickCount)
-	{
-		_tickCount = Math.min(newTickCount, _template.getTotalTickCount());
-	}
-	
-	public void setFirstTime(int newFirstTime)
-	{
-		_periodFirstTime = Math.min(newFirstTime, _abnormalTime);
-		_periodStartTicks -= _periodFirstTime * GameTimeController.TICKS_PER_SECOND;
-	}
-	
-	/**
-	 * Verify if this effect display an icon.
-	 * @return {@code true} if this effect display an icon, {@code false} otherwise
-	 */
-	public boolean isIconDisplay()
-	{
-		return _template.isIconDisplay();
-	}
-	
-	/**
-	 * Get this effect's calculated abnormal time.
-	 * @return the abnormal time
-	 */
-	public int getAbnormalTime()
-	{
-		return _abnormalTime;
-	}
-	
-	/**
-	 * Get the elapsed time from the beginning of this effect.
-	 * @return the elapsed time
-	 */
-	public int getTime()
-	{
-		return (GameTimeController.getInstance().getGameTicks() - _periodStartTicks) / GameTimeController.TICKS_PER_SECOND;
-	}
-	
-	/**
-	 * Get the remaining time.
-	 * @return the remaining time
-	 */
-	public int getTimeLeft()
-	{
-		if (_template.getTotalTickCount() > 1)
-		{
-			return (((_template.getTotalTickCount() - _tickCount) + 1) * (_abnormalTime / _template.getTotalTickCount())) - getTime();
-		}
-		return _abnormalTime - getTime();
-	}
-	
-	/**
-	 * Verify if the effect is in use.
-	 * @return {@code true} if the effect is in use, {@code false} otherwise
-	 */
-	public boolean isInUse()
-	{
-		return _inUse;
-	}
-	
-	/**
-	 * Set the effect in use.<br>
-	 * If is set to {@code true}, {@link #onStart()} is invoked, otherwise {@link #onExit()} is invoked.
-	 * @param inUse the value to set
-	 * @return {@link #_startConditionsCorrect}
-	 */
-	public boolean setInUse(boolean inUse)
-	{
-		_inUse = inUse;
-		if (_inUse)
-		{
-			_startConditionsCorrect = onStart();
-		}
-		else
-		{
-			onExit();
-		}
-		return _startConditionsCorrect;
-	}
-	
-	/**
-	 * Get the skill that launched this effect.
-	 * @return the skill related to this effect
-	 */
-	public final L2Skill getSkill()
-	{
-		return _skill;
-	}
-	
-	/**
-	 * Get the character that evoked this effect.
-	 * @return the effector
-	 */
-	public final L2Character getEffector()
-	{
-		return _effector;
-	}
-	
-	/**
-	 * Get the character that received this effect.
-	 * @return the effected
-	 */
-	public final L2Character getEffected()
-	{
-		return _effected;
-	}
-	
-	public boolean isSelfEffect()
-	{
-		return _isSelfEffect;
-	}
-	
-	public void setSelfEffect()
-	{
-		_isSelfEffect = true;
-	}
-	
-	public final double calc()
-	{
-		final Env env = new Env();
-		env.setCharacter(_effector);
-		env.setTarget(_effected);
-		env.setSkill(_skill);
-		return _lambda.calc(env);
-	}
-	
-	/**
-	 * Calculates whether this effects land or not.<br>
-	 * If it lands will be scheduled and added to the character effect list.<br>
-	 * Override in effect implementation to change behavior. <br>
-	 * <b>Warning:</b> Must be used only for instant effects continuous effects will <br>
-	 * not call this they have their success handled by activate_rate
-	 * @return {@code true} if this effect land, {@code false} otherwise
-	 */
-	public boolean calcSuccess()
-	{
-		return true;
-	}
-	
-	/**
-	 * Start the effect task.<br>
-	 * If the effect has ticks defined it will be scheduled.<br>
-	 * If abnormal time is defined (greater than 1) the period will be calculated like abnormal time divided total tick count.<br>
-	 * Otherwise it each tick will represent 1 second (1000 milliseconds).
-	 */
-	private final void startEffectTask()
-	{
-		stopEffectTask();
-		
-		if (isInstant())
-		{
-			_currentFuture = ThreadPoolManager.getInstance().scheduleEffect(new EffectTask(), 5);
-			return;
-		}
-		
-		final int delay = Math.max((_abnormalTime - _periodFirstTime) * 1000, 5); // Sanity check
-		if (_template.getTotalTickCount() > 0)
-		{
-			// TODO: If default abnormal time is changed to 0, the first check below must be updated as well.
-			final int period = ((_abnormalTime > 1) ? Math.max(_abnormalTime / _template.getTotalTickCount(), 1) : _template.getTotalTickCount()) * 1000;
-			_currentFuture = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(new EffectTask(), delay / period, period);
-		}
-		else
-		{
-			_currentFuture = ThreadPoolManager.getInstance().scheduleEffect(new EffectTask(), delay);
-		}
-	}
-	
-	/**
-	 * Exit this effect without preventing an update.
-	 */
-	public final void exit()
-	{
-		exit(false);
-	}
-	
-	/**
-	 * Exit this effect.
-	 * @param preventExitUpdate
-	 */
-	public final void exit(boolean preventExitUpdate)
-	{
-		_preventExitUpdate = preventExitUpdate;
-		_state = EffectState.FINISHING;
-		scheduleEffect();
-	}
-	
-	/**
-	 * Stop the task of this effect, remove it and update client magic icon.
-	 */
-	public final void stopEffectTask()
-	{
-		if (_currentFuture != null)
-		{
-			// Cancel the task
-			_currentFuture.cancel(false);
-			_currentFuture = null;
-			
-			if (getEffected() != null)
-			{
-				getEffected().getEffectList().remove(this);
-			}
-		}
-	}
-	
-	/**
-	 * Get this effect's type.
-	 * @return the effect type
-	 */
-	public abstract L2EffectType getEffectType();
-	
-	/**
-	 * Notify started.
-	 * @return {@code true} if all the start conditions are meet, {@code false} otherwise
-	 */
-	public boolean onStart()
-	{
-		if (_template.getAbnormalEffect() != AbnormalEffect.NULL)
-		{
-			getEffected().startAbnormalEffect(_template.getAbnormalEffect());
-		}
-		if (_template.getSpecialEffect() != null)
-		{
-			getEffected().startSpecialEffect(_template.getSpecialEffect());
-		}
-		if ((_template.getEventEffect() != AbnormalEffect.NULL) && getEffected().isPlayer())
-		{
-			getEffected().getActingPlayer().startEventEffect(_template.getEventEffect());
-		}
-		return true;
-	}
-	
-	/**
-	 * Cancel the effect in the the abnormal effect map of the effected L2Character.
-	 */
-	public void onExit()
-	{
-		if (_template.getAbnormalEffect() != AbnormalEffect.NULL)
-		{
-			getEffected().stopAbnormalEffect(_template.getAbnormalEffect());
-		}
-		if (_template.getSpecialEffect() != null)
-		{
-			getEffected().stopSpecialEffect(_template.getSpecialEffect());
-		}
-		if ((_template.getEventEffect() != AbnormalEffect.NULL) && getEffected().isPlayer())
-		{
-			getEffected().getActingPlayer().stopEventEffect(_template.getEventEffect());
-		}
-	}
-	
-	/**
-	 * Method called on each tick.<br>
-	 * By default if the abnormal time is lesser than zero it will return {@code true}, this means the effect will last forever.
-	 * @return if {@code true} this effect will continue forever, if {@code false} it will stop after tick count is reached
-	 */
-	public boolean onActionTime()
-	{
-		return getAbnormalTime() < 0;
-	}
-	
-	/**
-	 * Schedule this effect.
-	 */
-	public final void scheduleEffect()
-	{
-		switch (_state)
-		{
-			case CREATED:
-			{
-				_state = isInstant() ? EffectState.FINISHING : EffectState.ACTING;
-				
-				if (_skill.isBad() && isIconDisplay() && getEffected().isPlayer())
-				{
-					final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT);
-					sm.addSkillName(_skill);
-					getEffected().sendPacket(sm);
-				}
-				
-				if (_abnormalTime != 0)
-				{
-					startEffectTask();
-					return;
-				}
-				_startConditionsCorrect = onStart();
-			}
-			case ACTING:
-			{
-				if (isInUse())
-				{
-					_tickCount++; // Increase tick count.
-					if (onActionTime() && _startConditionsCorrect)
-					{
-						return; // Do not finish.
-					}
-				}
-				
-				if (_tickCount <= _template.getTotalTickCount())
-				{
-					return; // Do not finish it yet, has remaining ticks.
-				}
-				
-				_state = EffectState.FINISHING;
-			}
-			case FINISHING:
-			{
-				// Message
-				if (getEffected().isPlayer() && isIconDisplay())
-				{
-					SystemMessageId smId = null;
-					if (getSkill().isToggle())
-					{
-						smId = SystemMessageId.S1_HAS_BEEN_ABORTED;
-					}
-					else if (isRemoved())
-					{
-						smId = SystemMessageId.EFFECT_S1_DISAPPEARED;
-					}
-					else if (_tickCount >= _template.getTotalTickCount())
-					{
-						smId = SystemMessageId.S1_HAS_WORN_OFF;
-					}
-					
-					if (smId != null)
-					{
-						final SystemMessage sm = SystemMessage.getSystemMessage(smId);
-						sm.addSkillName(getSkill());
-						getEffected().sendPacket(sm);
-					}
-				}
-				
-				// if task is null - stopEffectTask does not remove effect
-				if ((_currentFuture == null) && (getEffected() != null))
-				{
-					getEffected().getEffectList().remove(this);
-				}
-				
-				// Stop the task of this effect, remove it and update client magic icon.
-				stopEffectTask();
-				
-				// Cancel the effect in the the abnormal effect list of the character.
-				if (isInUse() || !((_tickCount > 1) || (_abnormalTime > 0)))
-				{
-					if (_startConditionsCorrect)
-					{
-						onExit();
-					}
-				}
-				
-				if (_skill.getAfterEffectId() > 0)
-				{
-					final L2Skill skill = SkillTable.getInstance().getInfo(_skill.getAfterEffectId(), _skill.getAfterEffectLvl());
-					if (skill != null)
-					{
-						getEffected().broadcastPacket(new MagicSkillUse(_effected, skill.getId(), skill.getLevel(), 0, 0));
-						getEffected().broadcastPacket(new MagicSkillLaunched(_effected, skill.getId(), skill.getLevel()));
-						skill.getEffects(getEffected(), getEffected());
-					}
-				}
-			}
-		}
-	}
-	
-	/**
-	 * Get this effect's stats functions.
-	 * @return a list of stat functions.
-	 */
-	public List<Func> getStatFuncs()
-	{
-		if (_template.getFuncTemplates() == null)
-		{
-			return Collections.<Func> emptyList();
-		}
-		
-		final List<Func> funcs = new ArrayList<>(_template.getFuncTemplates().size());
-		final Env env = new Env();
-		env.setCharacter(_effector);
-		env.setTarget(_effected);
-		env.setSkill(_skill);
-		for (FuncTemplate t : _template.getFuncTemplates())
-		{
-			final Func f = t.getFunc(env, this);
-			if (f != null)
-			{
-				funcs.add(f);
-			}
-		}
-		return funcs;
-	}
-	
-	/**
-	 * Add the abnormal status update data for this effect.
-	 * @param mi the abnormal status packet
-	 */
-	public final void addIcon(AbnormalStatusUpdate mi)
-	{
-		if (_state != EffectState.ACTING)
-		{
-			return;
-		}
-		
-		if (_abnormalTime == -1)
-		{
-			mi.addEffect(getSkill(), -1);
-		}
-		else
-		{
-			mi.addEffect(getSkill(), getTimeLeft());
-		}
-	}
-	
-	/**
-	 * Add the party spelled data for this effect.
-	 * @param ps the party spelled packet
-	 */
-	public final void addPartySpelledIcon(PartySpelled ps)
-	{
-		if (_state != EffectState.ACTING)
-		{
-			return;
-		}
-		
-		final ScheduledFuture<?> future = _currentFuture;
-		if (future != null)
-		{
-			ps.addPartySpelledEffect(getSkill(), (int) future.getDelay(TimeUnit.SECONDS));
-		}
-		else if (_abnormalTime == -1)
-		{
-			ps.addPartySpelledEffect(getSkill(), -1);
-		}
-	}
-	
-	/**
-	 * Add the olympiad spelled data for this effect.
-	 * @param os the olympiad spelled packet
-	 */
-	public final void addOlympiadSpelledIcon(ExOlympiadSpelledInfo os)
-	{
-		if (_state != EffectState.ACTING)
-		{
-			return;
-		}
-		
-		final ScheduledFuture<?> future = _currentFuture;
-		if (future != null)
-		{
-			os.addEffect(getSkill(), (int) future.getDelay(TimeUnit.SECONDS));
-		}
-		else if (_abnormalTime == -1)
-		{
-			os.addEffect(getSkill(), -1);
-		}
-	}
-	
-	public int getPeriodStartTicks()
-	{
-		return _periodStartTicks;
-	}
-	
-	/**
-	 * Get the effect template.
-	 * @return the effect template
-	 */
-	public EffectTemplate getEffectTemplate()
-	{
-		return _template;
-	}
-	
-	/**
-	 * TODO: Unhardcode skill Id.
-	 * @return {@code true} if effect itself can be stolen, {@code false} otherwise
-	 */
-	public boolean canBeStolen()
-	{
-		return !getSkill().isPassive() && !getSkill().isToggle() && !getSkill().isDebuff() && !getSkill().isHeroSkill() && !getSkill().isGMSkill() && !(getSkill().isStatic() && (getSkill().getId() != 2341)) && getSkill().canBeDispeled();
-	}
-	
-	/**
-	 * Get the effect flags.
-	 * @return bit flag for current effect
-	 */
-	public int getEffectFlags()
-	{
-		return EffectFlag.NONE.getMask();
-	}
-	
-	@Override
-	public String toString()
-	{
-		return "Effect " + getClass().getSimpleName() + ", " + _skill + ", State: " + _state + ", Time: " + _abnormalTime + ", Remaining: " + getTimeLeft();
-	}
-	
-	public void decreaseForce()
-	{
-		
-	}
-	
-	public void increaseEffect()
-	{
-		
-	}
-	
-	public boolean checkCondition(Object obj)
-	{
-		return true;
-	}
-	
-	@Override
-	public boolean triggersChanceSkill()
-	{
-		return false;
-	}
-	
-	@Override
-	public int getTriggeredChanceId()
-	{
-		return 0;
-	}
-	
-	@Override
-	public int getTriggeredChanceLevel()
-	{
-		return 0;
-	}
-	
-	@Override
-	public ChanceCondition getTriggeredChanceCondition()
-	{
-		return null;
-	}
-	
-	public boolean isPreventExitUpdate()
-	{
-		return _preventExitUpdate;
-	}
-	
-	public void setPreventExitUpdate(boolean val)
-	{
-		_preventExitUpdate = val;
-	}
-	
-	/**
-	 * Verify if this effect is an instant effect.
-	 * @return {@code true} if this effect is instant, {@code false} otherwise
-	 */
-	public boolean isInstant()
-	{
-		return false;
-	}
-	
-	/**
-	 * Verify if this effect has been cancelled.
-	 * @return {@code true} if this effect has been cancelled, {@code false} otherwise
-	 */
-	public boolean isRemoved()
-	{
-		return _isRemoved;
-	}
-	
-	/**
-	 * Set the effect to removed.
-	 * @param val the value to set
-	 */
-	public void setRemoved(boolean val)
-	{
-		_isRemoved = val;
-	}
-}

+ 0 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/L2EffectType.java

@@ -25,7 +25,6 @@ package com.l2jserver.gameserver.model.effects;
 public enum L2EffectType
 {
 	AGGRESSION,
-	ACTION_BLOCK,
 	BLOCK_RESURRECTION,
 	BUFF,
 	CHARM_OF_LUCK,
@@ -44,7 +43,6 @@ public enum L2EffectType
 	DMG_OVER_TIME_PERCENT,
 	DEATH_LINK,
 	ENERGY_ATTACK,
-	ENLARGE_ABNORMAL_SLOT,
 	FAKE_DEATH,
 	FATAL_BLOW,
 	FEAR,
@@ -52,7 +50,6 @@ public enum L2EffectType
 	HEAL,
 	HEAL_OVER_TIME,
 	HEAL_PERCENT,
-	HIDE,
 	HP_DRAIN,
 	INVINCIBLE,
 	LETHAL,
@@ -86,5 +83,4 @@ public enum L2EffectType
 	SUMMON_PET,
 	TELEPORT,
 	TELEPORT_TO_TARGET,
-	TRANSFORMATION,
 }

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/BlockCheckerEngine.java

@@ -395,15 +395,15 @@ public final class BlockCheckerEngine
 				
 				// Give the player start up effects
 				// Freeze
-				_freeze.getEffects(player, player);
+				_freeze.applyEffects(player, null, player, null, false, false);
 				// Transformation
 				if (_holder.getPlayerTeam(player) == 0)
 				{
-					_transformationRed.getEffects(player, player);
+					_transformationRed.applyEffects(player, null, player, null, false, false);
 				}
 				else
 				{
-					_transformationBlue.getEffects(player, player);
+					_transformationBlue.applyEffects(player, null, player, null, false, false);
 				}
 				// Set the current player arena
 				player.setBlockCheckerArena((byte) _arena);

+ 7 - 7
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/Duel.java

@@ -31,7 +31,7 @@ import com.l2jserver.gameserver.enums.DuelResult;
 import com.l2jserver.gameserver.instancemanager.DuelManager;
 import com.l2jserver.gameserver.model.Location;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.zone.ZoneId;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
@@ -107,7 +107,7 @@ public class Duel
 		private double _cp;
 		private boolean _paDuel;
 		private int _x, _y, _z;
-		private FastList<L2Effect> _debuffs;
+		private FastList<L2Skill> _debuffs;
 		
 		public PlayerCondition(L2PcInstance player, boolean partyDuel)
 		{
@@ -145,17 +145,17 @@ public class Duel
 			}
 			if (_debuffs != null) // Debuff removal
 			{
-				for (L2Effect temp : _debuffs)
+				for (L2Skill skill : _debuffs)
 				{
-					if (temp != null)
+					if (skill != null)
 					{
-						temp.exit();
+						_player.stopSkillEffects(true, skill.getId());
 					}
 				}
 			}
 		}
 		
-		public void registerDebuff(L2Effect debuff)
+		public void registerDebuff(L2Skill debuff)
 		{
 			if (_debuffs == null)
 			{
@@ -1047,7 +1047,7 @@ public class Duel
 		}
 	}
 	
-	public void onBuff(L2PcInstance player, L2Effect debuff)
+	public void onBuff(L2PcInstance player, L2Skill debuff)
 	{
 		for (PlayerCondition cond : _playerConditions)
 		{

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/entity/TvTEvent.java

@@ -1000,7 +1000,7 @@ public class TvTEvent
 					L2Skill skill = SkillTable.getInstance().getInfo(e.getKey(), e.getValue());
 					if (skill != null)
 					{
-						skill.getEffects(playerInstance, playerInstance);
+						skill.applyEffects(playerInstance, null, playerInstance, null, false, false);
 					}
 				}
 			}
@@ -1014,7 +1014,7 @@ public class TvTEvent
 					L2Skill skill = SkillTable.getInstance().getInfo(e.getKey(), e.getValue());
 					if (skill != null)
 					{
-						skill.getEffects(playerInstance, playerInstance);
+						skill.applyEffects(playerInstance, null, playerInstance, null, false, false);
 					}
 				}
 			}

+ 19 - 24
L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/L2Item.java

@@ -36,8 +36,7 @@ import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.conditions.Condition;
 import com.l2jserver.gameserver.model.conditions.ConditionLogicOr;
 import com.l2jserver.gameserver.model.conditions.ConditionPetType;
-import com.l2jserver.gameserver.model.effects.EffectTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
 import com.l2jserver.gameserver.model.interfaces.IIdentifiable;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
@@ -45,6 +44,7 @@ import com.l2jserver.gameserver.model.items.type.L2ActionType;
 import com.l2jserver.gameserver.model.items.type.L2EtcItemType;
 import com.l2jserver.gameserver.model.items.type.L2ItemType;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.funcs.Func;
 import com.l2jserver.gameserver.model.skills.funcs.FuncTemplate;
@@ -229,7 +229,7 @@ public abstract class L2Item implements IIdentifiable
 	protected int _type2; // different lists for armor, weapon, etc
 	protected Elementals[] _elementals = null;
 	protected List<FuncTemplate> _funcTemplates;
-	protected List<EffectTemplate> _effectTemplates;
+	protected List<AbstractEffect> _effects;
 	protected List<Condition> _preConditions;
 	private SkillHolder[] _skillHolder;
 	private SkillHolder _unequipSkill = null;
@@ -826,34 +826,29 @@ public abstract class L2Item implements IIdentifiable
 	}
 	
 	/**
-	 * Returns the effects associated with the item.
-	 * @param item : L2ItemInstance pointing out the item
-	 * @param player : L2Character pointing out the player
-	 * @return a list of effects generated by the item
+	 * Applies the effects from this item to the creature.
+	 * @param item the item
+	 * @param creature the creature
 	 */
-	public List<L2Effect> getEffects(L2ItemInstance item, L2Character player)
+	public void applyEffects(L2ItemInstance item, L2Character creature)
 	{
-		if ((_effectTemplates == null) || _effectTemplates.isEmpty())
+		if ((_effects == null) || _effects.isEmpty())
 		{
-			return Collections.<L2Effect> emptyList();
+			return;
 		}
 		
 		final Env env = new Env();
-		env.setCharacter(player);
-		env.setTarget(player);
+		env.setCharacter(creature);
+		env.setTarget(creature);
 		env.setItem(item);
-		
-		final List<L2Effect> effects = new ArrayList<>(_effectTemplates.size());
-		for (EffectTemplate et : _effectTemplates)
+		final BuffInfo info = new BuffInfo(env);
+		for (AbstractEffect effect : _effects)
 		{
-			L2Effect e = et.getEffect(env);
-			if (e != null)
+			if (effect.calcSuccess(info))
 			{
-				e.scheduleEffect();
-				effects.add(e);
+				effect.onStart(info);
 			}
 		}
-		return effects;
 	}
 	
 	/**
@@ -909,13 +904,13 @@ public abstract class L2Item implements IIdentifiable
 	 * Add the EffectTemplate effect to the list of effects generated by the item
 	 * @param effect : EffectTemplate
 	 */
-	public void attach(EffectTemplate effect)
+	public void attach(AbstractEffect effect)
 	{
-		if (_effectTemplates == null)
+		if (_effects == null)
 		{
-			_effectTemplates = new ArrayList<>(1);
+			_effects = new ArrayList<>(1);
 		}
-		_effectTemplates.add(effect);
+		_effects.add(effect);
 	}
 	
 	public final void attach(Condition c)

+ 9 - 18
L2J_Server_BETA/java/com/l2jserver/gameserver/model/items/L2Weapon.java

@@ -18,10 +18,7 @@
  */
 package com.l2jserver.gameserver.model.items;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
 
 import com.l2jserver.gameserver.enums.QuestEventType;
 import com.l2jserver.gameserver.handler.ISkillHandler;
@@ -33,7 +30,6 @@ import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.conditions.Condition;
 import com.l2jserver.gameserver.model.conditions.ConditionGameChance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
 import com.l2jserver.gameserver.model.items.type.L2WeaponType;
 import com.l2jserver.gameserver.model.quest.Quest;
@@ -325,13 +321,12 @@ public final class L2Weapon extends L2Item
 	 * @param caster the L2Character pointing out the caster
 	 * @param target the L2Character pointing out the target
 	 * @param crit the boolean tells whether the hit was critical
-	 * @return the effects of skills associated with the item to be triggered onHit.
 	 */
-	public List<L2Effect> getSkillEffects(L2Character caster, L2Character target, boolean crit)
+	public void getSkillEffects(L2Character caster, L2Character target, boolean crit)
 	{
 		if ((_skillsOnCrit == null) || !crit)
 		{
-			return Collections.<L2Effect> emptyList();
+			return;
 		}
 		
 		final L2Skill onCritSkill = _skillsOnCrit.getSkill();
@@ -344,32 +339,28 @@ public final class L2Weapon extends L2Item
 			if (!_skillsOnCritCondition.test(env))
 			{
 				// Chance not met
-				return Collections.<L2Effect> emptyList();
+				return;
 			}
 		}
 		
 		if (!onCritSkill.checkCondition(caster, target, false))
 		{
 			// Skill condition not met
-			return Collections.<L2Effect> emptyList();
+			return;
 		}
 		
 		final byte shld = Formulas.calcShldUse(caster, target, onCritSkill);
 		if (!Formulas.calcSkillSuccess(caster, target, onCritSkill, shld, false, false, false))
 		{
 			// These skills should not work on RaidBoss
-			return Collections.<L2Effect> emptyList();
+			return;
 		}
-		if (target.getFirstEffect(onCritSkill.getId()) != null)
+		if (target.isAffectedBySkill(onCritSkill.getId()))
 		{
-			target.getFirstEffect(onCritSkill.getId()).exit();
+			target.stopSkillEffects(false, onCritSkill.getId());
 		}
-		final List<L2Effect> effects = new ArrayList<>();
-		for (L2Effect e : onCritSkill.getEffects(caster, target, new Env(shld, false, false, false)))
-		{
-			effects.add(e);
-		}
-		return effects;
+		
+		onCritSkill.applyEffects(caster, null, target, new Env(shld, false, false, false), crit, crit);
 	}
 	
 	/**

+ 12 - 13
L2J_Server_BETA/java/com/l2jserver/gameserver/model/effects/AbnormalEffect.java → L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/AbnormalVisualEffect.java

@@ -16,15 +16,16 @@
  * 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.effects;
+package com.l2jserver.gameserver.model.skills;
 
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 /**
+ * Abnormal Visual Effect enumerated.
  * @author DrHouse
  */
-public enum AbnormalEffect
+public enum AbnormalVisualEffect
 {
 	NULL("null", 0x0),
 	BLEEDING("bleed", 0x000001),
@@ -59,8 +60,7 @@ public enum AbnormalEffect
 	REAL_TARGET("realtarget", 0x20000000),
 	DEATH_MARK("deathmark", 0x40000000),
 	SKULL_FEAR("skull_fear", 0x80000000),
-	
-	// special effects
+	// Special effects
 	S_INVINCIBLE("invincible", 0x000001),
 	S_AIR_STUN("airstun", 0x000002),
 	S_AIR_ROOT("airroot", 0x000004),
@@ -76,8 +76,7 @@ public enum AbnormalEffect
 	S_VESPER_C("vesper_c", 0x001000),
 	S_VESPER_D("vesper_d", 0x002000),
 	ARCANE_SHIELD("arcane_shield", 0x008000),
-	
-	// event effects
+	// Event effects
 	E_AFRO_1("afrobaguette1", 0x000001),
 	E_AFRO_2("afrobaguette2", 0x000002),
 	E_AFRO_3("afrobaguette3", 0x000004),
@@ -88,11 +87,11 @@ public enum AbnormalEffect
 	E_VESPER_3("vesper3", 0x000080),
 	HUNTING_BONUS("hunting_bonus", 0x80000);
 	
-	private static final Logger _log = Logger.getLogger(AbnormalEffect.class.getName());
+	private static final Logger _log = Logger.getLogger(AbnormalVisualEffect.class.getName());
 	private final int _mask;
 	private final String _name;
 	
-	private AbnormalEffect(String name, int mask)
+	private AbnormalVisualEffect(String name, int mask)
 	{
 		_name = name;
 		_mask = mask;
@@ -109,21 +108,21 @@ public enum AbnormalEffect
 	}
 	
 	/**
-	 * @param name the name of the abnormal effect to get
-	 * @return the found abnormal effect
+	 * @param name the name of the abnormal visual effect to get
+	 * @return the found abnormal visual effect
 	 */
-	public static AbnormalEffect getByName(String name)
+	public static AbnormalVisualEffect getByName(String name)
 	{
 		if ((name != null) && !name.isEmpty())
 		{
-			for (AbnormalEffect eff : AbnormalEffect.values())
+			for (AbnormalVisualEffect eff : AbnormalVisualEffect.values())
 			{
 				if (eff.getName().equals(name))
 				{
 					return eff;
 				}
 			}
-			_log.log(Level.WARNING, AbnormalEffect.class.getSimpleName() + ": Abnormal effect not found for name: " + name + "!");
+			_log.log(Level.WARNING, AbnormalVisualEffect.class.getSimpleName() + ": Abnormal visual effect not found for name: " + name + "!");
 		}
 		return NULL;
 	}

+ 470 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/BuffInfo.java

@@ -0,0 +1,470 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledFuture;
+
+import com.l2jserver.gameserver.GameTimeController;
+import com.l2jserver.gameserver.ThreadPoolManager;
+import com.l2jserver.gameserver.model.CharEffectList;
+import com.l2jserver.gameserver.model.actor.L2Character;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
+import com.l2jserver.gameserver.model.effects.EffectTaskInfo;
+import com.l2jserver.gameserver.model.effects.EffectTickTask;
+import com.l2jserver.gameserver.model.stats.Env;
+import com.l2jserver.gameserver.model.stats.Formulas;
+import com.l2jserver.gameserver.network.SystemMessageId;
+import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
+
+/**
+ * Buff Info.<br>
+ * Complex DTO that holds all the information for a given buff (or debuff or dance/song) set of effects issued by an skill.
+ * @author Zoey76
+ */
+public final class BuffInfo
+{
+	// Data
+	/** Data. */
+	private final Env _env;
+	/** The effects. */
+	private final List<AbstractEffect> _effects = new ArrayList<>(1);
+	// Tasks
+	/** Effect tasks for ticks. */
+	private Map<AbstractEffect, EffectTaskInfo> _tasks;
+	/** Task for effect ending. */
+	private BuffTimeTask _effectTimeTask;
+	/** Scheduled future. */
+	private ScheduledFuture<?> _scheduledFutureTimeTask;
+	// Time and ticks
+	/** Abnormal time. */
+	private int _abnormalTime;
+	/** The game ticks at the start of this effect. */
+	private final int _periodStartTicks;
+	// Misc
+	/** If {@code true} then this effect has been cancelled. */
+	private boolean _isRemoved = false;
+	/** If {@code true} then this effect is in use (or has been stop because an Herb took place). */
+	private boolean _isInUse = true;
+	
+	/**
+	 * Buff Info constructor.
+	 * @param env the cast data
+	 */
+	public BuffInfo(Env env)
+	{
+		_env = env;
+		_abnormalTime = Formulas.calcEffectAbnormalTime(env);
+		_periodStartTicks = GameTimeController.getInstance().getGameTicks();
+	}
+	
+	/**
+	 * Gets the effects on this buff info.
+	 * @return the effects
+	 */
+	public List<AbstractEffect> getEffects()
+	{
+		return _effects;
+	}
+	
+	/**
+	 * Adds an effect to this buff info.
+	 * @param effect the effect to add
+	 */
+	public void addEffect(AbstractEffect effect)
+	{
+		_effects.add(effect);
+	}
+	
+	/**
+	 * Adds an effect task to this buff info.<br>
+	 * Uses double-checked locking to initialize the map if it's necessary.
+	 * @param effect the effect that owns the task
+	 * @param effectTaskInfo the task info
+	 */
+	private void addTask(AbstractEffect effect, EffectTaskInfo effectTaskInfo)
+	{
+		if (_tasks == null)
+		{
+			synchronized (this)
+			{
+				if (_tasks == null)
+				{
+					_tasks = new ConcurrentHashMap<>();
+				}
+			}
+		}
+		_tasks.put(effect, effectTaskInfo);
+	}
+	
+	/**
+	 * Gets the task for the given effect.
+	 * @param effect the effect
+	 * @return the task
+	 */
+	private EffectTaskInfo getEffectTask(AbstractEffect effect)
+	{
+		return (_tasks == null) ? null : _tasks.get(effect);
+	}
+	
+	/**
+	 * Gets the skill that created this buff info.
+	 * @return the skill
+	 */
+	public L2Skill getSkill()
+	{
+		return _env.getSkill();
+	}
+	
+	public Env getEnv()
+	{
+		return _env;
+	}
+	
+	/**
+	 * Gets the calculated abnormal time.
+	 * @return the abnormal time
+	 */
+	public int getAbnormalTime()
+	{
+		return _abnormalTime;
+	}
+	
+	/**
+	 * Sets the abnormal time.
+	 * @param abnormalTime the abnormal time to set
+	 */
+	public void setAbnormalTime(int abnormalTime)
+	{
+		_abnormalTime = abnormalTime;
+	}
+	
+	/**
+	 * Gets the period start ticks.
+	 * @return the period start
+	 */
+	public int getPeriodStartTicks()
+	{
+		return _periodStartTicks;
+	}
+	
+	/**
+	 * Get the remaining time in seconds for this buff info.
+	 * @return the elapsed time
+	 */
+	public int getTime()
+	{
+		return _abnormalTime - ((GameTimeController.getInstance().getGameTicks() - _periodStartTicks) / GameTimeController.TICKS_PER_SECOND);
+	}
+	
+	/**
+	 * Verify if this buff info has been cancelled.
+	 * @return {@code true} if this buff info has been cancelled, {@code false} otherwise
+	 */
+	public boolean isRemoved()
+	{
+		return _isRemoved;
+	}
+	
+	/**
+	 * Set the buff info to removed.
+	 * @param val the value to set
+	 */
+	public void setRemoved(boolean val)
+	{
+		_isRemoved = val;
+	}
+	
+	/**
+	 * Verify if this buff info is in use.
+	 * @return {@code true} if this buff info is in use, {@code false} otherwise
+	 */
+	public boolean isInUse()
+	{
+		return _isInUse;
+	}
+	
+	/**
+	 * Set the buff info to in use.
+	 * @param val the value to set
+	 */
+	public void setInUse(boolean val)
+	{
+		_isInUse = val;
+	}
+	
+	/**
+	 * Gets the character that launched the buff.
+	 * @return the effector
+	 */
+	public L2Character getEffector()
+	{
+		return _env.getCharacter();
+	}
+	
+	/**
+	 * Gets the target of the skill.
+	 * @return the effected
+	 */
+	public L2Character getEffected()
+	{
+		return _env.getTarget();
+	}
+	
+	/**
+	 * Stops all the effects for this buff info.<br>
+	 * Removes effects stats.<br>
+	 * <b>It will not remove the buff info from the effect list</b>.<br>
+	 * Instead call {@link CharEffectList#stopSkillEffects(boolean, L2Skill)}
+	 * @param removed if {@code true} the skill will be handled as removed
+	 */
+	public void stopAllEffects(boolean removed)
+	{
+		setRemoved(removed);
+		// Cancels the task that will end this buff info
+		if ((_scheduledFutureTimeTask != null) && !_scheduledFutureTimeTask.isCancelled())
+		{
+			_scheduledFutureTimeTask.cancel(false);
+		}
+		
+		// Remove stats
+		removeStats();
+		
+		finishEffects();
+	}
+	
+	public void initializeEffects()
+	{
+		// When effects are initialized, the successfully landed.
+		if (_env.getTarget().isPlayer())
+		{
+			final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT);
+			sm.addSkillName(_env.getSkill());
+			_env.getTarget().sendPacket(sm);
+		}
+		
+		// Creates a task that will stop all the effects.
+		if (_abnormalTime > 0)
+		{
+			_effectTimeTask = new BuffTimeTask(this);
+			_scheduledFutureTimeTask = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(_effectTimeTask, 0, 1000L);
+		}
+		
+		for (AbstractEffect effect : _effects)
+		{
+			if (effect.isInstant())
+			{
+				// TODO: Log, instant effects shouldn't be added.
+				continue;
+			}
+			
+			// If it's a continuous effect, if has ticks schedule a task with period, otherwise schedule a simple task to end it.
+			if (effect.getTicks() > 0)
+			{
+				// The task for the effect ticks
+				final EffectTickTask effectTask = new EffectTickTask(this, effect);
+				final ScheduledFuture<?> scheduledFuture = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(effectTask, effect.getTicks() * 1000L, effect.getTicks() * 1000L);
+				// Adds the task for ticking
+				addTask(effect, new EffectTaskInfo(effectTask, scheduledFuture));
+			}
+			
+			// Add stats.
+			_env.getTarget().addStatFuncs(effect.getStatFuncs(_env));
+			
+			applyAbnormalVisualEffects(_env.getTarget(), effect);
+		}
+	}
+	
+	/**
+	 * Called on each tick.<br>
+	 * Verify if the effect should end and the effect task should be cancelled.
+	 * @param effect the effect that is ticking
+	 * @param tickCount the tick count
+	 */
+	public void onTick(AbstractEffect effect, int tickCount)
+	{
+		boolean continueForever = false;
+		// If the effect is in use, allow it to affect the effected.
+		if (_isInUse)
+		{
+			// Callback for on action time event.
+			continueForever = effect.onActionTime(this);
+		}
+		
+		// Skills without abnormal time should tick indefinitely, unless they fail on action time.
+		if (_env.getSkill().getAbnormalTime() > 0)
+		{
+			// Checks made in seconds, although tasks run in milliseconds, it'll increase margin for effects that run indefinitely.
+			final long elapsedTime = effect.getTicks() * tickCount;
+			if (elapsedTime >= _env.getSkill().getAbnormalTime())
+			{
+				final EffectTaskInfo task = getEffectTask(effect);
+				if (task != null)
+				{
+					task.getScheduledFuture().cancel(true); // Allow to finish current run.
+					_env.getTarget().getEffectList().remove(this); // Remove the buff from the effect list.
+				}
+			}
+		}
+		else if (!continueForever)
+		{
+			final EffectTaskInfo task = getEffectTask(effect);
+			if (task != null)
+			{
+				task.getScheduledFuture().cancel(true); // Allow to finish current run.
+				_env.getTarget().getEffectList().remove(this); // Remove the buff from the effect list.
+			}
+		}
+	}
+	
+	public void finishEffects()
+	{
+		for (AbstractEffect effect : _effects)
+		{
+			removeAbnormalVisualEffects(_env.getTarget(), effect); // TODO: Implement correctly.
+			
+			// Instant effects shouldn't call onExit(..).
+			if ((effect != null) && !effect.isInstant())
+			{
+				effect.onExit(this);
+			}
+		}
+		
+		// Cancels the ticking task.
+		if (_tasks != null)
+		{
+			for (Entry<AbstractEffect, EffectTaskInfo> entry : _tasks.entrySet())
+			{
+				entry.getValue().getScheduledFuture().cancel(true);
+			}
+		}
+		
+		// Sends the proper system message.
+		final SystemMessageId smId;
+		if (_env.getSkill().isToggle())
+		{
+			smId = SystemMessageId.S1_HAS_BEEN_ABORTED;
+		}
+		else if (isRemoved())
+		{
+			smId = SystemMessageId.EFFECT_S1_HAS_BEEN_REMOVED;
+		}
+		else
+		{
+			smId = SystemMessageId.S1_HAS_WORN_OFF;
+		}
+		
+		final SystemMessage sm = SystemMessage.getSystemMessage(smId);
+		sm.addSkillName(_env.getSkill());
+		_env.getTarget().sendPacket(sm);
+		
+		if (this == _env.getTarget().getEffectList().getShortBuff())
+		{
+			_env.getTarget().getEffectList().shortBuffStatusUpdate(null);
+		}
+	}
+	
+	/**
+	 * Applies all the abnormal visual effects to the effected.<br>
+	 * TODO: Shouldn't be read from effect template, but from skill template.
+	 * @param effected the target of the skill
+	 * @param effect the effect
+	 */
+	private static void applyAbnormalVisualEffects(L2Character effected, AbstractEffect effect)
+	{
+		if (effect.getAbnormalEffect() != AbnormalVisualEffect.NULL)
+		{
+			effected.startAbnormalEffect(effect.getAbnormalEffect());
+		}
+		
+		if (effect.getSpecialEffect() != null)
+		{
+			effected.startSpecialEffect(effect.getSpecialEffect());
+		}
+		
+		if ((effect.getEventEffect() != AbnormalVisualEffect.NULL) && effected.isPlayer())
+		{
+			effected.getActingPlayer().startEventEffect(effect.getEventEffect());
+		}
+	}
+	
+	/**
+	 * Removes all the abnormal visual effects from the effected.<br>
+	 * TODO: Shouldn't be read from effect template, but from skill template.
+	 * @param effected the target of the skill
+	 * @param effect the effect
+	 */
+	private static void removeAbnormalVisualEffects(L2Character effected, AbstractEffect effect)
+	{
+		if (effect.getAbnormalEffect() != AbnormalVisualEffect.NULL)
+		{
+			effected.stopAbnormalEffect(effect.getAbnormalEffect());
+		}
+		
+		if (effect.getSpecialEffect() != null)
+		{
+			effected.stopSpecialEffect(effect.getSpecialEffect());
+		}
+		
+		if ((effect.getEventEffect() != AbnormalVisualEffect.NULL) && effected.isPlayer())
+		{
+			effected.getActingPlayer().stopEventEffect(effect.getEventEffect());
+		}
+	}
+	
+	public void addStats()
+	{
+		for (AbstractEffect effect : _effects)
+		{
+			_env.getTarget().addStatFuncs(effect.getStatFuncs(_env));
+		}
+	}
+	
+	public void removeStats()
+	{
+		for (AbstractEffect effect : _effects)
+		{
+			_env.getTarget().removeStatsOwner(effect);
+		}
+		// TODO: This should be removed when all effects are properly managed.
+		_env.getTarget().removeStatsOwner(_env.getSkill());
+	}
+	
+	/**
+	 * Gets the effect tick count.
+	 * @param effect the effect
+	 * @return the current tick count
+	 */
+	public int getTickCount(AbstractEffect effect)
+	{
+		if (_tasks != null)
+		{
+			final EffectTaskInfo effectTaskInfo = _tasks.get(effect);
+			if (effectTaskInfo != null)
+			{
+				return effectTaskInfo.getEffectTask().getTickCount();
+			}
+		}
+		return 0;
+	}
+}

+ 25 - 13
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/tasks/player/ShortBuffTask.java → L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/BuffTimeTask.java

@@ -16,31 +16,43 @@
  * 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.actor.tasks.player;
+package com.l2jserver.gameserver.model.skills;
 
-import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.network.serverpackets.ShortBuffStatusUpdate;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
- * Task dedicated to update player's short buffs window.
- * @author UnAfraid
+ * Effect time task finish the effect when the abnormal time is reached.
+ * @author Zoey76
  */
-public class ShortBuffTask implements Runnable
+public class BuffTimeTask implements Runnable
 {
-	private final L2PcInstance _player;
+	private final AtomicInteger _time = new AtomicInteger();
+	private final BuffInfo _info;
 	
-	public ShortBuffTask(L2PcInstance player)
+	/**
+	 * EffectTimeTask constructor.
+	 * @param info the buff info
+	 */
+	public BuffTimeTask(BuffInfo info)
 	{
-		_player = player;
+		_info = info;
+	}
+	
+	/**
+	 * Gets the elapsed time.
+	 * @return the tick count
+	 */
+	public int getElapsedTime()
+	{
+		return _time.get();
 	}
 	
 	@Override
 	public void run()
 	{
-		if (_player != null)
+		if (_time.incrementAndGet() > _info.getAbnormalTime())
 		{
-			_player.sendPacket(new ShortBuffStatusUpdate(0, 0, 0));
-			_player.setShortBuffTaskSkillId(0);
+			_info.getEffected().getEffectList().stopSkillEffects(false, _info.getSkill().getId());
 		}
 	}
-}
+}

+ 168 - 225
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/L2Skill.java

@@ -45,8 +45,7 @@ import com.l2jserver.gameserver.model.actor.instance.L2CubicInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2SiegeFlagInstance;
 import com.l2jserver.gameserver.model.conditions.Condition;
-import com.l2jserver.gameserver.model.effects.EffectTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.entity.TvTEvent;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
@@ -69,24 +68,25 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 	protected static final Logger _log = Logger.getLogger(L2Skill.class.getName());
 	
 	private static final L2Object[] EMPTY_TARGET_LIST = new L2Object[0];
-	private static final List<L2Effect> EMPTY_EFFECT_LIST = Collections.<L2Effect> emptyList();
 	
+	public static final int SKILL_CUBIC_MASTERY = 143;
 	public static final int SKILL_CREATE_DWARVEN = 172;
+	public static final int SKILL_LUCKY = 194;
 	public static final int SKILL_EXPERTISE = 239;
 	public static final int SKILL_CRYSTALLIZE = 248;
 	public static final int SKILL_CLAN_LUCK = 390;
 	public static final int SKILL_ONYX_BEAST_TRANSFORMATION = 617;
 	public static final int SKILL_CREATE_COMMON = 1320;
 	public static final int SKILL_DIVINE_INSPIRATION = 1405;
+	public static final int SKILL_SERVITOR_SHARE = 1557;
+	public static final int SKILL_CARAVANS_SECRET_MEDICINE = 2341;
 	public static final int SKILL_NPC_RACE = 4416;
 	
-	public static final boolean geoEnabled = Config.GEODATA > 0;
-	
 	/** Skill Id. */
 	private final int _id;
 	/** Skill level. */
 	private final int _level;
-	/** Custom skill Id displayed by the client. */
+	/** Custom skill ID displayed by the client. */
 	private final int _displayId;
 	/** Custom skill level displayed by the client. */
 	private final int _displayLevel;
@@ -174,8 +174,6 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 	private final int _soulMaxConsume;
 	private final boolean _dependOnTargetBuff;
 	
-	private final int _afterEffectId;
-	private final int _afterEffectLvl;
 	private final boolean _isHeroSkill; // If true the skill is a Hero Skill
 	private final boolean _isGMSkill; // True if skill is GM skill
 	private final boolean _isSevenSigns;
@@ -190,10 +188,10 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 	// Function lists
 	private List<FuncTemplate> _funcTemplates;
 	// Effect lists
-	private List<EffectTemplate> _effectTemplates;
-	private List<EffectTemplate> _effectTemplatesSelf;
-	private List<EffectTemplate> _effectTemplatesPassive;
-	private List<EffectTemplate> _effectTemplatesChanneling;
+	private List<AbstractEffect> _effects;
+	private List<AbstractEffect> _effectSelf;
+	private List<AbstractEffect> _effectPassive;
+	private List<AbstractEffect> _effectChanneling;
 	
 	protected ChanceCondition _chanceCondition = null;
 	
@@ -223,6 +221,7 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 	
 	private byte[] _effectTypes;
 	
+	// Channeling data
 	private final int _channelingSkillId;
 	private final int _channelingTickInitialDelay;
 	private final int _channelingTickInterval;
@@ -246,15 +245,13 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		_hpConsume = set.getInt("hpConsume", 0);
 		_itemConsumeCount = set.getInt("itemConsumeCount", 0);
 		_itemConsumeId = set.getInt("itemConsumeId", 0);
-		_afterEffectId = set.getInt("afterEffectId", 0);
-		_afterEffectLvl = set.getInt("afterEffectLvl", 1);
 		
 		_castRange = set.getInt("castRange", -1);
 		_effectRange = set.getInt("effectRange", -1);
 		_abnormalLvl = set.getInt("abnormalLvl", 0);
 		_abnormalType = set.getEnum("abnormalType", AbnormalType.class, AbnormalType.NONE);
 		
-		int abnormalTime = set.getInt("abnormalTime", 1); // TODO: Should be 0, but instant effects need it until implementation is done.
+		int abnormalTime = set.getInt("abnormalTime", 0);
 		if (Config.ENABLE_MODIFY_SKILL_DURATION && Config.SKILL_DURATION_LIST.containsKey(getId()))
 		{
 			if ((getLevel() < 100) || (getLevel() > 140))
@@ -379,6 +376,7 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		}
 		_npcId = set.getInt("npcId", 0);
 		_icon = set.getString("icon", "icon.skill0000");
+		
 		_channelingSkillId = set.getInt("channelingSkillId", 0);
 		_channelingTickInterval = set.getInt("channelingTickInterval", 2) * 1000;
 		_channelingTickInitialDelay = set.getInt("channelingTickInitialDelay", _channelingTickInterval / 1000) * 1000;
@@ -781,6 +779,11 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		return (_operateType != null) && _operateType.isToggle();
 	}
 	
+	public final boolean isContinuous()
+	{
+		return (_operateType != null) && _operateType.isContinuous();
+	}
+	
 	public final boolean isChance()
 	{
 		return (_chanceCondition != null) && isPassive();
@@ -796,6 +799,15 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		return _isTriggeredSkill;
 	}
 	
+	/**
+	 * Verify if the skill is a transformation skill.
+	 * @return {@code true} if the skill is a transformation, {@code false} otherwise
+	 */
+	public boolean isTransformation()
+	{
+		return _abnormalType == AbnormalType.TRANSFORM;
+	}
+	
 	public final int getEffectPoint()
 	{
 		return _effectPoint;
@@ -836,6 +848,27 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		return _isSevenSigns;
 	}
 	
+	/**
+	 * Verify if this is a healing potion skill.
+	 * @return {@code true} if this is a healing potion skill, {@code false} otherwise
+	 */
+	public final boolean isHealingPotionSkill()
+	{
+		switch (getId())
+		{
+			case 2031: // Lesser Healing Potion
+			case 2032: // Healing Potion
+			case 2037: // Greater Healing Potion
+			case 2863: // Highest Power Healing Potion
+			case 26025: // Powerful Healing Potion
+			case 26026: // High-grade Healing Potion
+			{
+				return true;
+			}
+		}
+		return false;
+	}
+	
 	public final int getChargeConsume()
 	{
 		return _chargeConsume;
@@ -1108,7 +1141,7 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 			}
 		}
 		
-		if (geoEnabled && !GeoData.getInstance().canSeeTarget(caster, target))
+		if ((Config.GEODATA > 0) && !GeoData.getInstance().canSeeTarget(caster, target))
 		{
 			return false;
 		}
@@ -1138,7 +1171,7 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		return true;
 	}
 	
-	public final List<Func> getStatFuncs(L2Effect effect, L2Character player)
+	public final List<Func> getStatFuncs(AbstractEffect effect, L2Character player)
 	{
 		if (_funcTemplates == null)
 		{
@@ -1167,73 +1200,60 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 	
 	public boolean hasEffects()
 	{
-		return (_effectTemplates != null) && !_effectTemplates.isEmpty();
+		return (_effects != null) && !_effects.isEmpty();
 	}
 	
-	public List<EffectTemplate> getEffectTemplates()
+	public List<AbstractEffect> getEffectTemplates()
 	{
-		return _effectTemplates;
+		return _effects;
 	}
 	
-	public List<EffectTemplate> getEffectTemplatesPassive()
+	public boolean hasPassiveEffects()
 	{
-		return _effectTemplatesPassive;
+		return (_effectPassive != null) && !_effectPassive.isEmpty();
 	}
 	
-	public List<EffectTemplate> getEffectTemplateChanneling()
+	public List<AbstractEffect> getEffectTemplatesPassive()
 	{
-		return _effectTemplatesChanneling;
+		return _effectPassive;
 	}
 	
-	public boolean hasSelfEffects()
+	public List<AbstractEffect> getEffectTemplateChanneling()
 	{
-		return (_effectTemplatesSelf != null) && !_effectTemplatesSelf.isEmpty();
+		return _effectChanneling;
 	}
 	
-	public boolean hasPassiveEffects()
+	public boolean hasSelfEffects()
 	{
-		return (_effectTemplatesPassive != null) && !_effectTemplatesPassive.isEmpty();
+		return (_effectSelf != null) && !_effectSelf.isEmpty();
 	}
 	
 	public boolean hasChannelingEffects()
 	{
-		return (_effectTemplatesChanneling != null) && !_effectTemplatesChanneling.isEmpty();
+		return (_effectChanneling != null) && !_effectChanneling.isEmpty();
 	}
 	
 	/**
-	 * Env is used to pass parameters for secondary effects (shield and ss/bss/bsss)
-	 * @param effector
-	 * @param effected
+	 * Applies the effects from this skill to the target.
+	 * @param effector the caster of the skill
+	 * @param cubic the cubic that cast the skill, can be {@code null}
+	 * @param effected the target of the effect
 	 * @param env
-	 * @return an array with the effects that have been added to effector
+	 * @param self if {@code true} self-effects will be casted on the caster
+	 * @param passive if {@code true} passive effects will be applied to the caster
 	 */
-	public final List<L2Effect> getEffects(L2Character effector, L2Character effected, Env env)
+	public final void applyEffects(L2Character effector, L2CubicInstance cubic, L2Character effected, Env env, boolean self, boolean passive)
 	{
-		if ((effected == null) || !hasEffects() || isPassive())
+		// Null targets, doors and siege flags cannot receive any effects.
+		if ((effected == null) || effected.isDoor() || (effected instanceof L2SiegeFlagInstance))
 		{
-			return EMPTY_EFFECT_LIST;
+			return;
 		}
 		
-		// doors and siege flags cannot receive any effects
-		if (effected.isDoor() || (effected instanceof L2SiegeFlagInstance))
+		// Check bad skills against target.
+		if ((effector != effected) && isBad() && (effected.isInvul() || (effector.isGM() && !effector.getAccessLevel().canGiveDamage())))
 		{
-			return EMPTY_EFFECT_LIST;
-		}
-		
-		if ((effector != effected) && isBad())
-		{
-			if (effected.isInvul())
-			{
-				return EMPTY_EFFECT_LIST;
-			}
-			
-			if (effector.isPlayer() && effector.isGM())
-			{
-				if (!effector.getAccessLevel().canGiveDamage())
-				{
-					return EMPTY_EFFECT_LIST;
-				}
-			}
+			return;
 		}
 		
 		if (env == null)
@@ -1242,175 +1262,100 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		}
 		env.setSkillMastery(Formulas.calcSkillMastery(effector, this));
 		env.setCharacter(effector);
+		env.setCubic(cubic);
 		env.setTarget(effected);
 		env.setSkill(this);
+		final boolean addContinuousEffects = _operateType.isToggle() || (_operateType.isContinuous() && Formulas.calcEffectSuccess(env));
 		
-		boolean addContinuousEffects = _operateType.isToggle() || (_operateType.isContinuous() && Formulas.calcEffectSuccess(env));
-		
-		final List<L2Effect> effects = new ArrayList<>(_effectTemplates.size());
-		for (EffectTemplate et : _effectTemplates)
+		if (!self && !passive && hasEffects())
 		{
-			final L2Effect e = et.getEffect(env);
-			if (e != null)
+			final BuffInfo info = new BuffInfo(env);
+			for (AbstractEffect effect : _effects)
 			{
-				if ((e.isInstant() && e.calcSuccess()) || (!e.isInstant() && addContinuousEffects))
+				if (effect != null)
 				{
-					e.scheduleEffect();
-					effects.add(e);
-				}
-			}
-		}
-		effected.getEffectList().add(effects);
-		return effects;
-	}
-	
-	/**
-	 * Warning: this method doesn't consider modifier (shield, ss, sps, bss) for secondary effects
-	 * @param effector
-	 * @param effected
-	 * @return
-	 */
-	public final List<L2Effect> getEffects(L2Character effector, L2Character effected)
-	{
-		return getEffects(effector, effected, null);
-	}
-	
-	public final List<L2Effect> getEffects(L2CubicInstance effector, L2Character effected, Env env)
-	{
-		if ((effector == null) || (effected == null) || !hasEffects() || isPassive())
-		{
-			return EMPTY_EFFECT_LIST;
-		}
-		
-		if ((effector.getOwner() != effected) && isBad())
-		{
-			if (effected.isInvul())
-			{
-				return EMPTY_EFFECT_LIST;
-			}
-			
-			if (effector.getOwner().isGM() && !effector.getOwner().getAccessLevel().canGiveDamage())
-			{
-				return EMPTY_EFFECT_LIST;
-			}
-		}
-		
-		if (env == null)
-		{
-			env = new Env();
-		}
-		env.setCharacter(effector.getOwner());
-		env.setCubic(effector);
-		env.setTarget(effected);
-		env.setSkill(this);
-		
-		boolean addContinuousEffects = _operateType.isToggle() || (_operateType.isContinuous() && Formulas.calcEffectSuccess(env));
-		
-		final List<L2Effect> effects = new ArrayList<>(_effectTemplates.size());
-		for (EffectTemplate et : _effectTemplates)
-		{
-			final L2Effect e = et.getEffect(env);
-			if (e != null)
-			{
-				if ((e.isInstant() && e.calcSuccess()) || (!e.isInstant() && addContinuousEffects))
-				{
-					e.scheduleEffect();
-					effects.add(e);
+					if (effect.isInstant())
+					{
+						if (effect.calcSuccess(info))
+						{
+							effect.onStart(info);
+						}
+					}
+					else if (addContinuousEffects)
+					{
+						if (effect.onStart(info))
+						{
+							info.addEffect(effect);
+						}
+					}
 				}
 			}
+			effected.getEffectList().add(info);
 		}
-		return effects;
-	}
-	
-	public final List<L2Effect> getEffectsSelf(L2Character effector)
-	{
-		if ((effector == null) || !hasSelfEffects() || isPassive())
-		{
-			return EMPTY_EFFECT_LIST;
-		}
-		
-		final Env env = new Env();
-		env.setCharacter(effector);
-		env.setTarget(effector);
-		env.setSkill(this);
 		
-		boolean addContinuousEffects = _operateType.isToggle() || (_operateType.isContinuous() && Formulas.calcEffectSuccess(env));
-		
-		final List<L2Effect> effects = new ArrayList<>(_effectTemplatesSelf.size());
-		for (EffectTemplate et : _effectTemplatesSelf)
+		if (self && hasSelfEffects())
 		{
-			final L2Effect e = et.getEffect(env);
-			if (e != null)
+			env.setTarget(effector);
+			final BuffInfo info = new BuffInfo(env);
+			for (AbstractEffect effect : _effectSelf)
 			{
-				if ((e.isInstant() && e.calcSuccess()) || (!e.isInstant() && addContinuousEffects))
+				if (effect != null)
 				{
-					e.setSelfEffect();
-					e.scheduleEffect();
-					effects.add(e);
+					if (effect.isInstant())
+					{
+						if (effect.calcSuccess(info))
+						{
+							effect.onStart(info);
+						}
+					}
+					else if (addContinuousEffects)
+					{
+						if (effect.onStart(info))
+						{
+							info.addEffect(effect);
+						}
+					}
 				}
 			}
-		}
-		effector.getEffectList().add(effects);
-		return effects;
-	}
-	
-	public final List<L2Effect> getPassiveEffects(L2Character effector)
-	{
-		if ((effector == null) || !hasPassiveEffects())
-		{
-			return EMPTY_EFFECT_LIST;
+			effector.getEffectList().add(info);
 		}
 		
-		final Env env = new Env();
-		env.setCharacter(effector);
-		env.setTarget(effector);
-		env.setSkill(this);
-		final List<L2Effect> effects = new ArrayList<>(_effectTemplatesPassive.size());
-		for (EffectTemplate et : _effectTemplatesPassive)
+		if (passive && hasPassiveEffects())
 		{
-			final L2Effect e = et.getEffect(env);
-			if (e != null)
+			env.setTarget(effector);
+			final BuffInfo info = new BuffInfo(env);
+			for (AbstractEffect effect : _effectPassive)
 			{
-				if (!e.isInstant())
+				if (effect != null)
 				{
-					e.scheduleEffect();
-					effects.add(e);
+					if (effect.onStart(info))
+					{
+						info.addEffect(effect);
+					}
 				}
 			}
+			effector.getEffectList().add(info);
 		}
-		effector.getEffectList().add(effects);
-		return effects;
-	}
-	
-	public final List<L2Effect> getChannelingEffects(L2Character effector, L2Character effected)
-	{
-		if ((effector == null) || (effected == null) || !hasChannelingEffects())
-		{
-			return EMPTY_EFFECT_LIST;
-		}
-		
-		final Env env = new Env();
-		env.setCharacter(effector);
-		env.setTarget(effected);
-		env.setSkill(this);
-		
-		boolean addContinuousEffects = _operateType.isToggle() || (_operateType.isContinuous() && Formulas.calcEffectSuccess(env));
 		
-		final List<L2Effect> effects = new ArrayList<>(_effectTemplatesChanneling.size());
-		for (EffectTemplate et : _effectTemplatesChanneling)
+		if (!self && !passive && hasChannelingEffects())
 		{
-			final L2Effect e = et.getEffect(env);
-			if (e != null)
+			env.setTarget(effected);
+			final BuffInfo info = new BuffInfo(env);
+			for (AbstractEffect effect : _effectChanneling)
 			{
-				if ((e.isInstant() && e.calcSuccess()) || (!e.isInstant() && addContinuousEffects))
+				if (effect != null)
 				{
-					e.scheduleEffect();
-					effects.add(e);
+					if ((effect.isInstant() && effect.calcSuccess(info)) || (!effect.isInstant() && addContinuousEffects))
+					{
+						if (effect.onStart(info))
+						{
+							info.addEffect(effect);
+						}
+					}
 				}
 			}
+			effector.getEffectList().add(info);
 		}
-		effector.getEffectList().add(effects);
-		return effects;
 	}
 	
 	public final void attach(FuncTemplate f)
@@ -1422,40 +1367,40 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		_funcTemplates.add(f);
 	}
 	
-	public final void attach(EffectTemplate effect)
+	public final void attach(AbstractEffect effect)
 	{
-		if (_effectTemplates == null)
+		if (_effects == null)
 		{
-			_effectTemplates = new ArrayList<>(1);
+			_effects = new ArrayList<>(1);
 		}
-		_effectTemplates.add(effect);
+		_effects.add(effect);
 	}
 	
-	public final void attachSelf(EffectTemplate effect)
+	public final void attachSelf(AbstractEffect effect)
 	{
-		if (_effectTemplatesSelf == null)
+		if (_effectSelf == null)
 		{
-			_effectTemplatesSelf = new ArrayList<>(1);
+			_effectSelf = new ArrayList<>(1);
 		}
-		_effectTemplatesSelf.add(effect);
+		_effectSelf.add(effect);
 	}
 	
-	public final void attachPassive(EffectTemplate effect)
+	public final void attachPassive(AbstractEffect effect)
 	{
-		if (_effectTemplatesPassive == null)
+		if (_effectPassive == null)
 		{
-			_effectTemplatesPassive = new ArrayList<>(1);
+			_effectPassive = new ArrayList<>(1);
 		}
-		_effectTemplatesPassive.add(effect);
+		_effectPassive.add(effect);
 	}
 	
-	public final void attachChanneling(EffectTemplate effectTemplate)
+	public final void attachChanneling(AbstractEffect effectTemplate)
 	{
-		if (_effectTemplatesChanneling == null)
+		if (_effectChanneling == null)
 		{
-			_effectTemplatesChanneling = new ArrayList<>(1);
+			_effectChanneling = new ArrayList<>(1);
 		}
-		_effectTemplatesChanneling.add(effectTemplate);
+		_effectChanneling.add(effectTemplate);
 	}
 	
 	public final void attach(Condition c, boolean itemOrWeapon)
@@ -1501,16 +1446,6 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		return _refId;
 	}
 	
-	public int getAfterEffectId()
-	{
-		return _afterEffectId;
-	}
-	
-	public int getAfterEffectLvl()
-	{
-		return _afterEffectLvl;
-	}
-	
 	@Override
 	public boolean triggersChanceSkill()
 	{
@@ -1558,6 +1493,15 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		return _canBeDispeled;
 	}
 	
+	/**
+	 * Verify if the skill can be stolen.
+	 * @return {@code true} if skill can be stolen, {@code false} otherwise
+	 */
+	public boolean canBeStolen()
+	{
+		return !isPassive() && !isToggle() && !isDebuff() && !isHeroSkill() && !isGMSkill() && !(isStatic() && (getId() != SKILL_CARAVANS_SECRET_MEDICINE)) && canBeDispeled() && (getId() != SKILL_SERVITOR_SHARE);
+	}
+	
 	public boolean isClanSkill()
 	{
 		return _isClanSkill;
@@ -1655,20 +1599,19 @@ public abstract class L2Skill implements IChanceSkillTrigger, IIdentifiable
 		{
 			if (_effectTypes == null)
 			{
-				_effectTypes = new byte[_effectTemplates.size()];
+				_effectTypes = new byte[_effects.size()];
 				
 				final Env env = new Env();
 				env.setSkill(this);
 				
 				int i = 0;
-				for (EffectTemplate et : _effectTemplates)
+				for (AbstractEffect effect : _effects)
 				{
-					final L2Effect e = et.getEffect(env, true);
-					if (e == null)
+					if (effect == null)
 					{
 						continue;
 					}
-					_effectTypes[i++] = (byte) e.getEffectType().ordinal();
+					_effectTypes[i++] = (byte) effect.getEffectType().ordinal();
 				}
 				Arrays.sort(_effectTypes);
 			}

+ 5 - 7
L2J_Server_BETA/java/com/l2jserver/gameserver/model/skills/SkillChannelizer.java

@@ -30,7 +30,6 @@ import com.l2jserver.gameserver.ThreadPoolManager;
 import com.l2jserver.gameserver.datatables.SkillTable;
 import com.l2jserver.gameserver.enums.ShotType;
 import com.l2jserver.gameserver.model.actor.L2Character;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.MagicSkillLaunched;
 import com.l2jserver.gameserver.util.Point3D;
@@ -182,11 +181,11 @@ public class SkillChannelizer implements Runnable
 				final int maxSkillLevel = SkillTable.getInstance().getMaxLevel(_skill.getChannelingSkillId());
 				final int skillLevel = Math.min(_channelized.getSkillChannelized().getChannerlizersSize(_skill.getChannelingSkillId()), maxSkillLevel);
 				
-				final L2Effect currentEffect = _channelized.getFirstEffect(_skill.getChannelingSkillId());
-				if ((currentEffect == null) || (currentEffect.getSkill().getLevel() < skillLevel))
+				final BuffInfo info = _channelized.getEffectList().getBuffInfoBySkillId(_skill.getChannelingSkillId());
+				if ((info == null) || (info.getSkill().getLevel() < skillLevel))
 				{
 					final L2Skill skill = SkillTable.getInstance().getInfo(_skill.getChannelingSkillId(), skillLevel);
-					skill.getEffects(getChannelizer(), _channelized);
+					skill.applyEffects(getChannelizer(), null, _channelized, null, false, false);
 				}
 				_channelizer.broadcastPacket(new MagicSkillLaunched(_channelizer, _skill.getId(), _skill.getLevel(), _channelized));
 			}
@@ -210,8 +209,7 @@ public class SkillChannelizer implements Runnable
 					if (_channelizer.isPlayable() && _channelizer.getActingPlayer().canAttackCharacter(target))
 					{
 						// Apply channeling skill effects on the target.
-						_skill.getChannelingEffects(_channelizer, target);
-						
+						_skill.applyEffects(_channelizer, null, _channelizer, null, false, false);
 						// Update the pvp flag of the caster.
 						_channelizer.getActingPlayer().updatePvPStatus(target);
 					}
@@ -223,7 +221,7 @@ public class SkillChannelizer implements Runnable
 				else
 				{
 					// Apply channeling skill effects on the target.
-					_skill.getChannelingEffects(_channelizer, target);
+					_skill.applyEffects(_channelizer, null, _channelizer, null, false, false);
 				}
 			}
 			

+ 0 - 18
L2J_Server_BETA/java/com/l2jserver/gameserver/model/stats/Env.java

@@ -21,7 +21,6 @@ package com.l2jserver.gameserver.model.stats;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2CubicInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 
@@ -35,7 +34,6 @@ public final class Env
 	private boolean _blessedSpiritShot = false;
 	private L2Character _character;
 	private L2CubicInstance _cubic;
-	private L2Effect _effect;
 	private L2ItemInstance _item;
 	private byte _shield = 0;
 	private L2Skill _skill;
@@ -81,14 +79,6 @@ public final class Env
 		return _cubic;
 	}
 	
-	/**
-	 * @return the _effect
-	 */
-	public L2Effect getEffect()
-	{
-		return _effect;
-	}
-	
 	/**
 	 * @return the _item
 	 */
@@ -201,14 +191,6 @@ public final class Env
 		_cubic = cubic;
 	}
 	
-	/**
-	 * @param effect the _effect to set
-	 */
-	public void setEffect(L2Effect effect)
-	{
-		_effect = effect;
-	}
-	
 	/**
 	 * @param item the _item to set
 	 */

+ 52 - 58
L2J_Server_BETA/java/com/l2jserver/gameserver/model/stats/Formulas.java

@@ -39,8 +39,6 @@ import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2CubicInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
-import com.l2jserver.gameserver.model.effects.EffectTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.entity.Castle;
 import com.l2jserver.gameserver.model.entity.ClanHall;
@@ -51,6 +49,7 @@ import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.L2Weapon;
 import com.l2jserver.gameserver.model.items.type.L2ArmorType;
 import com.l2jserver.gameserver.model.items.type.L2WeaponType;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.skills.funcs.formulas.FuncArmorSet;
 import com.l2jserver.gameserver.model.skills.funcs.formulas.FuncAtkAccuracy;
@@ -1981,96 +1980,91 @@ public final class Formulas
 		return Rnd.get(100) < rate;
 	}
 	
-	public static List<L2Effect> calcCancelStealEffects(L2Character activeChar, L2Character target, L2Skill skill, String slot, int rate, int max)
+	public static List<BuffInfo> calcCancelStealEffects(L2Character activeChar, L2Character target, L2Skill skill, String slot, int rate, int max)
 	{
-		final List<L2Effect> effects = target.getAllEffects();
-		List<L2Effect> canceled = new ArrayList<>(max);
-		if (!effects.isEmpty())
-		{
-			switch (slot)
-			{
-				case "buff":
+		final List<BuffInfo> canceled = new ArrayList<>(max);
+		switch (slot)
+		{
+			case "buff":
+			{
+				// Resist Modifier.
+				int cancelMagicLvl = skill.getMagicLevel();
+				final double vuln = target.calcStat(Stats.CANCEL_VULN, 0, target, null);
+				final double prof = activeChar.calcStat(Stats.CANCEL_PROF, 0, target, null);
+				double resMod = 1 + (((vuln + prof) * -1) / 100);
+				double finalRate = rate / resMod;
+				
+				if (activeChar.isDebug())
 				{
-					// Resist Modifier.
-					int cancelMagicLvl = skill.getMagicLevel();
-					final double vuln = target.calcStat(Stats.CANCEL_VULN, 0, target, null);
-					final double prof = activeChar.calcStat(Stats.CANCEL_PROF, 0, target, null);
-					double resMod = 1 + (((vuln + prof) * -1) / 100);
-					double finalRate = rate / resMod;
-					
-					if (activeChar.isDebug())
+					final StatsSet set = new StatsSet();
+					set.set("baseMod", rate);
+					set.set("magicLevel", cancelMagicLvl);
+					set.set("resMod", resMod);
+					set.set("rate", finalRate);
+					Debug.sendSkillDebug(activeChar, target, skill, set);
+				}
+				
+				final List<BuffInfo> buffs = new ArrayList<>(target.getEffectList().getBuffs().values());
+				buffs.addAll(target.getEffectList().getTriggered().values());
+				for (int i = buffs.size() - 1; i >= 0; i--) // reverse order
+				{
+					BuffInfo info = buffs.get(i);
+					if (!info.getSkill().canBeStolen() || (!calcCancelSuccess(info, cancelMagicLvl, (int) finalRate, skill)))
 					{
-						final StatsSet set = new StatsSet();
-						set.set("baseMod", rate);
-						set.set("magicLevel", cancelMagicLvl);
-						set.set("resMod", resMod);
-						set.set("rate", finalRate);
-						Debug.sendSkillDebug(activeChar, target, skill, set);
+						continue;
 					}
-					
-					L2Effect effect;
-					for (int i = effects.size(); --i >= 0;) // reverse order
+					canceled.add(info);
+					if (canceled.size() >= max)
 					{
-						effect = effects.get(i);
-						if (!effect.canBeStolen() || effect.getSkill().isDance() || (!calcCancelSuccess(effect, cancelMagicLvl, (int) finalRate, skill)))
-						{
-							continue;
-						}
-						canceled.add(effect);
-						if (canceled.size() >= max)
-						{
-							break;
-						}
+						break;
 					}
-					break;
 				}
-				case "debuff":
+				break;
+			}
+			case "debuff":
+			{
+				final List<BuffInfo> debuffs = new ArrayList<>(target.getEffectList().getDebuffs().values());
+				for (int i = debuffs.size() - 1; i >= 0; i--)
 				{
-					L2Effect effect;
-					for (int i = effects.size(); --i >= 0;) // reverse order
+					BuffInfo info = debuffs.get(i);
+					if (info.getSkill().isDebuff() && info.getSkill().canBeDispeled() && (Rnd.get(100) <= rate))
 					{
-						effect = effects.get(i);
-						if (effect.getSkill().isDebuff() && effect.getSkill().canBeDispeled() && (Rnd.get(100) <= rate))
+						canceled.add(info);
+						if (canceled.size() >= max)
 						{
-							canceled.add(effect);
-							if (canceled.size() >= max)
-							{
-								break;
-							}
+							break;
 						}
 					}
-					break;
 				}
+				break;
 			}
 		}
 		return canceled;
 	}
 	
-	public static boolean calcCancelSuccess(L2Effect eff, int cancelMagicLvl, int rate, L2Skill skill)
+	public static boolean calcCancelSuccess(BuffInfo info, int cancelMagicLvl, int rate, L2Skill skill)
 	{
 		// Lvl Bonus Modifier.
-		rate *= eff.getSkill().getMagicLevel() > 0 ? 1 + ((cancelMagicLvl - eff.getSkill().getMagicLevel()) / 100.) : 1;
+		rate *= info.getSkill().getMagicLevel() > 0 ? 1 + ((cancelMagicLvl - info.getSkill().getMagicLevel()) / 100.) : 1;
 		return Rnd.get(100) < Math.min(Math.max(rate, skill.getMinChance()), skill.getMaxChance());
 	}
 	
 	/**
 	 * Calculates the abnormal time for an effect.<br>
-	 * The abnormal time is taken from the skill definition, and it's global for all effects present in the skills.<br>
-	 * However there is the possibility to define an abnormal time for each effect.<br>
-	 * @param template the effect template
+	 * The abnormal time is taken from the skill definition, and it's global for all effects present in the skills.
 	 * @param env the data transfer object with required information
 	 * @return the time that the effect will last
 	 */
-	public static int calcEffectAbnormalTime(Env env, EffectTemplate template)
+	public static int calcEffectAbnormalTime(Env env)
 	{
 		final L2Character caster = env.getCharacter();
 		final L2Character target = env.getTarget();
 		final L2Skill skill = env.getSkill();
-		int time = (template.getAbnormalTime() != 0) || (skill == null) ? template.getAbnormalTime() : skill.isPassive() || skill.isToggle() ? -1 : skill.getAbnormalTime();
+		int time = skill.isPassive() || skill.isToggle() ? -1 : skill.getAbnormalTime();
 		
 		// An herb buff will affect both master and servitor, but the buff duration will be half of the normal duration.
 		// If a servitor is not summoned, the master will receive the full buff duration.
-		if ((target != null) && target.isServitor() && (skill != null) && skill.isAbnormalInstant())
+		if ((target != null) && target.isServitor() && skill.isAbnormalInstant())
 		{
 			time /= 2;
 		}
@@ -2082,7 +2076,7 @@ public final class Formulas
 		}
 		
 		// Debuffs Duration Affected by Resistances.
-		if ((caster != null) && (target != null) && (skill != null) && skill.isDebuff())
+		if ((caster != null) && (target != null) && skill.isDebuff())
 		{
 			double statMod = calcSkillStatMod(skill, target);
 			double resMod = calcGeneralTraitBonus(caster, target, skill.getTraitType(), false);

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/zone/type/L2AbnormalZone.java

@@ -19,7 +19,7 @@
 package com.l2jserver.gameserver.model.zone.type;
 
 import com.l2jserver.gameserver.model.actor.L2Character;
-import com.l2jserver.gameserver.model.effects.AbnormalEffect;
+import com.l2jserver.gameserver.model.skills.AbnormalVisualEffect;
 import com.l2jserver.gameserver.model.zone.L2ZoneType;
 
 /**
@@ -28,7 +28,7 @@ import com.l2jserver.gameserver.model.zone.L2ZoneType;
  */
 public class L2AbnormalZone extends L2ZoneType
 {
-	private int abnormal = AbnormalEffect.BIG_HEAD.getMask();
+	private int abnormal = AbnormalVisualEffect.BIG_HEAD.getMask();
 	private int special = 0;
 	
 	public L2AbnormalZone(int id)

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/zone/type/L2DynamicZone.java

@@ -75,7 +75,7 @@ public class L2DynamicZone extends L2ZoneType
 		}
 		if (_owner != null)
 		{
-			_skill.getEffects(_owner, character);
+			_skill.applyEffects(_owner, null, character, null, false, false);
 		}
 	}
 	
@@ -130,6 +130,6 @@ public class L2DynamicZone extends L2ZoneType
 	@Override
 	public void onReviveInside(L2Character character)
 	{
-		_skill.getEffects(_owner, character);
+		_skill.applyEffects(_owner, null, character, null, false, false);
 	}
 }

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/zone/type/L2EffectZone.java

@@ -261,9 +261,9 @@ public class L2EffectZone extends L2ZoneType
 								L2Skill skill = getSkill(e.getKey(), e.getValue());
 								if ((skill != null) && (_bypassConditions || skill.checkCondition(temp, temp, false)))
 								{
-									if (temp.getFirstEffect(e.getKey()) == null)
+									if (!temp.isAffectedBySkill(e.getKey()))
 									{
-										skill.getEffects(temp, temp);
+										skill.applyEffects(temp, null, temp, null, false, false);
 									}
 								}
 							}

+ 5 - 5
L2J_Server_BETA/java/com/l2jserver/gameserver/model/zone/type/L2SiegeZone.java

@@ -29,11 +29,11 @@ import com.l2jserver.gameserver.model.TeleportWhereType;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2SiegeSummonInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.entity.Fort;
 import com.l2jserver.gameserver.model.entity.FortSiege;
 import com.l2jserver.gameserver.model.entity.Siegable;
 import com.l2jserver.gameserver.model.entity.clanhall.SiegableHall;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.model.zone.AbstractZoneSettings;
 import com.l2jserver.gameserver.model.zone.L2ZoneType;
@@ -248,16 +248,16 @@ public class L2SiegeZone extends L2ZoneType
 			if (character.isPlayer() && character.getActingPlayer().isRegisteredOnThisSiegeField(getSettings().getSiegeableId()))
 			{
 				int lvl = 1;
-				final L2Effect e = character.getFirstEffect(5660);
-				if (e != null)
+				final BuffInfo info = character.getEffectList().getBuffInfoBySkillId(5660);
+				if (info != null)
 				{
-					lvl = Math.min(lvl + e.getSkill().getLevel(), 5);
+					lvl = Math.min(lvl + info.getSkill().getLevel(), 5);
 				}
 				
 				final L2Skill skill = SkillTable.getInstance().getInfo(5660, lvl);
 				if (skill != null)
 				{
-					skill.getEffects(character, character);
+					skill.applyEffects(character, null, character, null, false, false);
 				}
 			}
 		}

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/network/SystemMessageId.java

@@ -691,7 +691,7 @@ public final class SystemMessageId
 	
 	/**
 	 * ID: 110<br>
-	 * Message: $s1 $s2's effect can be felt.
+	 * Message: $s1's effect can be felt.
 	 */
 	public static final SystemMessageId YOU_FEEL_S1_EFFECT;
 	
@@ -4336,7 +4336,7 @@ public final class SystemMessageId
 	 * ID: 749<br>
 	 * Message: The effect of $s1 has been removed.
 	 */
-	public static final SystemMessageId EFFECT_S1_DISAPPEARED;
+	public static final SystemMessageId EFFECT_S1_HAS_BEEN_REMOVED;
 	
 	/**
 	 * ID: 750<br>
@@ -15922,7 +15922,7 @@ public final class SystemMessageId
 		YOU_ARE_NOT_IN_PETITION_CHAT = new SystemMessageId(745);
 		CURRENTLY_NO_PETITION = new SystemMessageId(746);
 		DIST_TOO_FAR_CASTING_STOPPED = new SystemMessageId(748);
-		EFFECT_S1_DISAPPEARED = new SystemMessageId(749);
+		EFFECT_S1_HAS_BEEN_REMOVED = new SystemMessageId(749);
 		NO_MORE_SKILLS_TO_LEARN = new SystemMessageId(750);
 		CANNOT_INVITE_CONFLICT_CLAN = new SystemMessageId(751);
 		CANNOT_USE_NAME = new SystemMessageId(752);

+ 14 - 11
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/Action.java

@@ -23,15 +23,12 @@ import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.PcCondOverride;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
-import com.l2jserver.gameserver.model.effects.L2EffectType;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
+import com.l2jserver.gameserver.model.skills.AbnormalType;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
 
-/**
- * This class ...
- * @version $Revision: 1.7.4.4 $ $Date: 2005/03/27 18:46:19 $
- */
 public final class Action extends L2GameClientPacket
 {
 	private static final String __C__1F_ACTION = "[C] 1F Action";
@@ -74,12 +71,18 @@ public final class Action extends L2GameClientPacket
 			return;
 		}
 		
-		L2Effect ef = null;
-		if (((ef = activeChar.getFirstEffect(L2EffectType.ACTION_BLOCK)) != null) && !ef.checkCondition(-4))
+		final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
+		if (info != null)
 		{
-			activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
-			activeChar.sendPacket(ActionFailed.STATIC_PACKET);
-			return;
+			for (AbstractEffect effect : info.getEffects())
+			{
+				if (!effect.checkCondition(-4))
+				{
+					activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
+					activeChar.sendPacket(ActionFailed.STATIC_PACKET);
+					return;
+				}
+			}
 		}
 		
 		final L2Object obj;

+ 14 - 7
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/Attack.java

@@ -22,8 +22,9 @@ import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.PcCondOverride;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
-import com.l2jserver.gameserver.model.effects.L2EffectType;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
+import com.l2jserver.gameserver.model.skills.AbnormalType;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
 
@@ -72,12 +73,18 @@ public final class Attack extends L2GameClientPacket
 			return;
 		}
 		
-		L2Effect ef = null;
-		if (((ef = activeChar.getFirstEffect(L2EffectType.ACTION_BLOCK)) != null) && !ef.checkCondition(-1))
+		final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
+		if (info != null)
 		{
-			activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
-			activeChar.sendPacket(ActionFailed.STATIC_PACKET);
-			return;
+			for (AbstractEffect effect : info.getEffects())
+			{
+				if (!effect.checkCondition(-1))
+				{
+					activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
+					activeChar.sendPacket(ActionFailed.STATIC_PACKET);
+					return;
+				}
+			}
 		}
 		
 		// avoid using expensive operations if not needed

+ 14 - 11
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/AttackRequest.java

@@ -22,15 +22,12 @@ import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.PcCondOverride;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
-import com.l2jserver.gameserver.model.effects.L2EffectType;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
+import com.l2jserver.gameserver.model.skills.AbnormalType;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
 
-/**
- * This class ...
- * @version $Revision: 1.7.2.1.2.2 $ $Date: 2005/03/27 15:29:30 $
- */
 public final class AttackRequest extends L2GameClientPacket
 {
 	private static final String _C__32_ATTACKREQUEST = "[C] 32 AttackRequest";
@@ -65,12 +62,18 @@ public final class AttackRequest extends L2GameClientPacket
 			return;
 		}
 		
-		L2Effect ef = null;
-		if (((ef = activeChar.getFirstEffect(L2EffectType.ACTION_BLOCK)) != null) && !ef.checkCondition(-1))
+		final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
+		if (info != null)
 		{
-			activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
-			activeChar.sendPacket(ActionFailed.STATIC_PACKET);
-			return;
+			for (AbstractEffect effect : info.getEffects())
+			{
+				if (!effect.checkCondition(-1))
+				{
+					activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
+					activeChar.sendPacket(ActionFailed.STATIC_PACKET);
+					return;
+				}
+			}
 		}
 		
 		// avoid using expensive operations if not needed

+ 14 - 6
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/RequestActionUse.java

@@ -39,8 +39,10 @@ import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2SiegeFlagInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2StaticObjectInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
 import com.l2jserver.gameserver.model.effects.L2EffectType;
+import com.l2jserver.gameserver.model.skills.AbnormalType;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.network.NpcStringId;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
@@ -105,12 +107,18 @@ public final class RequestActionUse extends L2GameClientPacket
 			return;
 		}
 		
-		L2Effect ef = null;
-		if (((ef = activeChar.getFirstEffect(L2EffectType.ACTION_BLOCK)) != null) && !ef.checkCondition(_actionId))
+		final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
+		if (info != null)
 		{
-			activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
-			activeChar.sendPacket(ActionFailed.STATIC_PACKET);
-			return;
+			for (AbstractEffect effect : info.getEffects())
+			{
+				if (!effect.checkCondition(_actionId))
+				{
+					activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
+					activeChar.sendPacket(ActionFailed.STATIC_PACKET);
+					return;
+				}
+			}
 		}
 		
 		// Don't allow to do some action if player is transformed

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/Say2.java

@@ -206,7 +206,7 @@ public final class Say2 extends L2GameClientPacket
 		
 		if (activeChar.isChatBanned() && (_text.charAt(0) != '.'))
 		{
-			if (activeChar.getFirstEffect(L2EffectType.CHAT_BLOCK) != null)
+			if (activeChar.getEffectList().getFirstEffect(L2EffectType.CHAT_BLOCK) != null)
 			{
 				activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_CHATTING_NOT_ALLOWED);
 			}

+ 27 - 13
L2J_Server_BETA/java/com/l2jserver/gameserver/network/clientpackets/TradeRequest.java

@@ -24,8 +24,9 @@ import com.l2jserver.gameserver.model.BlockList;
 import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.effects.L2Effect;
-import com.l2jserver.gameserver.model.effects.L2EffectType;
+import com.l2jserver.gameserver.model.effects.AbstractEffect;
+import com.l2jserver.gameserver.model.skills.AbnormalType;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
 import com.l2jserver.gameserver.network.serverpackets.SendTradeRequest;
@@ -60,12 +61,18 @@ public final class TradeRequest extends L2GameClientPacket
 			return;
 		}
 		
-		L2Effect ef = null;
-		if (((ef = player.getFirstEffect(L2EffectType.ACTION_BLOCK)) != null) && !ef.checkCondition(BotReportTable.TRADE_ACTION_BLOCK_ID))
+		BuffInfo info = player.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
+		if (info != null)
 		{
-			player.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
-			player.sendPacket(ActionFailed.STATIC_PACKET);
-			return;
+			for (AbstractEffect effect : info.getEffects())
+			{
+				if (!effect.checkCondition(BotReportTable.TRADE_ACTION_BLOCK_ID))
+				{
+					player.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
+					player.sendPacket(ActionFailed.STATIC_PACKET);
+					return;
+				}
+			}
 		}
 		
 		final L2Object target = L2World.getInstance().findObject(_objectId);
@@ -98,13 +105,20 @@ public final class TradeRequest extends L2GameClientPacket
 			return;
 		}
 		
-		if (((ef = partner.getFirstEffect(L2EffectType.ACTION_BLOCK)) != null) && !ef.checkCondition(BotReportTable.TRADE_ACTION_BLOCK_ID))
+		info = partner.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
+		if (info != null)
 		{
-			SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_REPORTED_AND_IS_BEING_INVESTIGATED);
-			sm.addCharName(partner);
-			player.sendPacket(sm);
-			player.sendPacket(ActionFailed.STATIC_PACKET);
-			return;
+			for (AbstractEffect effect : info.getEffects())
+			{
+				if (!effect.checkCondition(BotReportTable.TRADE_ACTION_BLOCK_ID))
+				{
+					final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_REPORTED_AND_IS_BEING_INVESTIGATED);
+					sm.addCharName(partner);
+					player.sendPacket(sm);
+					player.sendPacket(ActionFailed.STATIC_PACKET);
+					return;
+				}
+			}
 		}
 		
 		// L2J Customs: Karma punishment

+ 12 - 16
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/AbnormalStatusUpdate.java

@@ -21,25 +21,18 @@ package com.l2jserver.gameserver.network.serverpackets;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.l2jserver.gameserver.model.holders.EffectDurationHolder;
-import com.l2jserver.gameserver.model.skills.L2Skill;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 
 public class AbnormalStatusUpdate extends L2GameServerPacket
 {
-	private final List<EffectDurationHolder> _effects = new ArrayList<>();
+	private final List<BuffInfo> _effects = new ArrayList<>();
 	
-	public void addEffect(L2Skill skill, int duration)
+	public void addSkill(BuffInfo info)
 	{
-		switch (skill.getId())
+		if (!info.getSkill().isHealingPotionSkill())
 		{
-			case 2031:
-			case 2032:
-			case 2037:
-			case 26025:
-			case 26026:
-				return;
+			_effects.add(info);
 		}
-		_effects.add(new EffectDurationHolder(skill, duration));
 	}
 	
 	@Override
@@ -47,11 +40,14 @@ public class AbnormalStatusUpdate extends L2GameServerPacket
 	{
 		writeC(0x85);
 		writeH(_effects.size());
-		for (EffectDurationHolder edh : _effects)
+		for (BuffInfo info : _effects)
 		{
-			writeD(edh.getSkillId());
-			writeH(edh.getSkillLvl());
-			writeD(edh.getDuration());
+			if ((info != null) && info.isInUse())
+			{
+				writeD(info.getSkill().getId());
+				writeH(info.getSkill().getLevel());
+				writeD(info.getTime());
+			}
 		}
 	}
 }

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/AbstractNpcInfo.java

@@ -30,7 +30,7 @@ import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2NpcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2TrapInstance;
-import com.l2jserver.gameserver.model.effects.AbnormalEffect;
+import com.l2jserver.gameserver.model.skills.AbnormalVisualEffect;
 import com.l2jserver.gameserver.model.zone.ZoneId;
 
 public abstract class AbstractNpcInfo extends L2GameServerPacket
@@ -409,7 +409,7 @@ public abstract class AbstractNpcInfo extends L2GameServerPacket
 			writeD(_summon.getPvpFlag());
 			writeD(_summon.getKarma());
 			
-			writeD(gmSeeInvis ? _summon.getAbnormalEffect() | AbnormalEffect.STEALTH.getMask() : _summon.getAbnormalEffect());
+			writeD(gmSeeInvis ? _summon.getAbnormalEffect() | AbnormalVisualEffect.STEALTH.getMask() : _summon.getAbnormalEffect());
 			
 			writeD(0x00); // clan id
 			writeD(0x00); // crest id

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/CharInfo.java

@@ -25,8 +25,8 @@ import com.l2jserver.gameserver.model.PcCondOverride;
 import com.l2jserver.gameserver.model.actor.L2Decoy;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
-import com.l2jserver.gameserver.model.effects.AbnormalEffect;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
+import com.l2jserver.gameserver.model.skills.AbnormalVisualEffect;
 
 public class CharInfo extends L2GameServerPacket
 {
@@ -172,7 +172,7 @@ public class CharInfo extends L2GameServerPacket
 			writeD(_activeChar.getPvpFlag()); // pvp flag
 			writeD(_activeChar.getKarma()); // karma ??
 			
-			writeD(gmSeeInvis ? (_activeChar.getAbnormalEffect() | AbnormalEffect.STEALTH.getMask()) : _activeChar.getAbnormalEffect()); // C2
+			writeD(gmSeeInvis ? (_activeChar.getAbnormalEffect() | AbnormalVisualEffect.STEALTH.getMask()) : _activeChar.getAbnormalEffect()); // C2
 			
 			writeD(_activeChar.getClanId()); // clan id
 			writeD(_activeChar.getClanCrestId()); // crest id
@@ -284,7 +284,7 @@ public class CharInfo extends L2GameServerPacket
 			
 			writeC(_activeChar.isInPartyMatchRoom() ? 1 : 0);
 			
-			writeD(gmSeeInvis ? (_activeChar.getAbnormalEffect() | AbnormalEffect.STEALTH.getMask()) : _activeChar.getAbnormalEffect());
+			writeD(gmSeeInvis ? (_activeChar.getAbnormalEffect() | AbnormalVisualEffect.STEALTH.getMask()) : _activeChar.getAbnormalEffect());
 			
 			writeC(_activeChar.isFlyingMounted() ? 2 : 0);
 			

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/ConfirmDlg.java

@@ -25,9 +25,9 @@ import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.L2Summon;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.network.SystemMessageId;
 
@@ -162,9 +162,9 @@ public class ConfirmDlg extends L2GameServerPacket
 		return this;
 	}
 	
-	public ConfirmDlg addSkillName(L2Effect effect)
+	public ConfirmDlg addSkillName(BuffInfo info)
 	{
-		return addSkillName(effect.getSkill());
+		return addSkillName(info.getSkill());
 	}
 	
 	public ConfirmDlg addSkillName(L2Skill skill)

+ 11 - 9
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/ExOlympiadSpelledInfo.java

@@ -22,8 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.EffectDurationHolder;
-import com.l2jserver.gameserver.model.skills.L2Skill;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 
 /**
  * @author godson
@@ -31,16 +30,16 @@ import com.l2jserver.gameserver.model.skills.L2Skill;
 public class ExOlympiadSpelledInfo extends L2GameServerPacket
 {
 	private final int _playerId;
-	private final List<EffectDurationHolder> _effects = new ArrayList<>();
+	private final List<BuffInfo> _effects = new ArrayList<>();
 	
 	public ExOlympiadSpelledInfo(L2PcInstance player)
 	{
 		_playerId = player.getObjectId();
 	}
 	
-	public void addEffect(L2Skill skill, int duration)
+	public void addSkill(BuffInfo info)
 	{
-		_effects.add(new EffectDurationHolder(skill, duration));
+		_effects.add(info);
 	}
 	
 	@Override
@@ -50,11 +49,14 @@ public class ExOlympiadSpelledInfo extends L2GameServerPacket
 		writeH(0x7B);
 		writeD(_playerId);
 		writeD(_effects.size());
-		for (EffectDurationHolder edh : _effects)
+		for (BuffInfo info : _effects)
 		{
-			writeD(edh.getSkillId());
-			writeH(edh.getSkillLvl());
-			writeD(edh.getDuration());
+			if ((info != null) && info.isInUse())
+			{
+				writeD(info.getSkill().getId());
+				writeH(info.getSkill().getLevel());
+				writeD(info.getTime());
+			}
 		}
 	}
 }

+ 11 - 9
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/PartySpelled.java

@@ -22,12 +22,11 @@ import java.util.ArrayList;
 import java.util.List;
 
 import com.l2jserver.gameserver.model.actor.L2Character;
-import com.l2jserver.gameserver.model.holders.EffectDurationHolder;
-import com.l2jserver.gameserver.model.skills.L2Skill;
+import com.l2jserver.gameserver.model.skills.BuffInfo;
 
 public class PartySpelled extends L2GameServerPacket
 {
-	private final List<EffectDurationHolder> _effects = new ArrayList<>();
+	private final List<BuffInfo> _effects = new ArrayList<>();
 	private final L2Character _activeChar;
 	
 	public PartySpelled(L2Character cha)
@@ -35,9 +34,9 @@ public class PartySpelled extends L2GameServerPacket
 		_activeChar = cha;
 	}
 	
-	public void addPartySpelledEffect(L2Skill skill, int duration)
+	public void addSkill(BuffInfo info)
 	{
-		_effects.add(new EffectDurationHolder(skill, duration));
+		_effects.add(info);
 	}
 	
 	@Override
@@ -47,11 +46,14 @@ public class PartySpelled extends L2GameServerPacket
 		writeD(_activeChar.isServitor() ? 2 : _activeChar.isPet() ? 1 : 0);
 		writeD(_activeChar.getObjectId());
 		writeD(_effects.size());
-		for (EffectDurationHolder edh : _effects)
+		for (BuffInfo info : _effects)
 		{
-			writeD(edh.getSkillId());
-			writeH(edh.getSkillLvl());
-			writeD(edh.getDuration());
+			if ((info != null) && info.isInUse())
+			{
+				writeD(info.getSkill().getId());
+				writeH(info.getSkill().getLevel());
+				writeD(info.getTime());
+			}
 		}
 	}
 }

+ 2 - 0
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/ShortBuffStatusUpdate.java

@@ -20,6 +20,8 @@ package com.l2jserver.gameserver.network.serverpackets;
 
 public class ShortBuffStatusUpdate extends L2GameServerPacket
 {
+	public static final ShortBuffStatusUpdate RESET_SHORT_BUFF = new ShortBuffStatusUpdate(0, 0, 0);
+	
 	private final int _skillId;
 	private final int _skillLvl;
 	private final int _duration;

+ 0 - 6
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/SystemMessage.java

@@ -37,7 +37,6 @@ import com.l2jserver.gameserver.model.actor.L2Summon;
 import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
-import com.l2jserver.gameserver.model.effects.L2Effect;
 import com.l2jserver.gameserver.model.entity.Castle;
 import com.l2jserver.gameserver.model.items.L2Item;
 import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
@@ -334,11 +333,6 @@ public final class SystemMessage extends L2GameServerPacket
 		return this;
 	}
 	
-	public final SystemMessage addSkillName(final L2Effect effect)
-	{
-		return addSkillName(effect.getSkill());
-	}
-	
 	public final SystemMessage addSkillName(final L2Skill skill)
 	{
 		if (skill.getId() != skill.getDisplayId())

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/network/serverpackets/UserInfo.java

@@ -27,7 +27,7 @@ import com.l2jserver.gameserver.model.Elementals;
 import com.l2jserver.gameserver.model.PcCondOverride;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
-import com.l2jserver.gameserver.model.effects.AbnormalEffect;
+import com.l2jserver.gameserver.model.skills.AbnormalVisualEffect;
 
 public final class UserInfo extends L2GameServerPacket
 {
@@ -208,7 +208,7 @@ public final class UserInfo extends L2GameServerPacket
 		
 		writeC(_activeChar.isInPartyMatchRoom() ? 1 : 0);
 		
-		writeD(_activeChar.getAppearance().getInvisible() && _activeChar.isGM() ? _activeChar.getAbnormalEffect() | AbnormalEffect.STEALTH.getMask() : _activeChar.getAbnormalEffect());
+		writeD(_activeChar.getAppearance().getInvisible() && _activeChar.isGM() ? _activeChar.getAbnormalEffect() | AbnormalVisualEffect.STEALTH.getMask() : _activeChar.getAbnormalEffect());
 		writeC(_activeChar.isFlyingMounted() ? 2 : 0);
 		
 		writeD(_activeChar.getClanPrivileges());

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä