diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00134_TempleMissionary/Q00134_TempleMissionary.java b/src/main/java/com/l2jserver/datapack/quests/Q00134_TempleMissionary/Q00134_TempleMissionary.java
index 622cc1b77b2dd9f7ce0f3864edb5ccb511e2cce6..4da12a5cfb583096ddef27229d6366949881245a 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00134_TempleMissionary/Q00134_TempleMissionary.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00134_TempleMissionary/Q00134_TempleMissionary.java
@@ -19,12 +19,12 @@
 package com.l2jserver.datapack.quests.Q00134_TempleMissionary;
 
 import java.util.HashMap;
-import java.util.Map;
 
 import com.l2jserver.gameserver.enums.audio.Sound;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestDroplist;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.model.quest.State;
 
@@ -36,24 +36,25 @@ public class Q00134_TempleMissionary extends Quest {
 	// NPCs
 	private static final int GLYVKA = 30067;
 	private static final int ROUKE = 31418;
+	// Monsters
+	private static final int CRUMA_MARSHLANDS_TRAITOR = 27339;
 	// Items
 	private static final int GIANTS_EXPERIMENTAL_TOOL_FRAGMENT = 10335;
 	private static final int GIANTS_EXPERIMENTAL_TOOL = 10336;
 	private static final int GIANTS_TECHNOLOGY_REPORT = 10337;
 	private static final int ROUKES_REPOT = 10338;
 	private static final int BADGE_TEMPLE_MISSIONARY = 10339;
-	// Monsters
-	private static final int CRUMA_MARSHLANDS_TRAITOR = 27339;
-	private static final Map<Integer, Integer> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20157, 78); // Marsh Stakato
-		MOBS.put(20229, 75); // Stinger Wasp
-		MOBS.put(20230, 86); // Marsh Stakato Worker
-		MOBS.put(20231, 83); // Toad Lord
-		MOBS.put(20232, 81); // Marsh Stakato Soldier
-		MOBS.put(20233, 95); // Marsh Spider
-		MOBS.put(20234, 96); // Marsh Stakato Drone
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20157, GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, 78.0) // Marsh Stakato
+			.addSingleDrop(20229, GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, 75.0) // Stinger Wasp
+			.addSingleDrop(20230, GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, 86.0) // Marsh Stakato Worker
+			.addSingleDrop(20231, GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, 83.0) // Toad Lord
+			.addSingleDrop(20232, GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, 81.0) // Marsh Stakato Soldier
+			.addSingleDrop(20233, GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, 95.0) // Marsh Spider
+			.addSingleDrop(20234, GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, 96.0) // Marsh Stakato Drone
+			.build();
+
 	// Misc
 	private static final int MIN_LEVEL = 35;
 	private static final int MAX_REWARD_LEVEL = 41;
@@ -65,7 +66,7 @@ public class Q00134_TempleMissionary extends Quest {
 		addStartNpc(GLYVKA);
 		addTalkId(GLYVKA, ROUKE);
 		addKillId(CRUMA_MARSHLANDS_TRAITOR);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, GIANTS_EXPERIMENTAL_TOOL, GIANTS_TECHNOLOGY_REPORT, ROUKES_REPOT);
 	}
 	
@@ -131,9 +132,8 @@ public class Q00134_TempleMissionary extends Quest {
 				if (getRandom(100) != 0) {
 					addSpawn(CRUMA_MARSHLANDS_TRAITOR, npc.getX() + 20, npc.getY() + 20, npc.getZ(), npc.getHeading(), false, 60000);
 				}
-			} else if (getRandom(100) < MOBS.get(npc.getId())) {
-				st.giveItems(GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, 1);
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
+			} else {
+				giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 			}
 		}
 		return super.onKill(npc, player, isSummon);
@@ -188,7 +188,7 @@ public class Q00134_TempleMissionary extends Quest {
 							if ((st.getQuestItemsCount(GIANTS_EXPERIMENTAL_TOOL_FRAGMENT) < FRAGMENT_COUNT) && (st.getQuestItemsCount(GIANTS_TECHNOLOGY_REPORT) < REPORT_COUNT)) {
 								htmltext = "31418-04.html";
 							} else if (st.getQuestItemsCount(GIANTS_EXPERIMENTAL_TOOL_FRAGMENT) >= FRAGMENT_COUNT) {
-								final int count = (int) (st.getQuestItemsCount(GIANTS_EXPERIMENTAL_TOOL_FRAGMENT) / 10);
+								final long count = st.getQuestItemsCount(GIANTS_EXPERIMENTAL_TOOL_FRAGMENT) / 10;
 								st.takeItems(GIANTS_EXPERIMENTAL_TOOL_FRAGMENT, count * 10);
 								st.giveItems(GIANTS_EXPERIMENTAL_TOOL, count);
 								htmltext = "31418-05.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00135_TempleExecutor/Q00135_TempleExecutor.java b/src/main/java/com/l2jserver/datapack/quests/Q00135_TempleExecutor/Q00135_TempleExecutor.java
index da3db706a2393fd1faeba16ca139f1ae5005572e..b613a5f2ef9384901ee27d456c55185ddbf00a7b 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00135_TempleExecutor/Q00135_TempleExecutor.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00135_TempleExecutor/Q00135_TempleExecutor.java
@@ -18,12 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00135_TempleExecutor;
 
-import java.util.HashMap;
-import java.util.Map;
-
+import com.l2jserver.gameserver.enums.audio.Sound;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestDroplist;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.model.quest.State;
 
@@ -38,33 +38,31 @@ public class Q00135_TempleExecutor extends Quest {
 	private static final int ALEX = 30291;
 	private static final int SONIN = 31773;
 	// Items
-	private static final int STOLEN_CARGO = 10328;
-	private static final int HATE_CRYSTAL = 10329;
-	private static final int OLD_TREASURE_MAP = 10330;
 	private static final int SONINS_CREDENTIALS = 10331;
 	private static final int PANOS_CREDENTIALS = 10332;
 	private static final int ALEXS_CREDENTIALS = 10333;
 	private static final int BADGE_TEMPLE_EXECUTOR = 10334;
-	// Monsters
-	private static final Map<Integer, Integer> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20781, 439); // Delu Lizardman Shaman
-		MOBS.put(21104, 439); // Delu Lizardman Supplier
-		MOBS.put(21105, 504); // Delu Lizardman Special Agent
-		MOBS.put(21106, 423); // Cursed Seer
-		MOBS.put(21107, 902); // Delu Lizardman Commander
-	}
+	private static final QuestItemChanceHolder STOLEN_CARGO = new QuestItemChanceHolder(10328, 10L);
+	private static final QuestItemChanceHolder HATE_CRYSTAL = new QuestItemChanceHolder(10329, 10L);
+	private static final QuestItemChanceHolder OLD_TREASURE_MAP = new QuestItemChanceHolder(10330, 10L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20781, STOLEN_CARGO, 43.9).addSingleDrop(20781, HATE_CRYSTAL, 43.9).addSingleDrop(20781, OLD_TREASURE_MAP, 43.9) // Delu Lizardman Shaman
+			.addSingleDrop(21104, STOLEN_CARGO, 43.9).addSingleDrop(21104, HATE_CRYSTAL, 43.9).addSingleDrop(21104, OLD_TREASURE_MAP, 43.9) // Delu Lizardman Supplier
+			.addSingleDrop(21105, STOLEN_CARGO, 50.4).addSingleDrop(21105, HATE_CRYSTAL, 50.4).addSingleDrop(21105, OLD_TREASURE_MAP, 50.4) // Delu Lizardman Special Agent
+			.addSingleDrop(21106, STOLEN_CARGO, 42.3).addSingleDrop(21106, HATE_CRYSTAL, 42.3).addSingleDrop(21106, OLD_TREASURE_MAP, 42.3) // Cursed Seer
+			.addSingleDrop(21107, STOLEN_CARGO, 90.2).addSingleDrop(21107, HATE_CRYSTAL, 90.2).addSingleDrop(21107, OLD_TREASURE_MAP, 90.2) // Delu Lizardman Commander
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 35;
-	private static final int ITEM_COUNT = 10;
 	private static final int MAX_REWARD_LEVEL = 41;
 	
 	public Q00135_TempleExecutor() {
 		super(135, Q00135_TempleExecutor.class.getSimpleName(), "Temple Executor");
 		addStartNpc(SHEGFIELD);
 		addTalkId(SHEGFIELD, ALEX, SONIN, PANO);
-		addKillId(MOBS.keySet());
-		registerQuestItems(STOLEN_CARGO, HATE_CRYSTAL, OLD_TREASURE_MAP, SONINS_CREDENTIALS, PANOS_CREDENTIALS, ALEXS_CREDENTIALS);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(STOLEN_CARGO.getId(), HATE_CRYSTAL.getId(), OLD_TREASURE_MAP.getId(), SONINS_CREDENTIALS, PANOS_CREDENTIALS, ALEXS_CREDENTIALS);
 	}
 	
 	@Override
@@ -116,18 +114,18 @@ public class Q00135_TempleExecutor extends Quest {
 			return super.onKill(npc, player, isSummon);
 		}
 		final QuestState st = getQuestState(member, false);
-		if ((getRandom(1000) < MOBS.get(npc.getId()))) {
-			if (st.getQuestItemsCount(STOLEN_CARGO) < ITEM_COUNT) {
-				st.giveItems(STOLEN_CARGO, 1);
-			} else if (st.getQuestItemsCount(HATE_CRYSTAL) < ITEM_COUNT) {
-				st.giveItems(HATE_CRYSTAL, 1);
-			} else {
-				st.giveItems(OLD_TREASURE_MAP, 1);
-			}
+		if (!hasItemsAtLimit(st.getPlayer(), STOLEN_CARGO)) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), false);
+		} else if (!hasItemsAtLimit(st.getPlayer(), HATE_CRYSTAL)) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc, HATE_CRYSTAL), false);
+		} else {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc, OLD_TREASURE_MAP), false);
+		}
 			
-			if ((st.getQuestItemsCount(STOLEN_CARGO) >= ITEM_COUNT) && (st.getQuestItemsCount(HATE_CRYSTAL) >= ITEM_COUNT) && (st.getQuestItemsCount(OLD_TREASURE_MAP) >= ITEM_COUNT)) {
-				st.setCond(4, true);
-			}
+		if (hasItemsAtLimit(st.getPlayer(), STOLEN_CARGO, HATE_CRYSTAL, OLD_TREASURE_MAP)) {
+			st.setCond(4, true);
+		} else {
+			playSound(st.getPlayer(), Sound.ITEMSOUND_QUEST_ITEMGET);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
@@ -194,11 +192,11 @@ public class Q00135_TempleExecutor extends Quest {
 							break;
 						case 4:
 							if (st.hasQuestItems(PANOS_CREDENTIALS, SONINS_CREDENTIALS)) {
-								if (st.getQuestItemsCount(OLD_TREASURE_MAP) < ITEM_COUNT) {
+								if (!hasItemsAtLimit(st.getPlayer(), OLD_TREASURE_MAP)) {
 									return htmltext;
 								}
 								st.setCond(5, true);
-								st.takeItems(OLD_TREASURE_MAP, -1);
+								st.takeItems(OLD_TREASURE_MAP.getId(), -1);
 								st.giveItems(ALEXS_CREDENTIALS, 1);
 								htmltext = "30291-10.html";
 							} else {
@@ -225,10 +223,10 @@ public class Q00135_TempleExecutor extends Quest {
 							break;
 						case 4:
 							if (!st.isSet("Pano")) {
-								if (st.getQuestItemsCount(HATE_CRYSTAL) < ITEM_COUNT) {
+								if (!hasItemsAtLimit(st.getPlayer(), HATE_CRYSTAL)) {
 									return htmltext;
 								}
-								st.takeItems(HATE_CRYSTAL, -1);
+								st.takeItems(HATE_CRYSTAL.getId(), -1);
 								st.giveItems(PANOS_CREDENTIALS, 1);
 								st.set("Pano", "1");
 								htmltext = "30078-04.html";
@@ -254,10 +252,10 @@ public class Q00135_TempleExecutor extends Quest {
 							break;
 						case 4:
 							if (!st.isSet("Sonin")) {
-								if (st.getQuestItemsCount(STOLEN_CARGO) < ITEM_COUNT) {
+								if (!hasItemsAtLimit(st.getPlayer(), STOLEN_CARGO)) {
 									return htmltext;
 								}
-								st.takeItems(STOLEN_CARGO, -1);
+								st.takeItems(STOLEN_CARGO.getId(), -1);
 								st.giveItems(SONINS_CREDENTIALS, 1);
 								st.set("Sonin", "1");
 								htmltext = "31773-04.html";
@@ -272,4 +270,4 @@ public class Q00135_TempleExecutor extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00137_TempleChampionPart1/Q00137_TempleChampionPart1.java b/src/main/java/com/l2jserver/datapack/quests/Q00137_TempleChampionPart1/Q00137_TempleChampionPart1.java
index 85abed419011690c0c301b79a4a81175b9693c1f..e1de64493e5faf48dccba2b242d9653c3bfc1c98 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00137_TempleChampionPart1/Q00137_TempleChampionPart1.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00137_TempleChampionPart1/Q00137_TempleChampionPart1.java
@@ -18,9 +18,9 @@
  */
 package com.l2jserver.datapack.quests.Q00137_TempleChampionPart1;
 
-import com.l2jserver.gameserver.enums.audio.Sound;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
@@ -31,7 +31,8 @@ import com.l2jserver.gameserver.model.quest.QuestState;
 public class Q00137_TempleChampionPart1 extends Quest {
 	// NPCs
 	private static final int SYLVAIN = 30070;
-	private static final int MOBS[] = {
+	// Monsters
+	private static final int[] MOBS = {
 		20083, // Granite Golem
 		20144, // Hangman Tree
 		20199, // Amber Basilisk
@@ -40,16 +41,16 @@ public class Q00137_TempleChampionPart1 extends Quest {
 		20202, // Dead Seeker
 	};
 	// Items
-	private static final int FRAGMENT = 10340;
 	private static final int EXECUTOR = 10334;
 	private static final int MISSIONARY = 10339;
-	
+	private static final QuestItemChanceHolder FRAGMENT = new QuestItemChanceHolder(10340, 30L);
+
 	public Q00137_TempleChampionPart1() {
 		super(137, Q00137_TempleChampionPart1.class.getSimpleName(), "Temple Champion - 1");
 		addStartNpc(SYLVAIN);
 		addTalkId(SYLVAIN);
 		addKillId(MOBS);
-		registerQuestItems(FRAGMENT);
+		registerQuestItems(FRAGMENT.getId());
 	}
 	
 	@Override
@@ -90,12 +91,9 @@ public class Q00137_TempleChampionPart1 extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState st = getQuestState(player, false);
-		if ((st != null) && st.isStarted() && st.isCond(2) && (st.getQuestItemsCount(FRAGMENT) < 30)) {
-			st.giveItems(FRAGMENT, 1);
-			if (st.getQuestItemsCount(FRAGMENT) >= 30) {
-				st.setCond(3, true);
-			} else {
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
+		if ((st != null) && st.isStarted() && st.isCond(2)) {
+			if (giveItemRandomly(st.getPlayer(), npc, FRAGMENT, true)) {
+				st.setCond(3);
 			}
 		}
 		return super.onKill(npc, player, isSummon);
@@ -128,10 +126,10 @@ public class Q00137_TempleChampionPart1 extends Quest {
 			case 3:
 				if (st.getInt("talk") == 1) {
 					htmltext = "30070-10.html";
-				} else if (st.getQuestItemsCount(FRAGMENT) >= 30) {
+				} else if (hasItemsAtLimit(st.getPlayer(), FRAGMENT)) {
 					st.set("talk", "1");
 					htmltext = "30070-09.html";
-					st.takeItems(FRAGMENT, -1);
+					st.takeItems(FRAGMENT.getId(), -1);
 				}
 				break;
 			default:
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00138_TempleChampionPart2/Q00138_TempleChampionPart2.java b/src/main/java/com/l2jserver/datapack/quests/Q00138_TempleChampionPart2/Q00138_TempleChampionPart2.java
index 11b58109b0aa5382536b261b8c72beefb444d37e..80cbabcbbcb44fa6217a5abba10e489e66ae14a6 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00138_TempleChampionPart2/Q00138_TempleChampionPart2.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00138_TempleChampionPart2/Q00138_TempleChampionPart2.java
@@ -19,9 +19,9 @@
 package com.l2jserver.datapack.quests.Q00138_TempleChampionPart2;
 
 import com.l2jserver.datapack.quests.Q00137_TempleChampionPart1.Q00137_TempleChampionPart1;
-import com.l2jserver.gameserver.enums.audio.Sound;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
@@ -35,7 +35,8 @@ public class Q00138_TempleChampionPart2 extends Quest {
 	private static final int PUPINA = 30118;
 	private static final int ANGUS = 30474;
 	private static final int SLA = 30666;
-	private static final int MOBS[] = {
+	// Monsters
+	private static final int[] MOBS = {
 		20176, // Wyrm
 		20550, // Guardian Basilisk
 		20551, // Road Scavenger
@@ -43,16 +44,16 @@ public class Q00138_TempleChampionPart2 extends Quest {
 	};
 	// Items
 	private static final int TEMPLE_MANIFESTO = 10341;
-	private static final int RELICS_OF_THE_DARK_ELF_TRAINEE = 10342;
 	private static final int ANGUS_RECOMMENDATION = 10343;
 	private static final int PUPINAS_RECOMMENDATION = 10344;
+	private static final QuestItemChanceHolder RELICS_OF_THE_DARK_ELF_TRAINEE = new QuestItemChanceHolder(10342, 10L);
 	
 	public Q00138_TempleChampionPart2() {
 		super(138, Q00138_TempleChampionPart2.class.getSimpleName(), "Temple Champion - 2");
 		addStartNpc(SYLVAIN);
 		addTalkId(SYLVAIN, PUPINA, ANGUS, SLA);
 		addKillId(MOBS);
-		registerQuestItems(TEMPLE_MANIFESTO, RELICS_OF_THE_DARK_ELF_TRAINEE, ANGUS_RECOMMENDATION, PUPINAS_RECOMMENDATION);
+		registerQuestItems(TEMPLE_MANIFESTO, RELICS_OF_THE_DARK_ELF_TRAINEE.getId(), ANGUS_RECOMMENDATION, PUPINAS_RECOMMENDATION);
 	}
 	
 	@Override
@@ -109,13 +110,8 @@ public class Q00138_TempleChampionPart2 extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState st = getQuestState(player, false);
-		if ((st != null) && st.isStarted() && st.isCond(4) && (st.getQuestItemsCount(RELICS_OF_THE_DARK_ELF_TRAINEE) < 10)) {
-			st.giveItems(RELICS_OF_THE_DARK_ELF_TRAINEE, 1);
-			if (st.getQuestItemsCount(RELICS_OF_THE_DARK_ELF_TRAINEE) >= 10) {
-				st.playSound(Sound.ITEMSOUND_QUEST_MIDDLE);
-			} else {
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
+		if ((st != null) && st.isStarted() && st.isCond(4)) {
+			giveItemRandomly(st.getPlayer(), npc, RELICS_OF_THE_DARK_ELF_TRAINEE, true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
@@ -174,8 +170,8 @@ public class Q00138_TempleChampionPart2 extends Quest {
 						htmltext = "30474-01.html";
 						break;
 					case 4:
-						if (st.getQuestItemsCount(RELICS_OF_THE_DARK_ELF_TRAINEE) >= 10) {
-							st.takeItems(RELICS_OF_THE_DARK_ELF_TRAINEE, -1);
+						if (hasItemsAtLimit(st.getPlayer(), RELICS_OF_THE_DARK_ELF_TRAINEE)) {
+							st.takeItems(RELICS_OF_THE_DARK_ELF_TRAINEE.getId(), -1);
 							st.giveItems(ANGUS_RECOMMENDATION, 1);
 							st.setCond(5, true);
 							htmltext = "30474-04.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00139_ShadowFoxPart1/Q00139_ShadowFoxPart1.java b/src/main/java/com/l2jserver/datapack/quests/Q00139_ShadowFoxPart1/Q00139_ShadowFoxPart1.java
index 7aa482163551ad1f0b6bdf350fc5f080b1ce261d..db3d0378b969029192f656391b9edc9d1b022421 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00139_ShadowFoxPart1/Q00139_ShadowFoxPart1.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00139_ShadowFoxPart1/Q00139_ShadowFoxPart1.java
@@ -19,13 +19,14 @@
 package com.l2jserver.datapack.quests.Q00139_ShadowFoxPart1;
 
 import com.l2jserver.datapack.quests.Q00138_TempleChampionPart2.Q00138_TempleChampionPart2;
-import com.l2jserver.gameserver.enums.audio.Sound;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.model.quest.State;
 
+import static com.l2jserver.gameserver.model.quest.QuestDroplist.singleDropItem;
+
 /**
  * Shadow Fox - 1 (139)
  * @author Nono
@@ -34,7 +35,7 @@ public class Q00139_ShadowFoxPart1 extends Quest {
 	// NPC
 	private static final int MIA = 30896;
 	// Monsters
-	private static final int MOBS[] = {
+	private static final int[] MOBS = {
 		20784, // Tasaba Lizardman
 		20785, // Tasaba Lizardman Shaman
 		21639, // Tasaba Lizardman
@@ -46,8 +47,7 @@ public class Q00139_ShadowFoxPart1 extends Quest {
 	// Misc
 	private static final int MIN_LEVEL = 37;
 	private static final int MAX_REWARD_LEVEL = 42;
-	private static final int DROP_CHANCE = 68;
-	
+
 	public Q00139_ShadowFoxPart1() {
 		super(139, Q00139_ShadowFoxPart1.class.getSimpleName(), "Shadow Fox - 1");
 		addStartNpc(MIA);
@@ -114,15 +114,10 @@ public class Q00139_ShadowFoxPart1 extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance member = getRandomPartyMember(player, 2);
-		if (member == null) {
-			return super.onKill(npc, player, isSummon);
-		}
-		final QuestState st = getQuestState(member, false);
-		if (!st.isSet("talk") && (getRandom(100) < DROP_CHANCE)) {
+		QuestState st = getRandomPartyMemberState(player, 2, 1, npc);
+		if (st != null && !st.isSet("talk")) {
 			int itemId = (getRandom(11) == 0) ? CHEST : FRAGMENT;
-			st.giveItems(itemId, 1);
-			st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
+			giveItemRandomly(st.getPlayer(), npc, singleDropItem(itemId, 68.0), 0, true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
@@ -151,4 +146,4 @@ public class Q00139_ShadowFoxPart1 extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00140_ShadowFoxPart2/Q00140_ShadowFoxPart2.java b/src/main/java/com/l2jserver/datapack/quests/Q00140_ShadowFoxPart2/Q00140_ShadowFoxPart2.java
index 23d5ed5beaf3938c4850053ffc917163f2f8b1b5..e5b15ba7f629907fd7ac8f2a9b37520f94cf8ec5 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00140_ShadowFoxPart2/Q00140_ShadowFoxPart2.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00140_ShadowFoxPart2/Q00140_ShadowFoxPart2.java
@@ -18,14 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00140_ShadowFoxPart2;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00139_ShadowFoxPart1.Q00139_ShadowFoxPart1;
-import com.l2jserver.gameserver.enums.audio.Sound;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestDroplist;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.model.quest.State;
 
@@ -41,14 +38,13 @@ public class Q00140_ShadowFoxPart2 extends Quest {
 	private static final int DARK_CRYSTAL = 10347;
 	private static final int DARK_OXYDE = 10348;
 	private static final int CRYPTOGRAM_OF_THE_GODDESS_SWORD = 10349;
-	// Monsters
-	private static final Map<Integer, Integer> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20789, 45); // Crokian
-		MOBS.put(20790, 58); // Dailaon
-		MOBS.put(20791, 100);// Crokian Warrior
-		MOBS.put(20792, 92); // Farhite
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20789, DARK_CRYSTAL, 45.0) // Crokian
+			.addSingleDrop(20790, DARK_CRYSTAL, 58.0) // Dailaon
+			.addSingleDrop(20791, DARK_CRYSTAL, 100.0) // Crokian Warrior
+			.addSingleDrop(20792, DARK_CRYSTAL, 92.0) // Farhite
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 37;
 	private static final int MAX_REWARD_LEVEL = 42;
@@ -60,7 +56,7 @@ public class Q00140_ShadowFoxPart2 extends Quest {
 		super(140, Q00140_ShadowFoxPart2.class.getSimpleName(), "Shadow Fox - 2");
 		addStartNpc(KLUCK);
 		addTalkId(KLUCK, XENOVIA);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(DARK_CRYSTAL, DARK_OXYDE, CRYPTOGRAM_OF_THE_GODDESS_SWORD);
 	}
 	
@@ -125,14 +121,9 @@ public class Q00140_ShadowFoxPart2 extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance member = getRandomPartyMember(player, 3);
-		if (member == null) {
-			return super.onKill(npc, player, isSummon);
-		}
-		final QuestState st = getQuestState(member, false);
-		if (getRandom(100) < MOBS.get(npc.getId())) {
-			st.giveItems(DARK_CRYSTAL, 1);
-			st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
+		QuestState st = getRandomPartyMemberState(player, 3, 1, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
@@ -194,4 +185,4 @@ public class Q00140_ShadowFoxPart2 extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00141_ShadowFoxPart3/Q00141_ShadowFoxPart3.java b/src/main/java/com/l2jserver/datapack/quests/Q00141_ShadowFoxPart3/Q00141_ShadowFoxPart3.java
index 71afee9133901b35daeca85495b308bd9f251669..fef2dd2a4f2f224d91dfdd79cc90b8a343d765da 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00141_ShadowFoxPart3/Q00141_ShadowFoxPart3.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00141_ShadowFoxPart3/Q00141_ShadowFoxPart3.java
@@ -18,16 +18,14 @@
  */
 package com.l2jserver.datapack.quests.Q00141_ShadowFoxPart3;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00140_ShadowFoxPart2.Q00140_ShadowFoxPart2;
 import com.l2jserver.datapack.quests.Q00998_FallenAngelSelect.Q00998_FallenAngelSelect;
-import com.l2jserver.gameserver.enums.audio.Sound;
 import com.l2jserver.gameserver.instancemanager.QuestManager;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestDroplist;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.model.quest.State;
 
@@ -38,26 +36,24 @@ import com.l2jserver.gameserver.model.quest.State;
 public class Q00141_ShadowFoxPart3 extends Quest {
 	// NPCs
 	private static final int NATOOLS = 30894;
-	// Monsters
-	private static final Map<Integer, Integer> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20135, 53); // Alligator
-		MOBS.put(20791, 100); // Crokian Warrior
-		MOBS.put(20792, 92); // Farhite
-	}
 	// Items
-	private static final int PREDECESSORS_REPORT = 10350;
+	private static final QuestItemChanceHolder PREDECESSORS_REPORT = new QuestItemChanceHolder(10350, 30L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20135, PREDECESSORS_REPORT, 53.0) // Alligator
+			.addSingleDrop(20791, PREDECESSORS_REPORT, 100.0) // Crokian Warrior
+			.addSingleDrop(20792, PREDECESSORS_REPORT, 92.0) // Farhite
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 37;
 	private static final int MAX_REWARD_LEVEL = 42;
-	private static final int REPORT_COUNT = 30;
-	
+
 	public Q00141_ShadowFoxPart3() {
 		super(141, Q00141_ShadowFoxPart3.class.getSimpleName(), "Shadow Fox - 3");
 		addStartNpc(NATOOLS);
 		addTalkId(NATOOLS);
-		addKillId(MOBS.keySet());
-		registerQuestItems(PREDECESSORS_REPORT);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(PREDECESSORS_REPORT.getId());
 	}
 	
 	@Override
@@ -114,18 +110,9 @@ public class Q00141_ShadowFoxPart3 extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance member = getRandomPartyMember(player, 2);
-		if (member == null) {
-			return super.onKill(npc, player, isSummon);
-		}
-		final QuestState st = getQuestState(member, false);
-		if ((getRandom(100) < MOBS.get(npc.getId()))) {
-			st.giveItems(PREDECESSORS_REPORT, 1);
-			if (st.getQuestItemsCount(PREDECESSORS_REPORT) >= REPORT_COUNT) {
-				st.setCond(3, true);
-			} else {
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
+		QuestState st = getRandomPartyMemberState(player, 2, 1, npc);
+		if (st != null && giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			st.setCond(3);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
@@ -153,7 +140,7 @@ public class Q00141_ShadowFoxPart3 extends Quest {
 							htmltext = "30894-16.html";
 						} else {
 							htmltext = "30894-08.html";
-							st.takeItems(PREDECESSORS_REPORT, -1);
+							st.takeItems(PREDECESSORS_REPORT.getId(), -1);
 							st.set("talk", "1");
 						}
 						break;
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00228_TestOfMagus/Q00228_TestOfMagus.java b/src/main/java/com/l2jserver/datapack/quests/Q00228_TestOfMagus/Q00228_TestOfMagus.java
index c59da46057d3a50b179bb7368f2840cb45899f35..a3b3372ca742ff385bc95062b546c80ce1c31742 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00228_TestOfMagus/Q00228_TestOfMagus.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00228_TestOfMagus/Q00228_TestOfMagus.java
@@ -22,7 +22,10 @@ import com.l2jserver.gameserver.enums.audio.Sound;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.base.ClassId;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestDroplist;
+import com.l2jserver.gameserver.model.quest.QuestDroplist.QuestDropInfo;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
@@ -30,6 +33,9 @@ import com.l2jserver.gameserver.network.serverpackets.NpcSay;
 import com.l2jserver.gameserver.network.serverpackets.SocialAction;
 import com.l2jserver.gameserver.util.Util;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Test Of Magus (228)
  * @author ivantotov
@@ -43,6 +49,23 @@ public final class Q00228_TestOfMagus extends Quest {
 	private static final int WATER_UNDINE = 30413;
 	private static final int ELDER_CASIAN = 30612;
 	private static final int BARD_RUKAL = 30629;
+	// Monster
+	private static final int HARPY = 20145;
+	private static final int MARSH_STAKATO = 20157;
+	private static final int WYRM = 20176;
+	private static final int MARSH_STAKATO_WORKER = 20230;
+	private static final int TOAD_LORD = 20231;
+	private static final int MARSH_STAKATO_SOLDIER = 20232;
+	private static final int MARSH_STAKATO_DRONE = 20234;
+	private static final int WINDSUS = 20553;
+	private static final int ENCHANTED_MONSTEREYE = 20564;
+	private static final int ENCHANTED_STOLEN_GOLEM = 20565;
+	private static final int ENCHANTED_IRON_GOLEM = 20566;
+	// Quest Monster
+	private static final int SINGING_FLOWER_PHANTASM = 27095;
+	private static final int SINGING_FLOWER_NIGTMATE = 27096;
+	private static final int SINGING_FLOWER_DARKLING = 27097;
+	private static final int GHOST_FIRE = 27098;
 	// Items
 	private static final int RUKALS_LETTER = 2841;
 	private static final int PARINAS_LETTER = 2842;
@@ -51,14 +74,6 @@ public final class Q00228_TestOfMagus extends Quest {
 	private static final int GOLDEN_SEED_2ND = 2845;
 	private static final int GOLDEN_SEED_3RD = 2846;
 	private static final int SCORE_OF_ELEMENTS = 2847;
-	private static final int DAZZLING_DROP = 2848;
-	private static final int FLAME_CRYSTAL = 2849;
-	private static final int HARPYS_FEATHER = 2850;
-	private static final int WYRMS_WINGBONE = 2851;
-	private static final int WINDSUS_MANE = 2852;
-	private static final int ENCHANTED_MONSTER_EYE_SHELL = 2853;
-	private static final int ENCHANTED_GOLEM_POWDER = 2854;
-	private static final int ENCHANTED_IRON_GOLEM_SCRAP = 2855;
 	private static final int TONE_OF_WATER = 2856;
 	private static final int TONE_OF_FIRE = 2857;
 	private static final int TONE_OF_WIND = 2858;
@@ -67,26 +82,48 @@ public final class Q00228_TestOfMagus extends Quest {
 	private static final int SYLPH_CHARM = 2861;
 	private static final int UNDINE_CHARM = 2862;
 	private static final int SERPENT_CHARM = 2863;
+	private static final QuestItemChanceHolder DAZZLING_DROP = new QuestItemChanceHolder(2848, 20L);
+	private static final QuestItemChanceHolder FLAME_CRYSTAL = new QuestItemChanceHolder(2849, 50.0, 5L);
+	private static final QuestItemChanceHolder HARPYS_FEATHER = new QuestItemChanceHolder(2850, 20L);
+	private static final QuestItemChanceHolder WYRMS_WINGBONE = new QuestItemChanceHolder(2851, 50.0, 10L);
+	private static final QuestItemChanceHolder WINDSUS_MANE = new QuestItemChanceHolder(2852, 50.0, 10L);
+	private static final QuestItemChanceHolder ENCHANTED_MONSTER_EYE_SHELL = new QuestItemChanceHolder(2853, 10L);
+	private static final QuestItemChanceHolder ENCHANTED_GOLEM_POWDER = new QuestItemChanceHolder(2854, 10L);
+	private static final QuestItemChanceHolder ENCHANTED_IRON_GOLEM_SCRAP = new QuestItemChanceHolder(2855, 10L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(HARPY, HARPYS_FEATHER)
+			.bulkAddSingleDrop(DAZZLING_DROP)
+				.withNpcs(MARSH_STAKATO, MARSH_STAKATO_WORKER, TOAD_LORD, MARSH_STAKATO_SOLDIER, MARSH_STAKATO_DRONE).build()
+			.addSingleDrop(WYRM, WYRMS_WINGBONE)
+			.addSingleDrop(WINDSUS, WINDSUS_MANE)
+			.addSingleDrop(ENCHANTED_MONSTEREYE, ENCHANTED_MONSTER_EYE_SHELL)
+			.addSingleDrop(ENCHANTED_STOLEN_GOLEM, ENCHANTED_GOLEM_POWDER)
+			.addSingleDrop(ENCHANTED_IRON_GOLEM, ENCHANTED_IRON_GOLEM_SCRAP)
+			.addSingleDrop(GHOST_FIRE, FLAME_CRYSTAL)
+			.build();
+	private static final int[] SYLPH_REQUIRED_ITEMS = { SCORE_OF_ELEMENTS, SYLPH_CHARM };
+	private static final int[] UNDINE_REQUIRED_ITEMS = { SCORE_OF_ELEMENTS, UNDINE_CHARM };
+	private static final int[] SERPENT_REQUIRED_ITEMS = { SCORE_OF_ELEMENTS, SERPENT_CHARM };
+	private static final int[] SALAMANDER_REQUIRED_ITEMS = { SCORE_OF_ELEMENTS, SALAMANDER_CHARM };
+	private static final Map<Integer, int[]> MOBS_REQUIRED_ITEMS = new HashMap<>();
+	static {
+		MOBS_REQUIRED_ITEMS.put(HARPY, SYLPH_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(MARSH_STAKATO, UNDINE_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(MARSH_STAKATO_WORKER, UNDINE_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(TOAD_LORD, UNDINE_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(MARSH_STAKATO_SOLDIER, UNDINE_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(MARSH_STAKATO_DRONE, UNDINE_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(WYRM, SYLPH_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(WINDSUS, SYLPH_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(ENCHANTED_MONSTEREYE, SERPENT_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(ENCHANTED_STOLEN_GOLEM, SERPENT_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(ENCHANTED_IRON_GOLEM, SERPENT_REQUIRED_ITEMS);
+		MOBS_REQUIRED_ITEMS.put(GHOST_FIRE, SALAMANDER_REQUIRED_ITEMS);
+	}
 	// Reward
 	private static final int MARK_OF_MAGUS = 2840;
 	private static final int DIMENSIONAL_DIAMOND = 7562;
-	// Monster
-	private static final int HARPY = 20145;
-	private static final int MARSH_STAKATO = 20157;
-	private static final int WYRM = 20176;
-	private static final int MARSH_STAKATO_WORKER = 20230;
-	private static final int TOAD_LORD = 20231;
-	private static final int MARSH_STAKATO_SOLDIER = 20232;
-	private static final int MARSH_STAKATO_DRONE = 20234;
-	private static final int WINDSUS = 20553;
-	private static final int ENCHANTED_MONSTEREYE = 20564;
-	private static final int ENCHANTED_STOLEN_GOLEM = 20565;
-	private static final int ENCHANTED_IRON_GOLEM = 20566;
-	// Quest Monster
-	private static final int SINGING_FLOWER_PHANTASM = 27095;
-	private static final int SINGING_FLOWER_NIGTMATE = 27096;
-	private static final int SINGING_FLOWER_DARKLING = 27097;
-	private static final int GHOST_FIRE = 27098;
 	// Misc
 	private static final int MIN_LVL = 39;
 	
@@ -95,7 +132,7 @@ public final class Q00228_TestOfMagus extends Quest {
 		addStartNpc(BARD_RUKAL);
 		addTalkId(BARD_RUKAL, PARINA, EARTH_SNAKE, FLAME_SALAMANDER, WIND_SYLPH, WATER_UNDINE, ELDER_CASIAN);
 		addKillId(HARPY, MARSH_STAKATO, WYRM, MARSH_STAKATO_WORKER, TOAD_LORD, MARSH_STAKATO_SOLDIER, MARSH_STAKATO_DRONE, WINDSUS, ENCHANTED_MONSTEREYE, ENCHANTED_STOLEN_GOLEM, ENCHANTED_IRON_GOLEM, SINGING_FLOWER_PHANTASM, SINGING_FLOWER_NIGTMATE, SINGING_FLOWER_DARKLING, GHOST_FIRE);
-		registerQuestItems(RUKALS_LETTER, PARINAS_LETTER, LILAC_CHARM, GOLDEN_SEED_1ST, GOLDEN_SEED_2ND, GOLDEN_SEED_3RD, SCORE_OF_ELEMENTS, DAZZLING_DROP, FLAME_CRYSTAL, HARPYS_FEATHER, WYRMS_WINGBONE, WINDSUS_MANE, ENCHANTED_MONSTER_EYE_SHELL, ENCHANTED_GOLEM_POWDER, ENCHANTED_IRON_GOLEM_SCRAP, TONE_OF_WATER, TONE_OF_FIRE, TONE_OF_WIND, TONE_OF_EARTH, SALAMANDER_CHARM, SYLPH_CHARM, UNDINE_CHARM, SERPENT_CHARM);
+		registerQuestItems(RUKALS_LETTER, PARINAS_LETTER, LILAC_CHARM, GOLDEN_SEED_1ST, GOLDEN_SEED_2ND, GOLDEN_SEED_3RD, SCORE_OF_ELEMENTS, DAZZLING_DROP.getId(), FLAME_CRYSTAL.getId(), HARPYS_FEATHER.getId(), WYRMS_WINGBONE.getId(), WINDSUS_MANE.getId(), ENCHANTED_MONSTER_EYE_SHELL.getId(), ENCHANTED_GOLEM_POWDER.getId(), ENCHANTED_IRON_GOLEM_SCRAP.getId(), TONE_OF_WATER, TONE_OF_FIRE, TONE_OF_WIND, TONE_OF_EARTH, SALAMANDER_CHARM, SYLPH_CHARM, UNDINE_CHARM, SERPENT_CHARM);
 	}
 	
 	@Override
@@ -172,138 +209,42 @@ public final class Q00228_TestOfMagus extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getQuestState(killer, false);
-		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, killer, true)) {
-			switch (npc.getId()) {
-				case HARPY: {
-					if (hasQuestItems(killer, SCORE_OF_ELEMENTS, SYLPH_CHARM) && (getQuestItemsCount(killer, HARPYS_FEATHER) < 20)) {
-						giveItems(killer, HARPYS_FEATHER, 1);
-						if (getQuestItemsCount(killer, HARPYS_FEATHER) >= 20) {
-							playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-						} else {
-							playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
-						}
-					}
-					break;
-				}
-				case MARSH_STAKATO:
-				case MARSH_STAKATO_WORKER:
-				case TOAD_LORD:
-				case MARSH_STAKATO_SOLDIER:
-				case MARSH_STAKATO_DRONE: {
-					if (hasQuestItems(killer, SCORE_OF_ELEMENTS, UNDINE_CHARM) && (getQuestItemsCount(killer, DAZZLING_DROP) < 20)) {
-						giveItems(killer, DAZZLING_DROP, 1);
-						if (getQuestItemsCount(killer, DAZZLING_DROP) >= 20) {
+		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
+			QuestDropInfo dropInfo = DROPLIST.get(npc);
+			if (dropInfo != null && hasQuestItems(qs.getPlayer(), MOBS_REQUIRED_ITEMS.get(npc.getId()))) {
+				giveItemRandomly(qs.getPlayer(), npc, dropInfo, true);
+			} else {
+				switch (npc.getId()) {
+					case SINGING_FLOWER_PHANTASM -> {
+						if (hasQuestItems(killer, LILAC_CHARM) && !hasQuestItems(killer, GOLDEN_SEED_1ST)) {
+							giveItems(killer, GOLDEN_SEED_1ST, 1);
+							npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.I_AM_A_TREE_OF_NOTHING_A_TREE_THAT_KNOWS_WHERE_TO_RETURN));
 							playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-						} else {
-							playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
-						}
-					}
-					break;
-				}
-				case WYRM: {
-					if (hasQuestItems(killer, SCORE_OF_ELEMENTS, SYLPH_CHARM) && (getQuestItemsCount(killer, WYRMS_WINGBONE) < 10)) {
-						if (getRandom(100) < 50) {
-							giveItems(killer, WYRMS_WINGBONE, 1);
-							if (getQuestItemsCount(killer, WYRMS_WINGBONE) >= 10) {
-								playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-							} else {
-								playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
-							}
-						}
-					}
-					break;
-				}
-				case WINDSUS: {
-					if (hasQuestItems(killer, SCORE_OF_ELEMENTS, SYLPH_CHARM) && (getQuestItemsCount(killer, WINDSUS_MANE) < 10)) {
-						if (getRandom(100) < 50) {
-							giveItems(killer, WINDSUS_MANE, 1);
-							if (getQuestItemsCount(killer, WINDSUS_MANE) >= 10) {
-								playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-							} else {
-								playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
+							if (hasQuestItems(killer, GOLDEN_SEED_2ND, GOLDEN_SEED_3RD)) {
+								qs.setCond(4);
 							}
 						}
 					}
-					break;
-				}
-				case ENCHANTED_MONSTEREYE: {
-					if (hasQuestItems(killer, SCORE_OF_ELEMENTS, SERPENT_CHARM) && (getQuestItemsCount(killer, ENCHANTED_MONSTER_EYE_SHELL) < 10)) {
-						giveItems(killer, ENCHANTED_MONSTER_EYE_SHELL, 1);
-						if (getQuestItemsCount(killer, ENCHANTED_MONSTER_EYE_SHELL) >= 10) {
+					case SINGING_FLOWER_NIGTMATE -> {
+						if (hasQuestItems(killer, LILAC_CHARM) && !hasQuestItems(killer, GOLDEN_SEED_2ND)) {
+							giveItems(killer, GOLDEN_SEED_2ND, 1);
+							npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.I_AM_A_CREATURE_THAT_SHOWS_THE_TRUTH_OF_THE_PLACE_DEEP_IN_MY_HEART));
 							playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-						} else {
-							playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
+							if (hasQuestItems(killer, GOLDEN_SEED_1ST, GOLDEN_SEED_3RD)) {
+								qs.setCond(4);
+							}
 						}
 					}
-					break;
-				}
-				case ENCHANTED_STOLEN_GOLEM: {
-					if (hasQuestItems(killer, SCORE_OF_ELEMENTS, SERPENT_CHARM) && (getQuestItemsCount(killer, ENCHANTED_GOLEM_POWDER) < 10)) {
-						giveItems(killer, ENCHANTED_GOLEM_POWDER, 1);
-						if (getQuestItemsCount(killer, ENCHANTED_GOLEM_POWDER) >= 10) {
+					case SINGING_FLOWER_DARKLING -> {
+						if (hasQuestItems(killer, LILAC_CHARM) && !hasQuestItems(killer, GOLDEN_SEED_3RD)) {
+							giveItems(killer, GOLDEN_SEED_3RD, 1);
+							npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.I_AM_A_MIRROR_OF_DARKNESS_A_VIRTUAL_IMAGE_OF_DARKNESS));
 							playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-						} else {
-							playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
-						}
-					}
-					break;
-				}
-				case ENCHANTED_IRON_GOLEM: {
-					if (hasQuestItems(killer, SCORE_OF_ELEMENTS, SERPENT_CHARM) && (getQuestItemsCount(killer, ENCHANTED_IRON_GOLEM_SCRAP) < 10)) {
-						giveItems(killer, ENCHANTED_IRON_GOLEM_SCRAP, 1);
-						if (getQuestItemsCount(killer, ENCHANTED_IRON_GOLEM_SCRAP) >= 10) {
-							playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-						} else {
-							playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
-						}
-					}
-					break;
-				}
-				case SINGING_FLOWER_PHANTASM: {
-					if (hasQuestItems(killer, LILAC_CHARM) && !hasQuestItems(killer, GOLDEN_SEED_1ST)) {
-						giveItems(killer, GOLDEN_SEED_1ST, 1);
-						npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.I_AM_A_TREE_OF_NOTHING_A_TREE_THAT_KNOWS_WHERE_TO_RETURN));
-						playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-						if (hasQuestItems(killer, GOLDEN_SEED_2ND, GOLDEN_SEED_3RD)) {
-							qs.setCond(4);
-						}
-					}
-					break;
-				}
-				case SINGING_FLOWER_NIGTMATE: {
-					if (hasQuestItems(killer, LILAC_CHARM) && !hasQuestItems(killer, GOLDEN_SEED_2ND)) {
-						giveItems(killer, GOLDEN_SEED_2ND, 1);
-						npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.I_AM_A_CREATURE_THAT_SHOWS_THE_TRUTH_OF_THE_PLACE_DEEP_IN_MY_HEART));
-						playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-						if (hasQuestItems(killer, GOLDEN_SEED_1ST, GOLDEN_SEED_3RD)) {
-							qs.setCond(4);
-						}
-					}
-					break;
-				}
-				case SINGING_FLOWER_DARKLING: {
-					if (hasQuestItems(killer, LILAC_CHARM) && !hasQuestItems(killer, GOLDEN_SEED_3RD)) {
-						giveItems(killer, GOLDEN_SEED_3RD, 1);
-						npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.I_AM_A_MIRROR_OF_DARKNESS_A_VIRTUAL_IMAGE_OF_DARKNESS));
-						playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-						if (hasQuestItems(killer, GOLDEN_SEED_1ST, GOLDEN_SEED_2ND)) {
-							qs.setCond(4);
-						}
-					}
-					break;
-				}
-				case GHOST_FIRE: {
-					if (hasQuestItems(killer, SCORE_OF_ELEMENTS, SALAMANDER_CHARM) && (getQuestItemsCount(killer, FLAME_CRYSTAL) < 5)) {
-						if (getRandom(100) < 50) {
-							giveItems(killer, FLAME_CRYSTAL, 1);
-							if (getQuestItemsCount(killer, FLAME_CRYSTAL) >= 5) {
-								playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-							} else {
-								playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
+							if (hasQuestItems(killer, GOLDEN_SEED_1ST, GOLDEN_SEED_2ND)) {
+								qs.setCond(4);
 							}
 						}
 					}
-					break;
 				}
 			}
 		}
@@ -370,10 +311,10 @@ public final class Q00228_TestOfMagus extends Quest {
 						if (!hasAtLeastOneQuestItem(player, TONE_OF_EARTH, SERPENT_CHARM)) {
 							htmltext = "30409-01.html";
 						} else if (hasQuestItems(player, SERPENT_CHARM)) {
-							if ((getQuestItemsCount(player, ENCHANTED_MONSTER_EYE_SHELL) >= 10) && (getQuestItemsCount(player, ENCHANTED_GOLEM_POWDER) >= 10) && (getQuestItemsCount(player, ENCHANTED_IRON_GOLEM_SCRAP) >= 10)) {
-								takeItems(player, ENCHANTED_MONSTER_EYE_SHELL, -1);
-								takeItems(player, ENCHANTED_GOLEM_POWDER, -1);
-								takeItems(player, ENCHANTED_IRON_GOLEM_SCRAP, -1);
+							if (hasItemsAtLimit(player, ENCHANTED_MONSTER_EYE_SHELL, ENCHANTED_GOLEM_POWDER, ENCHANTED_IRON_GOLEM_SCRAP)) {
+								takeItems(player, ENCHANTED_MONSTER_EYE_SHELL.getId(), -1);
+								takeItems(player, ENCHANTED_GOLEM_POWDER.getId(), -1);
+								takeItems(player, ENCHANTED_IRON_GOLEM_SCRAP.getId(), -1);
 								giveItems(player, TONE_OF_EARTH, 1);
 								takeItems(player, SERPENT_CHARM, 1);
 								if (hasQuestItems(player, TONE_OF_FIRE, TONE_OF_WATER, TONE_OF_WIND)) {
@@ -395,10 +336,10 @@ public final class Q00228_TestOfMagus extends Quest {
 							htmltext = "30411-01.html";
 							giveItems(player, SALAMANDER_CHARM, 1);
 						} else if (hasQuestItems(player, SALAMANDER_CHARM)) {
-							if (getQuestItemsCount(player, FLAME_CRYSTAL) < 5) {
+							if (!hasItemsAtLimit(player, FLAME_CRYSTAL)) {
 								htmltext = "30411-02.html";
 							} else {
-								takeItems(player, FLAME_CRYSTAL, -1);
+								takeItems(player, FLAME_CRYSTAL.getId(), -1);
 								giveItems(player, TONE_OF_FIRE, 1);
 								takeItems(player, SALAMANDER_CHARM, 1);
 								if (hasQuestItems(player, TONE_OF_WATER, TONE_OF_WIND, TONE_OF_EARTH)) {
@@ -417,10 +358,10 @@ public final class Q00228_TestOfMagus extends Quest {
 						if (!hasAtLeastOneQuestItem(player, TONE_OF_WIND, SYLPH_CHARM)) {
 							htmltext = "30412-01.html";
 						} else if (hasQuestItems(player, SYLPH_CHARM)) {
-							if ((getQuestItemsCount(player, HARPYS_FEATHER) >= 20) && (getQuestItemsCount(player, WYRMS_WINGBONE) >= 10) && (getQuestItemsCount(player, WINDSUS_MANE) >= 10)) {
-								takeItems(player, HARPYS_FEATHER, -1);
-								takeItems(player, WYRMS_WINGBONE, -1);
-								takeItems(player, WINDSUS_MANE, -1);
+							if (hasItemsAtLimit(player, HARPYS_FEATHER, WYRMS_WINGBONE, WINDSUS_MANE)) {
+								takeItems(player, HARPYS_FEATHER.getId(), -1);
+								takeItems(player, WYRMS_WINGBONE.getId(), -1);
+								takeItems(player, WINDSUS_MANE.getId(), -1);
 								giveItems(player, TONE_OF_WIND, 1);
 								takeItems(player, SYLPH_CHARM, 1);
 								if (hasQuestItems(player, TONE_OF_WATER, TONE_OF_FIRE, TONE_OF_EARTH)) {
@@ -442,10 +383,10 @@ public final class Q00228_TestOfMagus extends Quest {
 							htmltext = "30413-01.html";
 							giveItems(player, UNDINE_CHARM, 1);
 						} else if (hasQuestItems(player, UNDINE_CHARM)) {
-							if (getQuestItemsCount(player, DAZZLING_DROP) < 20) {
+							if (!hasItemsAtLimit(player, DAZZLING_DROP)) {
 								htmltext = "30413-02.html";
 							} else {
-								takeItems(player, DAZZLING_DROP, -1);
+								takeItems(player, DAZZLING_DROP.getId(), -1);
 								giveItems(player, TONE_OF_WATER, 1);
 								takeItems(player, UNDINE_CHARM, 1);
 								if (hasQuestItems(player, TONE_OF_FIRE, TONE_OF_WIND, TONE_OF_EARTH)) {
@@ -481,4 +422,4 @@ public final class Q00228_TestOfMagus extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}