Bläddra i källkod

BETA: Cleaned up `L2NpcTemplate` removing all old AI skill getters and replacing them with a single one that takes `AISkillScope` as parameter.

Reviewed by: xban1x, !UnAfraid
Nos 11 år sedan
förälder
incheckning
6eeccc83f4

+ 40 - 38
L2J_Server_BETA/java/com/l2jserver/gameserver/ai/L2AttackableAI.java

@@ -34,6 +34,7 @@ import com.l2jserver.gameserver.GeoData;
 import com.l2jserver.gameserver.ThreadPoolManager;
 import com.l2jserver.gameserver.datatables.NpcData;
 import com.l2jserver.gameserver.datatables.TerritoryTable;
+import com.l2jserver.gameserver.enums.AISkillScope;
 import com.l2jserver.gameserver.enums.AIType;
 import com.l2jserver.gameserver.enums.QuestEventType;
 import com.l2jserver.gameserver.instancemanager.DimensionalRiftManager;
@@ -396,7 +397,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 		// self and buffs
 		if ((lastBuffTick + 30) < GameTimeController.getInstance().getGameTicks())
 		{
-			for (L2Skill sk : _skillrender.getBuffSkills())
+			for (L2Skill sk : _skillrender.getAISkills(AISkillScope.BUFF))
 			{
 				if (cast(sk))
 				{
@@ -637,7 +638,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 			}
 			else if (Rnd.nextInt(RANDOM_WALK_RATE) == 0)
 			{
-				for (L2Skill sk : _skillrender.getBuffSkills())
+				for (L2Skill sk : _skillrender.getAISkills(AISkillScope.BUFF))
 				{
 					if (cast(sk))
 					{
@@ -652,7 +653,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 			int x1, y1, z1;
 			final int range = Config.MAX_DRIFT_RANGE;
 			
-			for (L2Skill sk : _skillrender.getBuffSkills())
+			for (L2Skill sk : _skillrender.getAISkills(AISkillScope.BUFF))
 			{
 				if (cast(sk))
 				{
@@ -834,9 +835,10 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 		
 		final int combinedCollision = collision + mostHate.getTemplate().getCollisionRadius();
 		
-		if (!_skillrender.getSuicideSkills().isEmpty() && ((int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100) < 30))
+		List<L2Skill> aiSuicideSkills = _skillrender.getAISkills(AISkillScope.SUICIDE);
+		if (!aiSuicideSkills.isEmpty() && ((int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100) < 30))
 		{
-			final L2Skill skill = _skillrender.getSuicideSkills().get(Rnd.nextInt(_skillrender.getSuicideSkills().size()));
+			final L2Skill skill = aiSuicideSkills.get(Rnd.nextInt(aiSuicideSkills.size()));
 			if (Util.checkIfInRange(skill.getAffectRange(), getActiveChar(), mostHate, false) && (Rnd.get(100) < Rnd.get(npc.getMinSkillChance(), npc.getMaxSkillChance())))
 			{
 				if (cast(skill))
@@ -844,7 +846,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 					return;
 				}
 				
-				for (L2Skill sk : _skillrender.getSuicideSkills())
+				for (L2Skill sk : aiSuicideSkills)
 				{
 					if (cast(sk))
 					{
@@ -996,11 +998,12 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 			}
 		}
 		
-		if (!_skillrender.getGeneralskills().isEmpty())
+		if (!_skillrender.getAISkills(AISkillScope.GENERAL).isEmpty())
 		{
 			// -------------------------------------------------------------------------------
 			// Heal Condition
-			if (!_skillrender.getHealSkills().isEmpty())
+			List<L2Skill> aiHealSkills = _skillrender.getAISkills(AISkillScope.HEAL);
+			if (!aiHealSkills.isEmpty())
 			{
 				double percentage = (npc.getCurrentHp() / npc.getMaxHp()) * 100;
 				if (npc.isMinion())
@@ -1008,7 +1011,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 					L2Character leader = npc.getLeader();
 					if ((leader != null) && !leader.isDead() && (Rnd.get(100) > ((leader.getCurrentHp() / leader.getMaxHp()) * 100)))
 					{
-						for (L2Skill sk : _skillrender.getHealSkills())
+						for (L2Skill sk : aiHealSkills)
 						{
 							if (sk.getTargetType() == L2TargetType.SELF)
 							{
@@ -1036,7 +1039,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				}
 				if (Rnd.get(100) < ((100 - percentage) / 3))
 				{
-					for (L2Skill sk : _skillrender.getHealSkills())
+					for (L2Skill sk : aiHealSkills)
 					{
 						if (!checkSkillCastConditions(sk))
 						{
@@ -1048,7 +1051,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						return;
 					}
 				}
-				for (L2Skill sk : _skillrender.getHealSkills())
+				for (L2Skill sk : aiHealSkills)
 				{
 					if (!checkSkillCastConditions(sk))
 					{
@@ -1091,14 +1094,15 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 			}
 			// -------------------------------------------------------------------------------
 			// Res Skill Condition
-			if (!_skillrender.getResSkills().isEmpty())
+			List<L2Skill> aiResSkills = _skillrender.getAISkills(AISkillScope.HEAL);
+			if (!aiResSkills.isEmpty())
 			{
 				if (npc.isMinion())
 				{
 					L2Character leader = npc.getLeader();
 					if ((leader != null) && leader.isDead())
 					{
-						for (L2Skill sk : _skillrender.getResSkills())
+						for (L2Skill sk : aiResSkills)
 						{
 							if (sk.getTargetType() == L2TargetType.SELF)
 							{
@@ -1123,7 +1127,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 						}
 					}
 				}
-				for (L2Skill sk : _skillrender.getResSkills())
+				for (L2Skill sk : aiResSkills)
 				{
 					if (!checkSkillCastConditions(sk))
 					{
@@ -1191,16 +1195,17 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 		setTimepass(0);
 		// --------------------------------------------------------------------------------
 		// Skill Use
-		if (!_skillrender.getGeneralskills().isEmpty())
+		List<L2Skill> aiGeneralSkills = _skillrender.getAISkills(AISkillScope.GENERAL);
+		if (!aiGeneralSkills.isEmpty())
 		{
 			if (Rnd.get(100) < Rnd.get(npc.getMinSkillChance(), npc.getMaxSkillChance()))
 			{
-				L2Skill skills = _skillrender.getGeneralskills().get(Rnd.nextInt(_skillrender.getGeneralskills().size()));
+				L2Skill skills = aiGeneralSkills.get(Rnd.nextInt(aiGeneralSkills.size()));
 				if (cast(skills))
 				{
 					return;
 				}
-				for (L2Skill sk : _skillrender.getGeneralskills())
+				for (L2Skill sk : aiGeneralSkills)
 				{
 					if (cast(sk))
 					{
@@ -1283,21 +1288,18 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 			{
 				case -1:
 				{
-					if (_skillrender.getGeneralskills() != null)
+					for (L2Skill sk : _skillrender.getAISkills(AISkillScope.GENERAL))
 					{
-						for (L2Skill sk : _skillrender.getGeneralskills())
+						if (cast(sk))
 						{
-							if (cast(sk))
-							{
-								return;
-							}
+							return;
 						}
 					}
 					break;
 				}
 				case 1:
 				{
-					for (L2Skill sk : _skillrender.getAtkSkills())
+					for (L2Skill sk : _skillrender.getAISkills(AISkillScope.ATTACK))
 					{
 						if (cast(sk))
 						{
@@ -1308,7 +1310,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				}
 				default:
 				{
-					for (L2Skill sk : _skillrender.getGeneralskills())
+					for (L2Skill sk : _skillrender.getAISkills(AISkillScope.GENERAL))
 					{
 						if (sk.getId() == getActiveChar().getPrimarySkillId())
 						{
@@ -1841,14 +1843,14 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 			}
 			
 			// Check if activeChar has any skill
-			if (!_skillrender.getGeneralskills().isEmpty())
+			if (!_skillrender.getAISkills(AISkillScope.GENERAL).isEmpty())
 			{
 				// -------------------------------------------------------------
 				// Try to stop the target or disable the target as priority
 				int random = Rnd.get(100);
-				if (!_skillrender.getImmobiliseSkills().isEmpty() && !getAttackTarget().isImmobilized() && (random < 2))
+				if (!getAttackTarget().isImmobilized() && (random < 2))
 				{
-					for (L2Skill sk : _skillrender.getImmobiliseSkills())
+					for (L2Skill sk : _skillrender.getAISkills(AISkillScope.IMMOBILIZE))
 					{
 						if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
 						{
@@ -1871,9 +1873,9 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				}
 				// -------------------------------------------------------------
 				// Same as Above, but with Mute/FEAR etc....
-				if (!_skillrender.getCostOverTimeSkills().isEmpty() && (random < 5))
+				if (random < 5)
 				{
-					for (L2Skill sk : _skillrender.getCostOverTimeSkills())
+					for (L2Skill sk : _skillrender.getAISkills(AISkillScope.COT))
 					{
 						if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
 						{
@@ -1895,9 +1897,9 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 					}
 				}
 				// -------------------------------------------------------------
-				if (!_skillrender.getDebuffSkills().isEmpty() && (random < 8))
+				if (random < 8)
 				{
-					for (L2Skill sk : _skillrender.getDebuffSkills())
+					for (L2Skill sk : _skillrender.getAISkills(AISkillScope.DEBUFF))
 					{
 						if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
 						{
@@ -1920,9 +1922,9 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				}
 				// -------------------------------------------------------------
 				// Some side effect skill like CANCEL or NEGATE
-				if (!_skillrender.getNegativeSkills().isEmpty() && (random < 9))
+				if (random < 9)
 				{
-					for (L2Skill sk : _skillrender.getNegativeSkills())
+					for (L2Skill sk : _skillrender.getAISkills(AISkillScope.NEGATIVE))
 					{
 						if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
 						{
@@ -1945,9 +1947,9 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 				}
 				// -------------------------------------------------------------
 				// Start ATK SKILL when nothing can be done
-				if (!_skillrender.getAtkSkills().isEmpty() && (npc.isMovementDisabled() || (npc.getAiType() == AIType.MAGE) || (npc.getAiType() == AIType.HEALER)))
+				if ((npc.isMovementDisabled() || (npc.getAiType() == AIType.MAGE) || (npc.getAiType() == AIType.HEALER)))
 				{
-					for (L2Skill sk : _skillrender.getAtkSkills())
+					for (L2Skill sk : _skillrender.getAISkills(AISkillScope.ATTACK))
 					{
 						if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
 						{
@@ -2584,7 +2586,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 	
 	private List<L2Skill> longRangeSkillRender()
 	{
-		longRangeSkills = _skillrender.getLongRangeSkills();
+		longRangeSkills = _skillrender.getAISkills(AISkillScope.LONG_RANGE);
 		if (longRangeSkills.isEmpty())
 		{
 			longRangeSkills = getActiveChar().getLongRangeSkill();
@@ -2594,7 +2596,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
 	
 	private List<L2Skill> shortRangeSkillRender()
 	{
-		shortRangeSkills = _skillrender.getShortRangeSkills();
+		shortRangeSkills = _skillrender.getAISkills(AISkillScope.SHORT_RANGE);
 		if (shortRangeSkills.isEmpty())
 		{
 			shortRangeSkills = getActiveChar().getShortRangeSkill();

+ 111 - 7
L2J_Server_BETA/java/com/l2jserver/gameserver/datatables/NpcData.java

@@ -23,6 +23,7 @@ import java.sql.ResultSet;
 import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -38,6 +39,7 @@ import org.w3c.dom.Node;
 import com.l2jserver.Config;
 import com.l2jserver.L2DatabaseFactory;
 import com.l2jserver.gameserver.engines.DocumentParser;
+import com.l2jserver.gameserver.enums.AISkillScope;
 import com.l2jserver.gameserver.model.L2MinionData;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
@@ -46,8 +48,10 @@ import com.l2jserver.gameserver.model.drops.DropListScope;
 import com.l2jserver.gameserver.model.drops.GeneralDropItem;
 import com.l2jserver.gameserver.model.drops.GroupedGeneralDropItem;
 import com.l2jserver.gameserver.model.drops.IDropItem;
+import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
 import com.l2jserver.gameserver.model.skills.L2Skill;
+import com.l2jserver.gameserver.model.skills.L2SkillType;
 
 /**
  * @author Nos
@@ -99,7 +103,7 @@ public class NpcData extends DocumentParser
 						final StatsSet set = new StatsSet();
 						final int npcId = parseInteger(attrs, "id");
 						Map<String, Object> parameters = null;
-						List<L2Skill> skills = null;
+						Map<Integer, L2Skill> skills = null;
 						Set<Integer> clans = null;
 						Set<Integer> enemyClans = null;
 						Map<DropListScope, List<IDropItem>> dropLists = null;
@@ -308,7 +312,7 @@ public class NpcData extends DocumentParser
 								}
 								case "skill_list":
 								{
-									skills = new ArrayList<>();
+									skills = new HashMap<>();
 									for (Node skill_list_node = npc_node.getFirstChild(); skill_list_node != null; skill_list_node = skill_list_node.getNextSibling())
 									{
 										if ("skill".equalsIgnoreCase(skill_list_node.getNodeName()))
@@ -319,7 +323,7 @@ public class NpcData extends DocumentParser
 											final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLevel);
 											if (skill != null)
 											{
-												skills.add(skill);
+												skills.put(skill.getId(), skill);
 											}
 											else
 											{
@@ -421,7 +425,7 @@ public class NpcData extends DocumentParser
 										{
 											if (dropLists == null)
 											{
-												dropLists = new HashMap<>();
+												dropLists = new EnumMap<>(DropListScope.class);
 											}
 											
 											List<IDropItem> dropList = new ArrayList<>();
@@ -478,13 +482,113 @@ public class NpcData extends DocumentParser
 							template.setParameters(null);
 						}
 						
-						template.resetSkills();
 						if (skills != null)
 						{
-							for (L2Skill skill : skills)
+							Map<AISkillScope, List<L2Skill>> aiSkillLists = null;
+							for (L2Skill skill : skills.values())
 							{
-								template.addSkill(skill);
+								if (!skill.isPassive())
+								{
+									if (aiSkillLists == null)
+									{
+										aiSkillLists = new EnumMap<>(AISkillScope.class);
+									}
+									
+									List<AISkillScope> aiSkillScopes = new ArrayList<>();
+									final AISkillScope shortOrLongRangeScope = skill.getCastRange() <= 150 ? AISkillScope.SHORT_RANGE : AISkillScope.SHORT_RANGE;
+									if (skill.isSuicideAttack())
+									{
+										aiSkillScopes.add(AISkillScope.SUICIDE);
+									}
+									else
+									{
+										aiSkillScopes.add(AISkillScope.GENERAL);
+										
+										if (skill.isContinuous())
+										{
+											if (!skill.isDebuff())
+											{
+												aiSkillScopes.add(AISkillScope.BUFF);
+											}
+											else
+											{
+												aiSkillScopes.add(AISkillScope.DEBUFF);
+												aiSkillScopes.add(AISkillScope.COT);
+												aiSkillScopes.add(shortOrLongRangeScope);
+											}
+										}
+										else if (skill.getSkillType() == L2SkillType.DUMMY)
+										{
+											if (skill.hasEffectType(L2EffectType.DISPEL, L2EffectType.DISPEL_BY_SLOT))
+											{
+												aiSkillScopes.add(AISkillScope.NEGATIVE);
+												aiSkillScopes.add(shortOrLongRangeScope);
+											}
+											else if (skill.hasEffectType(L2EffectType.HEAL, L2EffectType.HEAL_PERCENT))
+											{
+												aiSkillScopes.add(AISkillScope.HEAL);
+											}
+											else if (skill.hasEffectType(L2EffectType.PHYSICAL_ATTACK, L2EffectType.PHYSICAL_ATTACK_HP_LINK, L2EffectType.FATAL_BLOW, L2EffectType.ENERGY_ATTACK, L2EffectType.MAGICAL_ATTACK_MP, L2EffectType.MAGICAL_ATTACK, L2EffectType.DEATH_LINK, L2EffectType.HP_DRAIN))
+											{
+												aiSkillScopes.add(AISkillScope.ATTACK);
+												aiSkillScopes.add(AISkillScope.UNIVERSAL);
+												aiSkillScopes.add(shortOrLongRangeScope);
+											}
+											else if (skill.hasEffectType(L2EffectType.SLEEP))
+											{
+												aiSkillScopes.add(AISkillScope.IMMOBILIZE);
+											}
+											else if (skill.hasEffectType(L2EffectType.STUN, L2EffectType.ROOT))
+											{
+												aiSkillScopes.add(AISkillScope.IMMOBILIZE);
+												aiSkillScopes.add(shortOrLongRangeScope);
+											}
+											else if (skill.hasEffectType(L2EffectType.MUTE, L2EffectType.FEAR))
+											{
+												aiSkillScopes.add(AISkillScope.COT);
+												aiSkillScopes.add(shortOrLongRangeScope);
+											}
+											else if (skill.hasEffectType(L2EffectType.PARALYZE))
+											{
+												aiSkillScopes.add(AISkillScope.IMMOBILIZE);
+												aiSkillScopes.add(shortOrLongRangeScope);
+											}
+											else if (skill.hasEffectType(L2EffectType.DMG_OVER_TIME, L2EffectType.DMG_OVER_TIME_PERCENT))
+											{
+												aiSkillScopes.add(shortOrLongRangeScope);
+											}
+											else if (skill.hasEffectType(L2EffectType.RESURRECTION))
+											{
+												aiSkillScopes.add(AISkillScope.RES);
+											}
+											else
+											{
+												aiSkillScopes.add(AISkillScope.UNIVERSAL);
+											}
+										}
+									}
+									
+									for (AISkillScope aiSkillScope : aiSkillScopes)
+									{
+										List<L2Skill> aiSkills = aiSkillLists.get(aiSkillScope);
+										if (aiSkills == null)
+										{
+											aiSkills = new ArrayList<>();
+											aiSkillLists.put(aiSkillScope, aiSkills);
+										}
+										
+										aiSkills.add(skill);
+									}
+								}
 							}
+							
+							template.setSkills(skills);
+							template.setAISkillLists(aiSkillLists);
+						}
+						else
+						{
+							template.setSkills(null);
+							template.setAISkillLists(null);
 						}
 						
 						template.setClans(clans);

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/enums/AISkillType.java → L2J_Server_BETA/java/com/l2jserver/gameserver/enums/AISkillScope.java

@@ -21,7 +21,7 @@ package com.l2jserver.gameserver.enums;
 /**
  * @author Zoey76
  */
-public enum AISkillType
+public enum AISkillScope
 {
 	BUFF,
 	DEBUFF,

+ 7 - 12
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Npc.java

@@ -34,6 +34,7 @@ import com.l2jserver.gameserver.cache.HtmCache;
 import com.l2jserver.gameserver.datatables.CategoryData;
 import com.l2jserver.gameserver.datatables.ItemTable;
 import com.l2jserver.gameserver.datatables.NpcPersonalAIData;
+import com.l2jserver.gameserver.enums.AISkillScope;
 import com.l2jserver.gameserver.enums.AIType;
 import com.l2jserver.gameserver.enums.CategoryType;
 import com.l2jserver.gameserver.enums.InstanceType;
@@ -243,14 +244,11 @@ public class L2Npc extends L2Character
 			}
 			case 1:
 			{
-				if (getTemplate().getUniversalSkills() != null)
+				for (L2Skill sk : getTemplate().getAISkills(AISkillScope.UNIVERSAL))
 				{
-					for (L2Skill sk : getTemplate().getUniversalSkills())
+					if (sk.getCastRange() >= 200)
 					{
-						if (sk.getCastRange() >= 200)
-						{
-							skilldata.add(sk);
-						}
+						skilldata.add(sk);
 					}
 				}
 				break;
@@ -300,14 +298,11 @@ public class L2Npc extends L2Character
 			}
 			case 1:
 			{
-				if (getTemplate().getUniversalSkills() != null)
+				for (L2Skill sk : getTemplate().getAISkills(AISkillScope.UNIVERSAL))
 				{
-					for (L2Skill sk : getTemplate().getUniversalSkills())
+					if (sk.getCastRange() <= 200)
 					{
-						if (sk.getCastRange() <= 200)
-						{
-							skilldata.add(sk);
-						}
+						skilldata.add(sk);
 					}
 				}
 				break;

+ 29 - 272
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/templates/L2NpcTemplate.java

@@ -30,7 +30,7 @@ import java.util.logging.Logger;
 
 import com.l2jserver.Config;
 import com.l2jserver.gameserver.datatables.NpcData;
-import com.l2jserver.gameserver.enums.AISkillType;
+import com.l2jserver.gameserver.enums.AISkillScope;
 import com.l2jserver.gameserver.enums.AIType;
 import com.l2jserver.gameserver.enums.NpcRace;
 import com.l2jserver.gameserver.enums.QuestEventType;
@@ -41,12 +41,10 @@ import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.base.ClassId;
 import com.l2jserver.gameserver.model.drops.DropListScope;
 import com.l2jserver.gameserver.model.drops.IDropItem;
-import com.l2jserver.gameserver.model.effects.L2EffectType;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
 import com.l2jserver.gameserver.model.interfaces.IIdentifiable;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.skills.L2Skill;
-import com.l2jserver.gameserver.model.skills.L2SkillType;
 
 /**
  * NPC template.
@@ -103,14 +101,14 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 	private int _shortRangeSkillChance;
 	private int _longRangeSkillId;
 	private int _longRangeSkillChance;
+	private Map<Integer, L2Skill> _skills;
+	private Map<AISkillScope, List<L2Skill>> _aiSkillLists;
 	private Set<Integer> _clans;
 	private Set<Integer> _enemyClans;
 	private Map<DropListScope, List<IDropItem>> _dropLists;
 	private double _collisionRadiusGrown;
 	private double _collisionHeightGrown;
 	
-	private final Map<AISkillType, List<L2Skill>> _aiSkills = new ConcurrentHashMap<>();
-	private final Map<Integer, L2Skill> _skills = new ConcurrentHashMap<>();
 	private final List<L2MinionData> _minions = new ArrayList<>();
 	private final List<ClassId> _teachInfo = new ArrayList<>();
 	private final Map<QuestEventType, List<Quest>> _questEvents = new ConcurrentHashMap<>();
@@ -437,6 +435,28 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 		return _longRangeSkillChance;
 	}
 	
+	@Override
+	public Map<Integer, L2Skill> getSkills()
+	{
+		return _skills;
+	}
+	
+	public void setSkills(Map<Integer, L2Skill> skills)
+	{
+		_skills = skills != null ? Collections.unmodifiableMap(skills) : Collections.<Integer, L2Skill> emptyMap();
+	}
+	
+	public List<L2Skill> getAISkills(AISkillScope aiSkillScope)
+	{
+		final List<L2Skill> aiSkills = _aiSkillLists.get(aiSkillScope);
+		return aiSkills != null ? aiSkills : Collections.<L2Skill> emptyList();
+	}
+	
+	public void setAISkillLists(Map<AISkillScope, List<L2Skill>> aiSkillLists)
+	{
+		_aiSkillLists = aiSkillLists != null ? Collections.unmodifiableMap(aiSkillLists) : Collections.<AISkillScope, List<L2Skill>> emptyMap();
+	}
+	
 	public Set<Integer> getClans()
 	{
 		return _clans;
@@ -653,15 +673,6 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 		return _collisionHeightGrown;
 	}
 	
-	public void resetSkills()
-	{
-		for (AISkillType type : AISkillType.values())
-		{
-			_aiSkills.put(type, new ArrayList<L2Skill>());
-		}
-		_skills.clear();
-	}
-	
 	public static boolean isAssignableTo(Class<?> sub, Class<?> clazz)
 	{
 		// If clazz represents an interface
@@ -705,46 +716,6 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 		return L2NpcTemplate.isAssignableTo(obj.getClass(), clazz);
 	}
 	
-	public void addAtkSkill(L2Skill skill)
-	{
-		getAtkSkills().add(skill);
-	}
-	
-	public void addBuffSkill(L2Skill skill)
-	{
-		getBuffSkills().add(skill);
-	}
-	
-	public void addCOTSkill(L2Skill skill)
-	{
-		getCostOverTimeSkills().add(skill);
-	}
-	
-	public void addDebuffSkill(L2Skill skill)
-	{
-		getDebuffSkills().add(skill);
-	}
-	
-	public void addGeneralSkill(L2Skill skill)
-	{
-		getGeneralskills().add(skill);
-	}
-	
-	public void addHealSkill(L2Skill skill)
-	{
-		getHealSkills().add(skill);
-	}
-	
-	public void addImmobiliseSkill(L2Skill skill)
-	{
-		getImmobiliseSkills().add(skill);
-	}
-	
-	public void addNegativeSkill(L2Skill skill)
-	{
-		getNegativeSkills().add(skill);
-	}
-	
 	public void addQuestEvent(QuestEventType eventType, Quest q)
 	{
 		if (!_questEvents.containsKey(eventType))
@@ -791,118 +762,6 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 		_minions.add(minion);
 	}
 	
-	public void addRangeSkill(L2Skill skill)
-	{
-		if ((skill.getCastRange() <= 150) && (skill.getCastRange() > 0))
-		{
-			getShortRangeSkills().add(skill);
-		}
-		else if (skill.getCastRange() > 150)
-		{
-			getLongRangeSkills().add(skill);
-		}
-	}
-	
-	public void addResSkill(L2Skill skill)
-	{
-		getResSkills().add(skill);
-	}
-	
-	public void addSkill(L2Skill skill)
-	{
-		if (!skill.isPassive())
-		{
-			if (skill.isSuicideAttack())
-			{
-				addSuicideSkill(skill);
-			}
-			else
-			{
-				addGeneralSkill(skill);
-				
-				if (skill.isContinuous())
-				{
-					if (!skill.isDebuff())
-					{
-						addBuffSkill(skill);
-					}
-					else
-					{
-						addDebuffSkill(skill);
-						addCOTSkill(skill);
-						addRangeSkill(skill);
-					}
-				}
-				else if (skill.getSkillType() == L2SkillType.DUMMY)
-				{
-					if (skill.hasEffectType(L2EffectType.DISPEL, L2EffectType.DISPEL_BY_SLOT))
-					{
-						addNegativeSkill(skill);
-						addRangeSkill(skill);
-					}
-					else if (skill.hasEffectType(L2EffectType.HEAL, L2EffectType.HEAL_PERCENT))
-					{
-						addHealSkill(skill);
-					}
-					else if (skill.hasEffectType(L2EffectType.PHYSICAL_ATTACK, L2EffectType.PHYSICAL_ATTACK_HP_LINK, L2EffectType.FATAL_BLOW, L2EffectType.ENERGY_ATTACK, L2EffectType.MAGICAL_ATTACK_MP, L2EffectType.MAGICAL_ATTACK, L2EffectType.DEATH_LINK, L2EffectType.HP_DRAIN))
-					{
-						addAtkSkill(skill);
-						addUniversalSkill(skill);
-						addRangeSkill(skill);
-					}
-					else if (skill.hasEffectType(L2EffectType.SLEEP))
-					{
-						addImmobiliseSkill(skill);
-					}
-					else if (skill.hasEffectType(L2EffectType.STUN, L2EffectType.ROOT))
-					{
-						addImmobiliseSkill(skill);
-						addRangeSkill(skill);
-					}
-					else if (skill.hasEffectType(L2EffectType.MUTE, L2EffectType.FEAR))
-					{
-						addCOTSkill(skill);
-						addRangeSkill(skill);
-					}
-					else if (skill.hasEffectType(L2EffectType.PARALYZE))
-					{
-						addImmobiliseSkill(skill);
-						addRangeSkill(skill);
-					}
-					else if (skill.hasEffectType(L2EffectType.DMG_OVER_TIME, L2EffectType.DMG_OVER_TIME_PERCENT))
-					{
-						addRangeSkill(skill);
-					}
-					else if (skill.hasEffectType(L2EffectType.RESURRECTION))
-					{
-						addResSkill(skill);
-					}
-					else
-					{
-						addUniversalSkill(skill);
-					}
-				}
-			}
-		}
-		
-		_skills.put(skill.getId(), skill);
-	}
-	
-	public void addSuicideSkill(L2Skill skill)
-	{
-		getSuicideSkills().add(skill);
-	}
-	
-	public void addTeachInfo(List<ClassId> teachInfo)
-	{
-		_teachInfo.addAll(teachInfo);
-	}
-	
-	public void addUniversalSkill(L2Skill skill)
-	{
-		getUniversalSkills().add(skill);
-	}
-	
 	public boolean canTeach(ClassId classId)
 	{
 		// If the player is on a third class, fetch the class teacher
@@ -914,38 +773,6 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 		return _teachInfo.contains(classId);
 	}
 	
-	/**
-	 * @return the attack skills.
-	 */
-	public List<L2Skill> getAtkSkills()
-	{
-		return _aiSkills.get(AISkillType.ATTACK);
-	}
-	
-	/**
-	 * @return the buff skills.
-	 */
-	public List<L2Skill> getBuffSkills()
-	{
-		return _aiSkills.get(AISkillType.BUFF);
-	}
-	
-	/**
-	 * @return the cost over time skills.
-	 */
-	public List<L2Skill> getCostOverTimeSkills()
-	{
-		return _aiSkills.get(AISkillType.COT);
-	}
-	
-	/**
-	 * @return the debuff skills.
-	 */
-	public List<L2Skill> getDebuffSkills()
-	{
-		return _aiSkills.get(AISkillType.DEBUFF);
-	}
-	
 	public Map<QuestEventType, List<Quest>> getEventQuests()
 	{
 		return _questEvents;
@@ -956,38 +783,6 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 		return _questEvents.get(EventType);
 	}
 	
-	/**
-	 * @return the general skills.
-	 */
-	public List<L2Skill> getGeneralskills()
-	{
-		return _aiSkills.get(AISkillType.GENERAL);
-	}
-	
-	/**
-	 * @return the heal skills.
-	 */
-	public List<L2Skill> getHealSkills()
-	{
-		return _aiSkills.get(AISkillType.HEAL);
-	}
-	
-	/**
-	 * @return the immobilize skills.
-	 */
-	public List<L2Skill> getImmobiliseSkills()
-	{
-		return _aiSkills.get(AISkillType.IMMOBILIZE);
-	}
-	
-	/**
-	 * @return the long range skills.
-	 */
-	public List<L2Skill> getLongRangeSkills()
-	{
-		return _aiSkills.get(AISkillType.LONG_RANGE);
-	}
-	
 	/**
 	 * @return the list of all Minions that must be spawn with the L2NpcInstance using this L2NpcTemplate.
 	 */
@@ -996,51 +791,13 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
 		return _minions;
 	}
 	
-	/**
-	 * @return the negative skills.
-	 */
-	public List<L2Skill> getNegativeSkills()
-	{
-		return _aiSkills.get(AISkillType.NEGATIVE);
-	}
-	
-	/**
-	 * @return the resurrection skills.
-	 */
-	public List<L2Skill> getResSkills()
-	{
-		return _aiSkills.get(AISkillType.RES);
-	}
-	
-	/**
-	 * @return the short range skills.
-	 */
-	public List<L2Skill> getShortRangeSkills()
-	{
-		return _aiSkills.get(AISkillType.SHORT_RANGE);
-	}
-	
-	/**
-	 * @return the universal skills.
-	 */
-	public List<L2Skill> getUniversalSkills()
-	{
-		return _aiSkills.get(AISkillType.UNIVERSAL);
-	}
-	
-	public List<L2Skill> getSuicideSkills()
-	{
-		return _aiSkills.get(AISkillType.SUICIDE);
-	}
-	
-	@Override
-	public Map<Integer, L2Skill> getSkills()
+	public List<ClassId> getTeachInfo()
 	{
-		return _skills;
+		return _teachInfo;
 	}
 	
-	public List<ClassId> getTeachInfo()
+	public void addTeachInfo(List<ClassId> teachInfo)
 	{
-		return _teachInfo;
+		_teachInfo.addAll(teachInfo);
 	}
 }