From c5969cf0b789f018bd4a74bc89e46a427d87fec3 Mon Sep 17 00:00:00 2001
From: Noe Caratini <caratinin@gmail.com>
Date: Sun, 17 Apr 2022 22:09:04 +0100
Subject: [PATCH] refactor: Improved quest drops handling

Refactored all quests to use QuestDroplist and the new giveItemRandomly() signature.
---
 .../ai/npc/Alexandria/Alexandria.java         |  44 +-
 .../datapack/gracia/ai/EnergySeeds.java       |   3 +-
 .../hellbound/ai/npc/Quarry/Quarry.java       |   8 +-
 .../instances/ChambersOfDelusion/Chamber.java |  30 +-
 .../Q00032_AnObviousLie.java                  |  75 +--
 .../Q00038_DragonFangs.java                   |  20 +-
 .../Q00039_RedEyedInvaders.java               |  37 +-
 .../Q00050_LanoscosSpecialBait.java           |  34 +-
 .../Q00051_OFullesSpecialBait.java            |  29 +-
 .../Q00052_WilliesSpecialBait.java            |  31 +-
 .../Q00053_LinnaeusSpecialBait.java           |  34 +-
 .../Q00065_CertifiedSoulBreaker.java          |  38 +-
 .../Q00103_SpiritOfCraftsman.java             |  31 +-
 .../Q00108_JumbleTumbleDiamondFuss.java       |  69 ++-
 .../Q00111_ElrokianHuntersProof.java          | 111 ++---
 .../Q00117_TheOceanOfDistantStars.java        |  34 +-
 .../Q00118_ToLeadAndBeLed.java                | 109 ++--
 .../Q00123_TheLeaderAndTheFollower.java       | 107 ++--
 .../Q00125_TheNameOfEvil1.java                |  83 ++--
 .../Q00154_SacrificeToTheSea.java             |   9 +-
 .../Q00175_TheWayOfTheWarrior.java            |  34 +-
 .../Q00212_TrialOfDuty.java                   |  51 +-
 .../Q00216_TrialOfTheGuildsman.java           | 189 +++----
 .../Q00222_TestOfTheDuelist.java              | 329 ++++---------
 .../Q00230_TestOfTheSummoner.java             | 276 +++++------
 .../Q00233_TestOfTheWarSpirit.java            |  93 ++--
 .../Q00234_FatesWhisper.java                  |  33 +-
 .../Q00235_MimirsElixir.java                  |  59 +--
 .../Q00252_ItSmellsDelicious.java             |  41 +-
 .../Q00261_CollectorsDream.java               |  10 +-
 .../Q00262_TradeWithTheIvoryTower.java        |  51 +-
 .../Q00264_KeenClaws/Q00264_KeenClaws.java    |  59 +--
 .../Q00266_PleasOfPixies.java                 |  55 +--
 .../Q00269_InventionAmbition.java             |  31 +-
 .../Q00275_DarkWingedSpies.java               |  26 +-
 .../Q00276_TotemOfTheHestui.java              |  37 +-
 .../Q00278_HomeSecurity.java                  |  36 +-
 .../Q00279_TargetOfOpportunity.java           |  82 ++--
 .../Q00280_TheFoodChain.java                  |  65 +--
 .../Q00283_TheFewTheProudTheBrave.java        |  15 +-
 .../Q00284_MuertosFeather.java                |  27 +-
 .../Q00286_FabulousFeathers.java              |  39 +-
 .../Q00290_ThreatRemoval.java                 |  49 +-
 .../Q00291_RevengeOfTheRedbonnet.java         |  12 +-
 .../Q00292_BrigandsSweep.java                 |  42 +-
 .../Q00294_CovertBusiness.java                |  45 +-
 .../Q00295_DreamingOfTheSkies.java            |  11 +-
 .../Q00296_TarantulasSpiderSilk.java          |  29 +-
 .../Q00298_LizardmensConspiracy.java          |  45 +-
 .../Q00299_GatherIngredientsForPie.java       |  55 +--
 .../Q00303_CollectArrowheads.java             |  23 +-
 .../Q00306_CrystalOfFireAndIce.java           |  51 +-
 .../Q00308_ReedFieldMaintenance.java          |  66 +--
 .../Q00309_ForAGoodCause.java                 |  65 +--
 .../Q00311_ExpulsionOfEvilSpirits.java        |  37 +-
 .../Q00313_CollectSpores.java                 |  16 +-
 .../Q00316_DestroyPlagueCarriers.java         |  38 +-
 .../Q00317_CatchTheWind.java                  |  15 +-
 .../Q00320_BonesTellTheFuture.java            |  13 +-
 .../Q00325_GrimCollector.java                 |  49 +-
 .../Q00329_CuriosityOfADwarf.java             |  36 +-
 .../Q00335_TheSongOfTheHunter.java            |  36 +-
 .../Q00336_CoinsOfMagic.java                  | 306 ++++--------
 .../Q00340_SubjugationOfLizardmen.java        |  58 +--
 .../Q00344_1000YearsTheEndOfLamentation.java  |  35 +-
 .../Q00347_GoGetTheCalculator.java            |   9 +-
 .../Q00351_BlackSwan/Q00351_BlackSwan.java    |  47 +-
 .../Q00352_HelpRoodRaiseANewPet.java          |  55 +--
 .../Q00354_ConquestOfAlligatorIsland.java     |  55 +--
 .../Q00355_FamilyHonor.java                   |  47 +-
 .../Q00356_DigUpTheSeaOfSpores.java           |  46 +-
 .../Q00357_WarehouseKeepersAmbition.java      |  23 +-
 .../Q00358_IllegitimateChildOfTheGoddess.java |  37 +-
 .../Q00359_ForASleeplessDeadman.java          |  41 +-
 .../Q00365_DevilsLegacy.java                  |  31 +-
 .../Q00366_SilverHairedShaman.java            |  33 +-
 .../Q00368_TrespassingIntoTheHolyGround.java  |  42 +-
 .../Q00369_CollectorOfJewels.java             |  57 +--
 .../Q00370_AnElderSowsSeeds.java              |  41 +-
 .../Q00371_ShrieksOfGhosts.java               |  63 +--
 .../Q00372_LegacyOfInsolence.java             |  24 +-
 .../Q00373_SupplierOfReagents.java            |  88 +---
 ...00376_ExplorationOfTheGiantsCavePart1.java |  33 +-
 ...00377_ExplorationOfTheGiantsCavePart2.java |  43 +-
 .../Q00379_FantasyWine.java                   |  35 +-
 ...Q00380_BringOutTheFlavorOfIngredients.java |  42 +-
 .../Q00381_LetsBecomeARoyalMember.java        |  15 +-
 .../Q00382_KailsMagicCoin.java                |  32 +-
 .../Q00384_WarehouseKeepersPastime.java       | 240 ++-------
 .../Q00385_YokeOfThePast.java                 | 104 ++--
 .../Q00386_StolenDignity.java                 | 464 ++++--------------
 .../Q00416_PathOfTheOrcShaman.java            |  96 ++--
 .../Q00417_PathOfTheScavenger.java            |  39 +-
 .../Q00420_LittleWing/Q00420_LittleWing.java  |  36 +-
 .../Q00501_ProofOfClanAlliance.java           | 103 +---
 .../Q00503_PursuitOfClanAmbition.java         |  99 ++--
 .../Q00603_DaimonTheWhiteEyedPart1.java       |  32 +-
 .../Q00619_RelicsOfTheOldEmpire.java          | 322 ++++++------
 .../Q00620_FourGoblets.java                   | 142 ++----
 .../Q00623_TheFinestFood.java                 |  35 +-
 .../Q00626_ADarkTwilight.java                 |  70 ++-
 .../Q00627_HeartInSearchOfPower.java          |  70 ++-
 .../Q00628_HuntGoldenRam.java                 |  69 ++-
 .../Q00629_CleanUpTheSwampOfScreams.java      |  36 +-
 .../Q00631_DeliciousTopChoiceMeat.java        |  99 ++--
 .../Q00632_NecromancersRequest.java           |  84 ++--
 .../Q00633_InTheForgottenVillage.java         | 101 ++--
 ...Q00634_InSearchOfFragmentsOfDimension.java |  27 +-
 .../Q00637_ThroughOnceMore.java               |  43 +-
 .../Q00638_SeekersOfTheHolyGrail.java         | 158 +++---
 .../Q00642_APowerfulPrimevalCreature.java     |  47 +-
 .../Q00643_RiseAndFallOfTheElrokiTribe.java   |  89 +---
 .../Q00644_GraveRobberAnnihilation.java       |  41 +-
 .../Q00648_AnIceMerchantsDream.java           |  82 ++--
 .../Q00654_JourneyToASettlement.java          |  31 +-
 ...00659_IdRatherBeCollectingFairyBreath.java |  27 +-
 .../Q00660_AidingTheFloranVillage.java        |  44 +-
 .../Q00661_MakingTheHarvestGroundsSafe.java   |  23 +-
 .../Q00662_AGameOfCards.java                  | 114 ++---
 .../Q00688_DefeatTheElrokianRaiders.java      |  41 +-
 .../Q00690_JudesRequest.java                  |  33 +-
 .../Q00691_MatrasSuspiciousRequest.java       |  53 +-
 .../Q00692_HowtoOpposeEvil.java               | 118 ++---
 .../Q10272_LightFragment.java                 |  44 +-
 .../Q10292_SevenSignsGirlOfDoubt.java         |  36 +-
 125 files changed, 2961 insertions(+), 4976 deletions(-)

diff --git a/src/main/java/com/l2jserver/datapack/ai/npc/Alexandria/Alexandria.java b/src/main/java/com/l2jserver/datapack/ai/npc/Alexandria/Alexandria.java
index 51a2c7ea08..a8d302f8b2 100644
--- a/src/main/java/com/l2jserver/datapack/ai/npc/Alexandria/Alexandria.java
+++ b/src/main/java/com/l2jserver/datapack/ai/npc/Alexandria/Alexandria.java
@@ -18,16 +18,16 @@
  */
 package com.l2jserver.datapack.ai.npc.Alexandria;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import com.l2jserver.datapack.ai.npc.AbstractNpcAI;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
-import com.l2jserver.gameserver.model.holders.QuestItemHolder;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Alexandria (Armor Merchant) AI.
@@ -47,23 +47,23 @@ public final class Alexandria extends AbstractNpcAI {
 		new ItemHolder(9817, 5),
 	};
 	// Agathions
-	private static final QuestItemHolder[] LITTLE_DEVILS = new QuestItemHolder[] {
+	private static final ItemChanceHolder[] LITTLE_DEVILS = new ItemChanceHolder[] {
 		new AdditionalQuestItemHolder(10321, 600, 1, 10408),
-		new QuestItemHolder(10322, 10),
-		new QuestItemHolder(10323, 10),
-		new QuestItemHolder(10324, 5),
-		new QuestItemHolder(10325, 5),
-		new QuestItemHolder(10326, 370),
+		new ItemChanceHolder(10322, 10),
+		new ItemChanceHolder(10323, 10),
+		new ItemChanceHolder(10324, 5),
+		new ItemChanceHolder(10325, 5),
+		new ItemChanceHolder(10326, 370),
 	};
-	private static final QuestItemHolder[] LITTLE_ANGELS = new QuestItemHolder[] {
+	private static final ItemChanceHolder[] LITTLE_ANGELS = new ItemChanceHolder[] {
 		new AdditionalQuestItemHolder(10315, 600, 1, 10408),
-		new QuestItemHolder(10316, 10),
-		new QuestItemHolder(10317, 10),
-		new QuestItemHolder(10318, 5),
-		new QuestItemHolder(10319, 5),
-		new QuestItemHolder(10320, 370),
+		new ItemChanceHolder(10316, 10),
+		new ItemChanceHolder(10317, 10),
+		new ItemChanceHolder(10318, 5),
+		new ItemChanceHolder(10319, 5),
+		new ItemChanceHolder(10320, 370),
 	};
-	private static final Map<String, List<QuestItemHolder>> AGATHIONS = new HashMap<>();
+	private static final Map<String, List<ItemChanceHolder>> AGATHIONS = new HashMap<>();
 	static {
 		AGATHIONS.put("littleAngel", Arrays.asList(LITTLE_ANGELS));
 		AGATHIONS.put("littleDevil", Arrays.asList(LITTLE_DEVILS));
@@ -85,14 +85,14 @@ public final class Alexandria extends AbstractNpcAI {
 			final int chance = getRandom(1000);
 			int chance2 = 0;
 			int chance3 = 0;
-			for (QuestItemHolder agathion : AGATHIONS.get(event)) {
+			for (ItemChanceHolder agathion : AGATHIONS.get(event)) {
 				chance3 += agathion.getChance();
 				if ((chance2 <= chance) && (chance < chance3)) {
 					if (takeAllItems(player, REQUIRED_ITEMS)) {
 						giveItems(player, agathion);
 						htmltext = "30098-03.html";
 						
-						if (agathion instanceof AdditionalQuestItemHolder) {
+						if (agathion instanceof ItemChanceHolder) {
 							giveItems(player, ((AdditionalQuestItemHolder) agathion).getAdditionalId(), 1);
 							htmltext = "30098-03a.html";
 						}
@@ -107,7 +107,7 @@ public final class Alexandria extends AbstractNpcAI {
 		return htmltext;
 	}
 	
-	public static class AdditionalQuestItemHolder extends QuestItemHolder {
+	public static class AdditionalQuestItemHolder extends ItemChanceHolder {
 		private final int _additionalId;
 		
 		public AdditionalQuestItemHolder(int id, int chance, long count, int additionalId) {
diff --git a/src/main/java/com/l2jserver/datapack/gracia/ai/EnergySeeds.java b/src/main/java/com/l2jserver/datapack/gracia/ai/EnergySeeds.java
index 7183c62b84..3c011fe658 100644
--- a/src/main/java/com/l2jserver/datapack/gracia/ai/EnergySeeds.java
+++ b/src/main/java/com/l2jserver/datapack/gracia/ai/EnergySeeds.java
@@ -509,12 +509,13 @@ public class EnergySeeds extends AbstractNpcAI {
 	}
 	
 	private void handleQuestDrop(L2PcInstance player, int itemId) {
-		double chance = HOWTOOPPOSEEVIL_CHANCE * rates().getRateQuestDrop();
+		double chance = HOWTOOPPOSEEVIL_CHANCE * rates().getQuestDropChanceMultiplier();
 		int numItems = (int) (chance / 100);
 		chance = chance % 100;
 		if (getRandom(100) < chance) {
 			numItems++;
 		}
+		numItems *= rates().getQuestDropAmountMultiplier();
 		if (numItems > 0) {
 			giveItems(player, itemId, numItems);
 			playSound(player, Sound.ITEMSOUND_QUEST_ITEMGET);
diff --git a/src/main/java/com/l2jserver/datapack/hellbound/ai/npc/Quarry/Quarry.java b/src/main/java/com/l2jserver/datapack/hellbound/ai/npc/Quarry/Quarry.java
index cdb9f481e8..617c7719a2 100644
--- a/src/main/java/com/l2jserver/datapack/hellbound/ai/npc/Quarry/Quarry.java
+++ b/src/main/java/com/l2jserver/datapack/hellbound/ai/npc/Quarry/Quarry.java
@@ -18,8 +18,6 @@
  */
 package com.l2jserver.datapack.hellbound.ai.npc.Quarry;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
 import com.l2jserver.datapack.ai.npc.AbstractNpcAI;
 import com.l2jserver.datapack.hellbound.HellboundEngine;
 import com.l2jserver.gameserver.ai.CtrlIntention;
@@ -34,6 +32,8 @@ import com.l2jserver.gameserver.model.zone.L2ZoneType;
 import com.l2jserver.gameserver.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
 
+import static com.l2jserver.gameserver.config.Configuration.rates;
+
 /**
  * Quarry AI.
  * @author DS, GKR
@@ -101,8 +101,8 @@ public final class Quarry extends AbstractNpcAI {
 				if ((npc != null) && !npc.isDead()) {
 					if (npc.getTarget().isPlayer()) {
 						for (ItemChanceHolder item : DROP_LIST) {
-							if (getRandom(10000) < item.getChance()) {
-								npc.dropItem((L2PcInstance) npc.getTarget(), item.getId(), (int) (item.getCount() * rates().getRateQuestDrop()));
+							if (getRandom(10000) < item.getChance() * rates().getQuestDropChanceMultiplier()) {
+								npc.dropItem((L2PcInstance) npc.getTarget(), item.getId(), (int) (item.getCount() * rates().getQuestDropAmountMultiplier()));
 								break;
 							}
 						}
diff --git a/src/main/java/com/l2jserver/datapack/instances/ChambersOfDelusion/Chamber.java b/src/main/java/com/l2jserver/datapack/instances/ChambersOfDelusion/Chamber.java
index ec6ed473e4..6fd7807ff7 100644
--- a/src/main/java/com/l2jserver/datapack/instances/ChambersOfDelusion/Chamber.java
+++ b/src/main/java/com/l2jserver/datapack/instances/ChambersOfDelusion/Chamber.java
@@ -18,12 +18,6 @@
  */
 package com.l2jserver.datapack.instances.ChambersOfDelusion;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-import java.util.Calendar;
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-
 import com.l2jserver.datapack.instances.AbstractInstance;
 import com.l2jserver.gameserver.ThreadPoolManager;
 import com.l2jserver.gameserver.ai.CtrlIntention;
@@ -47,6 +41,12 @@ import com.l2jserver.gameserver.network.serverpackets.NpcSay;
 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
 import com.l2jserver.gameserver.util.Util;
 
+import java.util.Calendar;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+
+import static com.l2jserver.gameserver.config.Configuration.rates;
+
 /**
  * Chambers of Delusion superclass.
  * @author GKR
@@ -439,19 +439,19 @@ public abstract class Chamber extends AbstractInstance {
 	public String onAttack(final L2Npc npc, final L2PcInstance attacker, final int damage, final boolean isPet, final Skill skill) {
 		if (!npc.isBusy() && (npc.getCurrentHp() < (npc.getMaxHp() / 10))) {
 			npc.setBusy(true);
-			if (getRandom(100) < 25) // 25% chance to reward
+			if (getRandom(100) < 25 * rates().getQuestDropChanceMultiplier()) // 25% chance to reward
 			{
-				if (getRandom(100) < 33) {
-					npc.dropItem(attacker, ENRIA, (int) (3 * rates().getRateQuestDrop()));
+				if (getRandom(100) < 33 * rates().getQuestDropChanceMultiplier()) {
+					npc.dropItem(attacker, ENRIA, (int) (3 * rates().getQuestDropAmountMultiplier()));
 				}
-				if (getRandom(100) < 50) {
-					npc.dropItem(attacker, THONS, (int) (4 * rates().getRateQuestDrop()));
+				if (getRandom(100) < 50 * rates().getQuestDropChanceMultiplier()) {
+					npc.dropItem(attacker, THONS, (int) (4 * rates().getQuestDropAmountMultiplier()));
 				}
-				if (getRandom(100) < 50) {
-					npc.dropItem(attacker, ASOFE, (int) (4 * rates().getRateQuestDrop()));
+				if (getRandom(100) < 50 * rates().getQuestDropChanceMultiplier()) {
+					npc.dropItem(attacker, ASOFE, (int) (4 * rates().getQuestDropAmountMultiplier()));
 				}
-				if (getRandom(100) < 16) {
-					npc.dropItem(attacker, LEONARD, (int) (2 * rates().getRateQuestDrop()));
+				if (getRandom(100) < 16 * rates().getQuestDropChanceMultiplier()) {
+					npc.dropItem(attacker, LEONARD, (int) (2 * rates().getQuestDropAmountMultiplier()));
 				}
 				
 				npc.broadcastEvent("SCE_LUCKY", 2000, null);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00032_AnObviousLie/Q00032_AnObviousLie.java b/src/main/java/com/l2jserver/datapack/quests/Q00032_AnObviousLie/Q00032_AnObviousLie.java
index a8ce956860..906075f0d8 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00032_AnObviousLie/Q00032_AnObviousLie.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00032_AnObviousLie/Q00032_AnObviousLie.java
@@ -18,15 +18,15 @@
  */
 package com.l2jserver.datapack.quests.Q00032_AnObviousLie;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
+import java.util.Map;
+
 /**
  * An Obvious Lie (32).
  * @author janiko
@@ -40,19 +40,17 @@ public final class Q00032_AnObviousLie extends Quest {
 	private static final int ALLIGATOR = 20135;
 	// Items
 	private static final int MAP_OF_GENTLER = 7165;
-	private static final ItemHolder MEDICINAL_HERB = new ItemHolder(7166, 20);
 	private static final ItemHolder SPIRIT_ORE = new ItemHolder(3031, 500);
 	private static final ItemHolder THREAD = new ItemHolder(1868, 1000);
 	private static final ItemHolder SUEDE = new ItemHolder(1866, 500);
+	private static final QuestItemChanceHolder MEDICINAL_HERB = new QuestItemChanceHolder(7166, 20L);
 	// Misc
 	private static final int MIN_LVL = 45;
 	// Reward
-	private static final Map<String, Integer> EARS = new HashMap<>();
-	{
-		EARS.put("cat", 6843); // Cat Ears
-		EARS.put("raccoon", 7680); // Raccoon ears
-		EARS.put("rabbit", 7683); // Rabbit ears
-	}
+	private static final Map<String, Integer> EARS = Map.of(
+			"cat", 6843, // Cat Ears
+			"raccoon", 7680, // Raccoon ears
+			"rabbit", 7683); // Rabbit ears
 	
 	public Q00032_AnObviousLie() {
 		super(32, Q00032_AnObviousLie.class.getSimpleName(), "An Obvious Lie");
@@ -69,7 +67,7 @@ public final class Q00032_AnObviousLie extends Quest {
 		if (qs == null) {
 			return htmltext;
 		}
-		
+
 		switch (event) {
 			case "30120-02.html": {
 				if (qs.isCreated()) {
@@ -147,7 +145,7 @@ public final class Q00032_AnObviousLie extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 3, 3, npc);
-		if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, MEDICINAL_HERB.getId(), 1, MEDICINAL_HERB.getCount(), 1.0, true)) {
+		if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, MEDICINAL_HERB, true)) {
 			qs.setCond(4);
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -172,63 +170,32 @@ public final class Q00032_AnObviousLie extends Quest {
 			}
 			case GENTLER: {
 				switch (qs.getCond()) {
-					case 1: {
-						htmltext = "30094-01.html";
-						break;
-					}
-					case 2: {
-						htmltext = "30094-03.html";
-						break;
-					}
-					case 4: {
-						htmltext = (hasItem(player, MEDICINAL_HERB) ? "30094-04.html" : "30094-05.html");
-						break;
-					}
-					case 5: {
-						htmltext = (hasItem(player, SPIRIT_ORE) ? "30094-07.html" : "30094-08.html");
-						break;
-					}
-					case 6: {
-						htmltext = "30094-10.html";
-						break;
-					}
-					case 7: {
-						htmltext = "30094-11.html";
-						break;
-					}
-					case 8: {
+					case 1 -> htmltext = "30094-01.html";
+					case 2 -> htmltext = "30094-03.html";
+					case 4 -> htmltext = (hasItem(player, MEDICINAL_HERB) ? "30094-04.html" : "30094-05.html");
+					case 5 -> htmltext = (hasItem(player, SPIRIT_ORE) ? "30094-07.html" : "30094-08.html");
+					case 6 -> htmltext = "30094-10.html";
+					case 7 -> htmltext = "30094-11.html";
+					case 8 -> {
 						if (hasAllItems(player, true, THREAD, SUEDE)) {
 							htmltext = "30094-13.html";
 						} else {
 							htmltext = "30094-14.html";
 						}
-						break;
 					}
 				}
 				break;
 			}
 			case MIKI_THE_CAT: {
 				switch (qs.getCond()) {
-					case 2: {
+					case 2 -> {
 						if (hasQuestItems(player, MAP_OF_GENTLER)) {
 							htmltext = "31706-01.html";
 						}
-						break;
-					}
-					case 3:
-					case 4:
-					case 5: {
-						htmltext = "31706-03.html";
-						break;
-					}
-					case 6: {
-						htmltext = "31706-04.html";
-						break;
-					}
-					case 7: {
-						htmltext = "31706-06.html";
-						break;
 					}
+					case 3, 4, 5 -> htmltext = "31706-03.html";
+					case 6 -> htmltext = "31706-04.html";
+					case 7 -> htmltext = "31706-06.html";
 				}
 				break;
 			}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00038_DragonFangs/Q00038_DragonFangs.java b/src/main/java/com/l2jserver/datapack/quests/Q00038_DragonFangs/Q00038_DragonFangs.java
index 01d7353f3b..a43b541003 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00038_DragonFangs/Q00038_DragonFangs.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00038_DragonFangs/Q00038_DragonFangs.java
@@ -20,7 +20,7 @@ package com.l2jserver.datapack.quests.Q00038_DragonFangs;
 
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
@@ -39,11 +39,11 @@ public final class Q00038_DragonFangs extends Quest {
 	private static final int LIZARDMAN_LEADER = 20356;
 	private static final int LIZARDMAN_SUB_LEADER = 20357;
 	// Items
-	private static final ItemHolder FEATHER = new ItemHolder(7173, 100);
 	private static final int TOTEM_TOOTH_1ST = 7174;
-	private static final ItemHolder TOTEM_TOOTH_2ND = new ItemHolder(7175, 50);
 	private static final int LETTER_1ST = 7176;
 	private static final int LETTER_2ND = 7177;
+	private static final QuestItemChanceHolder FEATHER = new QuestItemChanceHolder(7173, 100L);
+	private static final QuestItemChanceHolder TOTEM_TOOTH_2ND = new QuestItemChanceHolder(7175, 50.0, 50L);
 	// Rewards
 	private static final int BONE_HELMET = 45;
 	private static final int LEATHER_GAUNTLET = 605;
@@ -230,23 +230,19 @@ public final class Q00038_DragonFangs extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		switch (npc.getId()) {
-			case LIZARDMAN_SUB_LEADER:
-			case LIZARDMAN_SENTINEL: {
+			case LIZARDMAN_SUB_LEADER, LIZARDMAN_SENTINEL -> {
 				final QuestState qs = getRandomPartyMemberState(killer, 1, 3, npc);
-				if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, FEATHER.getId(), 1, FEATHER.getCount(), 1.0, true)) {
+				if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, FEATHER, true)) {
 					qs.setCond(2);
 				}
-				break;
 			}
-			case LIZARDMAN_LEADER:
-			case LIZARDMAN_SHAMAN: {
+			case LIZARDMAN_LEADER, LIZARDMAN_SHAMAN -> {
 				final QuestState qs = getRandomPartyMemberState(killer, 6, 3, npc);
-				if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, TOTEM_TOOTH_2ND.getId(), 1, TOTEM_TOOTH_2ND.getCount(), 0.5, true)) {
+				if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, TOTEM_TOOTH_2ND, true)) {
 					qs.setCond(7);
 				}
-				break;
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00039_RedEyedInvaders/Q00039_RedEyedInvaders.java b/src/main/java/com/l2jserver/datapack/quests/Q00039_RedEyedInvaders/Q00039_RedEyedInvaders.java
index 5454b622b7..5a60855412 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00039_RedEyedInvaders/Q00039_RedEyedInvaders.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00039_RedEyedInvaders/Q00039_RedEyedInvaders.java
@@ -21,9 +21,12 @@ package com.l2jserver.datapack.quests.Q00039_RedEyedInvaders;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
+import static com.l2jserver.gameserver.model.quest.QuestDroplist.singleDropItem;
+
 /**
  * Red-eyed Invaders (39)
  * @author janiko
@@ -38,10 +41,10 @@ public final class Q00039_RedEyedInvaders extends Quest {
 	private static final int MALE_LIZARDMAN_GUARD = 20921;
 	private static final int GIANT_ARANE = 20925;
 	// Items
-	private static final ItemHolder LIZ_NECKLACE_A = new ItemHolder(7178, 100);
-	private static final ItemHolder LIZ_NECKLACE_B = new ItemHolder(7179, 100);
-	private static final ItemHolder LIZ_PERFUME = new ItemHolder(7180, 30);
-	private static final ItemHolder LIZ_GEM = new ItemHolder(7181, 30);
+	private static final QuestItemChanceHolder LIZ_NECKLACE_A = new QuestItemChanceHolder(7178, 50.0, 100L);
+	private static final QuestItemChanceHolder LIZ_NECKLACE_B = new QuestItemChanceHolder(7179, 50.0, 50L);
+	private static final QuestItemChanceHolder LIZ_PERFUME = new QuestItemChanceHolder(7180, 25.0, 30L);
+	private static final QuestItemChanceHolder LIZ_GEM = new QuestItemChanceHolder(7181, 30.0, 30L);
 	// Rewards
 	private static final ItemHolder GREEN_HIGH_LURE = new ItemHolder(6521, 60);
 	private static final ItemHolder BABYDUCK_ROD = new ItemHolder(6529, 1);
@@ -157,61 +160,57 @@ public final class Q00039_RedEyedInvaders extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		switch (npc.getId()) {
-			case MALE_LIZARDMAN: {
+			case MALE_LIZARDMAN -> {
 				final QuestState qs = getRandomPartyMemberState(killer, 2, 3, npc);
-				if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_NECKLACE_A.getId(), 1, LIZ_NECKLACE_A.getCount(), 0.5, true)) {
+				if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_NECKLACE_A, true)) {
 					if (hasItem(qs.getPlayer(), LIZ_NECKLACE_B)) {
 						qs.setCond(3);
 					}
 				}
-				break;
 			}
-			case MALE_LIZARDMAN_SCOUT: {
+			case MALE_LIZARDMAN_SCOUT -> {
 				if (getRandomBoolean()) {
 					final QuestState qs = getRandomPartyMemberState(killer, 2, 3, npc);
-					if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_NECKLACE_A.getId(), 1, LIZ_NECKLACE_A.getCount(), 0.5, true)) {
+					if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_NECKLACE_A, true)) {
 						if (hasItem(qs.getPlayer(), LIZ_NECKLACE_B)) {
 							qs.setCond(3);
 						}
 					}
 				} else {
 					final QuestState qs = getRandomPartyMemberState(killer, 4, 3, npc);
-					if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_PERFUME.getId(), 1, LIZ_PERFUME.getCount(), 0.25, true)) {
+					if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_PERFUME, true)) {
 						if (hasItem(qs.getPlayer(), LIZ_GEM)) {
 							qs.setCond(5);
 						}
 					}
 				}
-				break;
 			}
-			case MALE_LIZARDMAN_GUARD: {
+			case MALE_LIZARDMAN_GUARD -> {
 				if (getRandomBoolean()) {
 					final QuestState qs = getRandomPartyMemberState(killer, 2, 3, npc);
-					if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_NECKLACE_B.getId(), 1, LIZ_NECKLACE_B.getCount(), 0.5, true)) {
+					if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_NECKLACE_B, true)) {
 						if (hasItem(qs.getPlayer(), LIZ_NECKLACE_A)) {
 							qs.setCond(3);
 						}
 					}
 				} else {
 					final QuestState qs = getRandomPartyMemberState(killer, 4, 3, npc);
-					if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_PERFUME.getId(), 1, LIZ_PERFUME.getCount(), 0.3, true)) {
+					if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, singleDropItem(LIZ_PERFUME, 30.0), LIZ_PERFUME.getLimit(), true)) {
 						if (hasItem(qs.getPlayer(), LIZ_GEM)) {
 							qs.setCond(5);
 						}
 					}
 				}
-				break;
 			}
-			case GIANT_ARANE: {
+			case GIANT_ARANE -> {
 				final QuestState qs = getRandomPartyMemberState(killer, 4, 3, npc);
-				if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_GEM.getId(), 1, LIZ_GEM.getCount(), 0.3, true)) {
+				if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, LIZ_GEM, true)) {
 					if (hasItem(qs.getPlayer(), LIZ_PERFUME)) {
 						qs.setCond(5);
 					}
 				}
-				break;
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00050_LanoscosSpecialBait/Q00050_LanoscosSpecialBait.java b/src/main/java/com/l2jserver/datapack/quests/Q00050_LanoscosSpecialBait/Q00050_LanoscosSpecialBait.java
index 0a5ed518e4..98133f3308 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00050_LanoscosSpecialBait/Q00050_LanoscosSpecialBait.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00050_LanoscosSpecialBait/Q00050_LanoscosSpecialBait.java
@@ -18,11 +18,9 @@
  */
 package com.l2jserver.datapack.quests.Q00050_LanoscosSpecialBait;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -37,15 +35,15 @@ public class Q00050_LanoscosSpecialBait extends Quest {
 	private static final int LANOSCO = 31570;
 	private static final int SINGING_WIND = 21026;
 	// Items
-	private static final int ESSENCE_OF_WIND = 7621;
 	private static final int WIND_FISHING_LURE = 7610;
-	
+	private static final QuestItemChanceHolder ESSENCE_OF_WIND = new QuestItemChanceHolder(7621, 33.0, 100L);
+
 	public Q00050_LanoscosSpecialBait() {
 		super(50, Q00050_LanoscosSpecialBait.class.getSimpleName(), "Lanosco's Special Bait");
 		addStartNpc(LANOSCO);
 		addTalkId(LANOSCO);
 		addKillId(SINGING_WIND);
-		registerQuestItems(ESSENCE_OF_WIND);
+		registerQuestItems(ESSENCE_OF_WIND.getId());
 	}
 	
 	@Override
@@ -62,7 +60,7 @@ public class Q00050_LanoscosSpecialBait extends Quest {
 				st.startQuest();
 				break;
 			case "31570-07.html":
-				if ((st.isCond(2)) && (st.getQuestItemsCount(ESSENCE_OF_WIND) >= 100)) {
+				if ((st.isCond(2)) && hasItemsAtLimit(st.getPlayer(), ESSENCE_OF_WIND)) {
 					htmltext = "31570-06.htm";
 					st.giveItems(WIND_FISHING_LURE, 4);
 					st.exitQuest(false, true);
@@ -74,26 +72,10 @@ public class Q00050_LanoscosSpecialBait extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember == null) {
-			return null;
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null && giveItemRandomly(st.getPlayer(), npc, ESSENCE_OF_WIND, true)) {
+			st.setCond(2);
 		}
-		
-		final QuestState st = getQuestState(partyMember, false);
-		
-		if (st.getQuestItemsCount(ESSENCE_OF_WIND) < 100) {
-			double chance = 33 * rates().getRateQuestDrop();
-			if (getRandom(100) < chance) {
-				st.rewardItems(ESSENCE_OF_WIND, 1);
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
-		}
-		
-		if (st.getQuestItemsCount(ESSENCE_OF_WIND) >= 100) {
-			st.setCond(2, true);
-			
-		}
-		
 		return super.onKill(npc, player, isSummon);
 	}
 	
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00051_OFullesSpecialBait/Q00051_OFullesSpecialBait.java b/src/main/java/com/l2jserver/datapack/quests/Q00051_OFullesSpecialBait/Q00051_OFullesSpecialBait.java
index b98d8f5cad..3e7447fa53 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00051_OFullesSpecialBait/Q00051_OFullesSpecialBait.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00051_OFullesSpecialBait/Q00051_OFullesSpecialBait.java
@@ -18,11 +18,9 @@
  */
 package com.l2jserver.datapack.quests.Q00051_OFullesSpecialBait;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -37,7 +35,7 @@ public class Q00051_OFullesSpecialBait extends Quest {
 	private static final int OFULLE = 31572;
 	private static final int FETTERED_SOUL = 20552;
 	// Items
-	private static final int LOST_BAIT = 7622;
+	private static final QuestItemChanceHolder LOST_BAIT = new QuestItemChanceHolder(7622, 33.0, 100L);
 	private static final int ICY_AIR_LURE = 7611;
 	
 	public Q00051_OFullesSpecialBait() {
@@ -45,7 +43,7 @@ public class Q00051_OFullesSpecialBait extends Quest {
 		addStartNpc(OFULLE);
 		addTalkId(OFULLE);
 		addKillId(FETTERED_SOUL);
-		registerQuestItems(LOST_BAIT);
+		registerQuestItems(LOST_BAIT.getId());
 	}
 	
 	@Override
@@ -61,7 +59,7 @@ public class Q00051_OFullesSpecialBait extends Quest {
 				st.startQuest();
 				break;
 			case "31572-07.html":
-				if ((st.isCond(2)) && (st.getQuestItemsCount(LOST_BAIT) >= 100)) {
+				if ((st.isCond(2)) && hasItemsAtLimit(st.getPlayer(), LOST_BAIT)) {
 					htmltext = "31572-06.htm";
 					st.giveItems(ICY_AIR_LURE, 4);
 					st.exitQuest(false, true);
@@ -73,22 +71,9 @@ public class Q00051_OFullesSpecialBait extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember == null) {
-			return null;
-		}
-		
-		final QuestState st = getQuestState(partyMember, false);
-		if (st.getQuestItemsCount(LOST_BAIT) < 100) {
-			double chance = 33 * rates().getRateQuestDrop();
-			if (getRandom(100) < chance) {
-				st.rewardItems(LOST_BAIT, 1);
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
-		}
-		
-		if (st.getQuestItemsCount(LOST_BAIT) >= 100) {
-			st.setCond(2, true);
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null && giveItemRandomly(st.getPlayer(), npc, LOST_BAIT, true)) {
+			st.setCond(2);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00052_WilliesSpecialBait/Q00052_WilliesSpecialBait.java b/src/main/java/com/l2jserver/datapack/quests/Q00052_WilliesSpecialBait/Q00052_WilliesSpecialBait.java
index 9d3000547b..fb368d032d 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00052_WilliesSpecialBait/Q00052_WilliesSpecialBait.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00052_WilliesSpecialBait/Q00052_WilliesSpecialBait.java
@@ -18,11 +18,9 @@
  */
 package com.l2jserver.datapack.quests.Q00052_WilliesSpecialBait;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -37,15 +35,15 @@ public class Q00052_WilliesSpecialBait extends Quest {
 	private static final int WILLIE = 31574;
 	private static final int TARLK_BASILISK = 20573;
 	// Items
-	private static final int TARLK_EYE = 7623;
 	private static final int EARTH_FISHING_LURE = 7612;
-	
+	private static final QuestItemChanceHolder TARLK_EYE = new QuestItemChanceHolder(7623, 33.0, 100L);
+
 	public Q00052_WilliesSpecialBait() {
 		super(52, Q00052_WilliesSpecialBait.class.getSimpleName(), "Willie's Special Bait");
 		addStartNpc(WILLIE);
 		addTalkId(WILLIE);
 		addKillId(TARLK_BASILISK);
-		registerQuestItems(TARLK_EYE);
+		registerQuestItems(TARLK_EYE.getId());
 	}
 	
 	@Override
@@ -61,7 +59,7 @@ public class Q00052_WilliesSpecialBait extends Quest {
 				st.startQuest();
 				break;
 			case "31574-07.html":
-				if (st.isCond(2) && (st.getQuestItemsCount(TARLK_EYE) >= 100)) {
+				if (st.isCond(2) && hasItemsAtLimit(st.getPlayer(), TARLK_EYE)) {
 					htmltext = "31574-06.htm";
 					st.giveItems(EARTH_FISHING_LURE, 4);
 					st.exitQuest(false, true);
@@ -73,22 +71,9 @@ public class Q00052_WilliesSpecialBait extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember == null) {
-			return null;
-		}
-		
-		final QuestState st = getQuestState(partyMember, false);
-		if (st.getQuestItemsCount(TARLK_EYE) < 100) {
-			double chance = 33 * rates().getRateQuestDrop();
-			if (getRandom(100) < chance) {
-				st.rewardItems(TARLK_EYE, 1);
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
-		}
-		
-		if (st.getQuestItemsCount(TARLK_EYE) >= 100) {
-			st.setCond(2, true);
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null && giveItemRandomly(st.getPlayer(), npc, TARLK_EYE, true)) {
+			st.setCond(2);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00053_LinnaeusSpecialBait/Q00053_LinnaeusSpecialBait.java b/src/main/java/com/l2jserver/datapack/quests/Q00053_LinnaeusSpecialBait/Q00053_LinnaeusSpecialBait.java
index dbe4c8a143..4d0d903e3e 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00053_LinnaeusSpecialBait/Q00053_LinnaeusSpecialBait.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00053_LinnaeusSpecialBait/Q00053_LinnaeusSpecialBait.java
@@ -18,11 +18,9 @@
  */
 package com.l2jserver.datapack.quests.Q00053_LinnaeusSpecialBait;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -37,15 +35,15 @@ public class Q00053_LinnaeusSpecialBait extends Quest {
 	private static final int LINNAEUS = 31577;
 	private static final int CRIMSON_DRAKE = 20670;
 	// Items
-	private static final int CRIMSON_DRAKE_HEART = 7624;
 	private static final int FLAMING_FISHING_LURE = 7613;
-	
+	private static final QuestItemChanceHolder CRIMSON_DRAKE_HEART = new QuestItemChanceHolder(7624, 33.0, 100L);
+
 	public Q00053_LinnaeusSpecialBait() {
 		super(53, Q00053_LinnaeusSpecialBait.class.getSimpleName(), "Linnaeus Special Bait");
 		addStartNpc(LINNAEUS);
 		addTalkId(LINNAEUS);
 		addKillId(CRIMSON_DRAKE);
-		registerQuestItems(CRIMSON_DRAKE_HEART);
+		registerQuestItems(CRIMSON_DRAKE_HEART.getId());
 	}
 	
 	@Override
@@ -62,7 +60,7 @@ public class Q00053_LinnaeusSpecialBait extends Quest {
 				st.startQuest();
 				break;
 			case "31577-3.htm":
-				if (st.isCond(2) && (st.getQuestItemsCount(CRIMSON_DRAKE_HEART) >= 100)) {
+				if (st.isCond(2) && hasItemsAtLimit(st.getPlayer(), CRIMSON_DRAKE_HEART)) {
 					st.giveItems(FLAMING_FISHING_LURE, 4);
 					st.exitQuest(false, true);
 				} else {
@@ -75,26 +73,10 @@ public class Q00053_LinnaeusSpecialBait extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember == null) {
-			return null;
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null && giveItemRandomly(st.getPlayer(), npc, CRIMSON_DRAKE_HEART, true)) {
+			st.setCond(2);
 		}
-		
-		final QuestState st = getQuestState(partyMember, false);
-		
-		if (st.getQuestItemsCount(CRIMSON_DRAKE_HEART) < 100) {
-			double chance = 33 * rates().getRateQuestDrop();
-			if (getRandom(100) < chance) {
-				st.rewardItems(CRIMSON_DRAKE_HEART, 1);
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
-		}
-		
-		if (st.getQuestItemsCount(CRIMSON_DRAKE_HEART) >= 100) {
-			st.setCond(2, true);
-			
-		}
-		
 		return super.onKill(npc, player, isSummon);
 	}
 	
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00065_CertifiedSoulBreaker/Q00065_CertifiedSoulBreaker.java b/src/main/java/com/l2jserver/datapack/quests/Q00065_CertifiedSoulBreaker/Q00065_CertifiedSoulBreaker.java
index b71711eada..6ada5e53ca 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00065_CertifiedSoulBreaker/Q00065_CertifiedSoulBreaker.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00065_CertifiedSoulBreaker/Q00065_CertifiedSoulBreaker.java
@@ -24,6 +24,7 @@ import com.l2jserver.gameserver.enums.Race;
 import com.l2jserver.gameserver.model.Location;
 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;
 import com.l2jserver.gameserver.network.NpcStringId;
@@ -56,8 +57,8 @@ public final class Q00065_CertifiedSoulBreaker extends Quest {
 	private static final int SUSPICIOUS_MAN = 32244;
 	// Items
 	private static final int SEALED_DOCUMENT = 9803;
-	private static final int WYRM_HEART = 9804;
 	private static final int KEKROPUS_RECOMMENDATION = 9805;
+	private static final QuestItemChanceHolder WYRM_HEART = new QuestItemChanceHolder(9804, 20.0, 10L);
 	// Reward
 	private static final int DIMENSIONAL_DIAMOND = 7562;
 	private static final int SOUL_BREAKER_CERTIFICATE = 9806;
@@ -77,7 +78,7 @@ public final class Q00065_CertifiedSoulBreaker extends Quest {
 		addTalkId(GRAND_MASTER_VITUS, CAPTAIN_LUCAS, JACOB, GUARD_HARLAN, GUARD_XABER, GUARD_LIAM, GUARD_VESA, GUARD_ZEROME, WHARF_MANAGER_FELTON, KEKROPUS, VICE_HIERARCH_CASCA, GRAND_MASTER_HOLST, GRAND_MASTER_MELDINA, KATENAR, CARGO_BOX, SUSPICIOUS_MAN);
 		addKillId(WYRM, GUARDIAN_ANGEL);
 		addSpawnId(GUARDIAN_ANGEL, SUSPICIOUS_MAN);
-		registerQuestItems(SEALED_DOCUMENT, WYRM_HEART, KEKROPUS_RECOMMENDATION);
+		registerQuestItems(SEALED_DOCUMENT, WYRM_HEART.getId(), KEKROPUS_RECOMMENDATION);
 	}
 	
 	@Override
@@ -187,7 +188,7 @@ public final class Q00065_CertifiedSoulBreaker extends Quest {
 			}
 			case "32138-12.html": {
 				if (qs.isMemoState(23)) {
-					takeItems(player, WYRM_HEART, -1);
+					takeItems(player, WYRM_HEART.getId(), -1);
 					giveItems(player, KEKROPUS_RECOMMENDATION, 1);
 					qs.setMemoState(24);
 					qs.setCond(17, true);
@@ -252,28 +253,21 @@ public final class Q00065_CertifiedSoulBreaker extends Quest {
 		final QuestState qs = getQuestState(killer, false);
 		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, killer, true)) {
 			switch (npc.getId()) {
-				case WYRM: {
-					if (qs.isMemoState(22)) {
-						if (giveItemRandomly(killer, npc, WYRM_HEART, 1, 10, 0.20, true)) {
-							qs.setMemoState(23);
-							qs.setCond(16, true);
-						}
+				case WYRM -> {
+					if (qs.isMemoState(22) && giveItemRandomly(qs.getPlayer(), npc, WYRM_HEART, true)) {
+						qs.setMemoState(23);
+						qs.setCond(16);
 					}
-					break;
 				}
-				case GUARDIAN_ANGEL: {
+				case GUARDIAN_ANGEL -> {
 					final L2PcInstance c0 = npc.getVariables().getObject("player0", L2PcInstance.class);
 					final L2Npc npc0 = npc.getVariables().getObject("npc0", L2Npc.class);
-					if (killer == c0) {
-						if (c0 != null) {
-							if (qs.isMemoState(12)) {
-								L2Npc katenar = addSpawn(KATENAR, killer.getX() + 20, killer.getY() + 20, killer.getZ(), 0, false, 0);
-								katenar.getVariables().set("player0", killer);
-								katenar.getVariables().set("npc0", npc);
-								qs.setMemoState(13);
-								npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.GRR_IVE_BEEN_HIT));
-							}
-						}
+					if (killer == c0 && qs.isMemoState(12)) {
+						L2Npc katenar = addSpawn(KATENAR, killer.getX() + 20, killer.getY() + 20, killer.getZ(), 0, false, 0);
+						katenar.getVariables().set("player0", killer);
+						katenar.getVariables().set("npc0", npc);
+						qs.setMemoState(13);
+						npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, NpcStringId.GRR_IVE_BEEN_HIT));
 					} else {
 						if (npc0 != null) {
 							if (npc0.getVariables().getBoolean("SPAWNED")) {
@@ -556,4 +550,4 @@ public final class Q00065_CertifiedSoulBreaker extends Quest {
 		}
 		return super.onSpawn(npc);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00103_SpiritOfCraftsman/Q00103_SpiritOfCraftsman.java b/src/main/java/com/l2jserver/datapack/quests/Q00103_SpiritOfCraftsman/Q00103_SpiritOfCraftsman.java
index 20b468c8d3..5c3e35c547 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00103_SpiritOfCraftsman/Q00103_SpiritOfCraftsman.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00103_SpiritOfCraftsman/Q00103_SpiritOfCraftsman.java
@@ -23,6 +23,7 @@ import com.l2jserver.gameserver.enums.Race;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.network.serverpackets.SocialAction;
@@ -45,7 +46,7 @@ public final class Q00103_SpiritOfCraftsman extends Quest {
 	private static final int PRESERVE_OIL = 972;
 	private static final int ZOMBIE_HEAD = 973;
 	private static final int STEELBENDERS_HEAD = 974;
-	private static final int BONE_FRAGMENT = 1107;
+	private static final QuestItemChanceHolder BONE_FRAGMENT = new QuestItemChanceHolder(1107, 10L);
 	// Monsters
 	private static final int MARSH_ZOMBIE = 20015;
 	private static final int DOOM_SOLDIER = 20455;
@@ -69,7 +70,7 @@ public final class Q00103_SpiritOfCraftsman extends Quest {
 		addStartNpc(BLACKSMITH_KAROYD);
 		addTalkId(BLACKSMITH_KAROYD, CECON, HARNE);
 		addKillId(MARSH_ZOMBIE, DOOM_SOLDIER, SKELETON_HUNTER, SKELETON_HUNTER_ARCHER);
-		registerQuestItems(KAROYDS_LETTER, CECKTINONS_VOUCHER1, CECKTINONS_VOUCHER2, SOUL_CATCHER, PRESERVE_OIL, ZOMBIE_HEAD, STEELBENDERS_HEAD, BONE_FRAGMENT);
+		registerQuestItems(KAROYDS_LETTER, CECKTINONS_VOUCHER1, CECKTINONS_VOUCHER2, SOUL_CATCHER, PRESERVE_OIL, ZOMBIE_HEAD, STEELBENDERS_HEAD, BONE_FRAGMENT.getId());
 	}
 	
 	@Override
@@ -165,10 +166,10 @@ public final class Q00103_SpiritOfCraftsman extends Quest {
 						giveItems(talker, CECKTINONS_VOUCHER2, 1);
 						htmltext = "30144-01.html";
 					} else if (hasQuestItems(talker, CECKTINONS_VOUCHER2)) {
-						if (getQuestItemsCount(talker, BONE_FRAGMENT) >= 10) {
+						if (hasItemsAtLimit(talker, BONE_FRAGMENT)) {
 							qs.setCond(5, true);
 							takeItems(talker, CECKTINONS_VOUCHER2, 1);
-							takeItems(talker, BONE_FRAGMENT, 10);
+							takeItems(talker, BONE_FRAGMENT.getId(), -1);
 							giveItems(talker, SOUL_CATCHER, 1);
 							htmltext = "30144-03.html";
 						} else {
@@ -190,25 +191,21 @@ public final class Q00103_SpiritOfCraftsman extends Quest {
 		if (qs == null) {
 			return super.onKill(npc, killer, isSummon);
 		}
-		
+
 		switch (npc.getId()) {
-			case MARSH_ZOMBIE: {
-				if (hasQuestItems(killer, PRESERVE_OIL) && (getRandom(10) < 5) && Util.checkIfInRange(1500, npc, killer, true)) {
-					giveItems(killer, ZOMBIE_HEAD, 1);
-					takeItems(killer, PRESERVE_OIL, -1);
+			case MARSH_ZOMBIE -> {
+				if (hasQuestItems(qs.getPlayer(), PRESERVE_OIL) && (getRandom(10) < 5) && Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
+					giveItems(qs.getPlayer(), ZOMBIE_HEAD, 1);
+					takeItems(qs.getPlayer(), PRESERVE_OIL, -1);
 					qs.setCond(7, true);
 				}
-				break;
 			}
-			case DOOM_SOLDIER:
-			case SKELETON_HUNTER:
-			case SKELETON_HUNTER_ARCHER: {
-				if (hasQuestItems(killer, CECKTINONS_VOUCHER2) && giveItemRandomly(qs.getPlayer(), npc, BONE_FRAGMENT, 1, 10, 1.0, true)) {
-					qs.setCond(4, true);
+			case DOOM_SOLDIER, SKELETON_HUNTER, SKELETON_HUNTER_ARCHER -> {
+				if (hasQuestItems(qs.getPlayer(), CECKTINONS_VOUCHER2) && giveItemRandomly(qs.getPlayer(), npc, BONE_FRAGMENT, true)) {
+					qs.setCond(4);
 				}
-				break;
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00108_JumbleTumbleDiamondFuss/Q00108_JumbleTumbleDiamondFuss.java b/src/main/java/com/l2jserver/datapack/quests/Q00108_JumbleTumbleDiamondFuss/Q00108_JumbleTumbleDiamondFuss.java
index 6c4498f2f6..3bccfdb86e 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00108_JumbleTumbleDiamondFuss/Q00108_JumbleTumbleDiamondFuss.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00108_JumbleTumbleDiamondFuss/Q00108_JumbleTumbleDiamondFuss.java
@@ -18,16 +18,15 @@
  */
 package com.l2jserver.datapack.quests.Q00108_JumbleTumbleDiamondFuss;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00281_HeadForTheHills.Q00281_HeadForTheHills;
 import com.l2jserver.gameserver.enums.Race;
 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.ItemHolder;
+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;
 import com.l2jserver.gameserver.network.serverpackets.SocialAction;
@@ -38,6 +37,9 @@ import com.l2jserver.gameserver.util.Util;
  * @author Janiko
  */
 public final class Q00108_JumbleTumbleDiamondFuss extends Quest {
+	// Misc
+	private static final int MIN_LVL = 10;
+	private static final int MAX_GEM_COUNT = 10;
 	// NPCs
 	private static final int COLLECTOR_GOUPH = 30523;
 	private static final int TRADER_REEP = 30516;
@@ -56,14 +58,21 @@ public final class Q00108_JumbleTumbleDiamondFuss extends Quest {
 	private static final int ELVEN_WINE = 1561;
 	private static final int BRUNONS_DICE = 1562;
 	private static final int BRUNONS_CONTRACT = 1563;
-	private static final int AQUAMARINE = 1564;
-	private static final int CHRYSOBERYL = 1565;
 	private static final int GEM_BOX = 1566;
 	private static final int COAL_PIECE = 1567;
 	private static final int BRUNONS_LETTER = 1568;
 	private static final int BERRY_TART = 1569;
 	private static final int BAT_DIAGRAM = 1570;
-	private static final int STAR_DIAMOND = 1571;
+	private static final QuestItemChanceHolder AQUAMARINE = new QuestItemChanceHolder(1564, MAX_GEM_COUNT);
+	private static final QuestItemChanceHolder CHRYSOBERYL = new QuestItemChanceHolder(1565, MAX_GEM_COUNT);
+	private static final QuestItemChanceHolder STAR_DIAMOND = new QuestItemChanceHolder(1571, 20.0, 1L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(GOBLIN_BRIGAND_LEADER, AQUAMARINE, 80.0)
+			.addSingleDrop(GOBLIN_BRIGAND_LEADER, CHRYSOBERYL, 80.0)
+			.addSingleDrop(GOBLIN_BRIGAND_LIEUTENANT, AQUAMARINE, 60.0)
+			.addSingleDrop(GOBLIN_BRIGAND_LIEUTENANT, CHRYSOBERYL, 60.0)
+			.build();
 	// Rewards
 	private static final ItemHolder[] REWARDS = {
 		new ItemHolder(1060, 100), // Lesser Healing Potion
@@ -74,21 +83,13 @@ public final class Q00108_JumbleTumbleDiamondFuss extends Quest {
 		new ItemHolder(4416, 10), // Echo Crystal - Theme of Celebration
 	};
 	private static final int SILVERSMITH_HAMMER = 1511;
-	// Misc
-	private static final int MIN_LVL = 10;
-	private static final int MAX_GEM_COUNT = 10;
-	private static final Map<Integer, Double> GOBLIN_DROP_CHANCES = new HashMap<>();
-	static {
-		GOBLIN_DROP_CHANCES.put(GOBLIN_BRIGAND_LEADER, 0.8);
-		GOBLIN_DROP_CHANCES.put(GOBLIN_BRIGAND_LIEUTENANT, 0.6);
-	}
 	
 	public Q00108_JumbleTumbleDiamondFuss() {
 		super(108, Q00108_JumbleTumbleDiamondFuss.class.getSimpleName(), "Jumble, Tumble, Diamond Fuss");
 		addStartNpc(COLLECTOR_GOUPH);
 		addTalkId(COLLECTOR_GOUPH, TRADER_REEP, CARRIER_TOROCCO, MINER_MARON, BLACKSMITH_BRUNON, WAREHOUSE_KEEPER_MURDOC, WAREHOUSE_KEEPER_AIRY);
 		addKillId(GOBLIN_BRIGAND_LEADER, GOBLIN_BRIGAND_LIEUTENANT, BLADE_BAT);
-		registerQuestItems(GOUPHS_CONTRACT, REEPS_CONTRACT, ELVEN_WINE, BRUNONS_DICE, BRUNONS_CONTRACT, AQUAMARINE, CHRYSOBERYL, GEM_BOX, COAL_PIECE, BRUNONS_LETTER, BERRY_TART, BAT_DIAGRAM, STAR_DIAMOND);
+		registerQuestItems(GOUPHS_CONTRACT, REEPS_CONTRACT, ELVEN_WINE, BRUNONS_DICE, BRUNONS_CONTRACT, AQUAMARINE.getId(), CHRYSOBERYL.getId(), GEM_BOX, COAL_PIECE, BRUNONS_LETTER, BERRY_TART, BAT_DIAGRAM, STAR_DIAMOND.getId());
 	}
 	
 	@Override
@@ -183,7 +184,7 @@ public final class Q00108_JumbleTumbleDiamondFuss extends Quest {
 								break;
 							}
 							case 12: {
-								if (st.hasQuestItems(STAR_DIAMOND)) {
+								if (st.hasQuestItems(STAR_DIAMOND.getId())) {
 									Q00281_HeadForTheHills.giveNewbieReward(talker);
 									st.addExpAndSp(34565, 2962);
 									st.giveAdena(14666, true);
@@ -304,8 +305,8 @@ public final class Q00108_JumbleTumbleDiamondFuss extends Quest {
 						break;
 					}
 					case 6: {
-						if (st.hasQuestItems(BRUNONS_CONTRACT) && (st.getQuestItemsCount(AQUAMARINE) >= MAX_GEM_COUNT) && (st.getQuestItemsCount(CHRYSOBERYL) >= MAX_GEM_COUNT)) {
-							takeItems(talker, -1, BRUNONS_CONTRACT, AQUAMARINE, CHRYSOBERYL);
+						if (st.hasQuestItems(BRUNONS_CONTRACT) && hasItemsAtLimit(st.getPlayer(), AQUAMARINE, CHRYSOBERYL)) {
+							takeItems(talker, -1, BRUNONS_CONTRACT, AQUAMARINE.getId(), CHRYSOBERYL.getId());
 							st.giveItems(GEM_BOX, 1);
 							st.setCond(7, true);
 							htmltext = "30526-04.html";
@@ -336,7 +337,7 @@ public final class Q00108_JumbleTumbleDiamondFuss extends Quest {
 					case 10:
 					case 11:
 					case 12: {
-						if (hasAtLeastOneQuestItem(talker, BERRY_TART, BAT_DIAGRAM, STAR_DIAMOND)) {
+						if (hasAtLeastOneQuestItem(talker, BERRY_TART, BAT_DIAGRAM, STAR_DIAMOND.getId())) {
 							htmltext = "30526-08.html";
 						}
 						break;
@@ -387,7 +388,7 @@ public final class Q00108_JumbleTumbleDiamondFuss extends Quest {
 						break;
 					}
 					case 12: {
-						if (st.hasQuestItems(STAR_DIAMOND)) {
+						if (st.hasQuestItems(STAR_DIAMOND.getId())) {
 							htmltext = "30522-03.html";
 						}
 						break;
@@ -408,47 +409,43 @@ public final class Q00108_JumbleTumbleDiamondFuss extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getQuestState(killer, false);
-		if ((st != null) && Util.checkIfInRange(1500, npc, killer, true)) {
+		if ((st != null) && Util.checkIfInRange(1500, npc, st.getPlayer(), true)) {
 			switch (npc.getId()) {
-				case GOBLIN_BRIGAND_LEADER:
-				case GOBLIN_BRIGAND_LIEUTENANT: {
+				case GOBLIN_BRIGAND_LEADER, GOBLIN_BRIGAND_LIEUTENANT -> {
 					if (st.isCond(5) && st.hasQuestItems(BRUNONS_CONTRACT)) {
-						final double dropChance = GOBLIN_DROP_CHANCES.get(npc.getId());
 						boolean playSound = false;
-						if (st.giveItemRandomly(npc, AQUAMARINE, 1, MAX_GEM_COUNT, dropChance, false)) {
-							if (st.getQuestItemsCount(CHRYSOBERYL) >= MAX_GEM_COUNT) {
+						if (giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc, AQUAMARINE), false)) {
+							if (hasItemsAtLimit(st.getPlayer(), CHRYSOBERYL)) {
 								st.setCond(6, true);
 								break;
 							}
-							
+
 							playSound = true;
 						}
-						if (st.giveItemRandomly(npc, CHRYSOBERYL, 1, MAX_GEM_COUNT, dropChance, false)) {
-							if (st.getQuestItemsCount(AQUAMARINE) >= MAX_GEM_COUNT) {
+						if (giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc, CHRYSOBERYL), false)) {
+							if (hasItemsAtLimit(st.getPlayer(), AQUAMARINE)) {
 								st.setCond(6, true);
 								break;
 							}
-							
+
 							playSound = true;
 						}
-						
+
 						if (playSound) {
 							st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
 						}
 					}
-					break;
 				}
-				case BLADE_BAT: {
+				case BLADE_BAT -> {
 					if (st.isCond(11) && st.hasQuestItems(BAT_DIAGRAM)) {
-						if (st.giveItemRandomly(npc, STAR_DIAMOND, 1, 1, 0.2, true)) {
+						if (giveItemRandomly(st.getPlayer(), npc, STAR_DIAMOND, true)) {
 							st.takeItems(BAT_DIAGRAM, -1);
 							st.setCond(12);
 						}
 					}
-					break;
 				}
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00111_ElrokianHuntersProof/Q00111_ElrokianHuntersProof.java b/src/main/java/com/l2jserver/datapack/quests/Q00111_ElrokianHuntersProof/Q00111_ElrokianHuntersProof.java
index 073d140683..d86d06a5d6 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00111_ElrokianHuntersProof/Q00111_ElrokianHuntersProof.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00111_ElrokianHuntersProof/Q00111_ElrokianHuntersProof.java
@@ -18,14 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00111_ElrokianHuntersProof;
 
-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.ItemChanceHolder;
+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;
 
@@ -34,6 +32,9 @@ import com.l2jserver.gameserver.model.quest.State;
  * @author Adry_85
  */
 public final class Q00111_ElrokianHuntersProof extends Quest {
+	// Misc
+	private static final int MIN_LEVEL = 75;
+	private static final int DINO_DROPS_LIMIT = 10;
 	// NPCs
 	private static final int MARQUEZ = 32113;
 	private static final int MUSHIKA = 32114;
@@ -42,45 +43,45 @@ public final class Q00111_ElrokianHuntersProof extends Quest {
 	// Items
 	private static final int ELROKIAN_TRAP = 8763;
 	private static final int TRAP_STONE = 8764;
-	private static final int DIARY_FRAGMENT = 8768;
 	private static final int EXPEDITION_MEMBERS_LETTER = 8769;
-	private static final int ORNITHOMINUS_CLAW = 8770;
-	private static final int DEINONYCHUS_BONE = 8771;
-	private static final int PACHYCEPHALOSAURUS_SKIN = 8772;
 	private static final int PRACTICE_ELROKIAN_TRAP = 8773;
-	// Misc
-	private static final int MIN_LEVEL = 75;
-	// Mobs
-	private static final Map<Integer, ItemChanceHolder> MOBS_DROP_CHANCES = new HashMap<>();
-	static {
-		MOBS_DROP_CHANCES.put(22196, new ItemChanceHolder(DIARY_FRAGMENT, 0.51, 4)); // velociraptor_leader
-		MOBS_DROP_CHANCES.put(22197, new ItemChanceHolder(DIARY_FRAGMENT, 0.51, 4)); // velociraptor
-		MOBS_DROP_CHANCES.put(22198, new ItemChanceHolder(DIARY_FRAGMENT, 0.51, 4)); // velociraptor_s
-		MOBS_DROP_CHANCES.put(22218, new ItemChanceHolder(DIARY_FRAGMENT, 0.25, 4)); // velociraptor_n
-		MOBS_DROP_CHANCES.put(22223, new ItemChanceHolder(DIARY_FRAGMENT, 0.26, 4)); // velociraptor_leader2
-		MOBS_DROP_CHANCES.put(22200, new ItemChanceHolder(ORNITHOMINUS_CLAW, 0.66, 11)); // ornithomimus_leader
-		MOBS_DROP_CHANCES.put(22201, new ItemChanceHolder(ORNITHOMINUS_CLAW, 0.33, 11)); // ornithomimus
-		MOBS_DROP_CHANCES.put(22202, new ItemChanceHolder(ORNITHOMINUS_CLAW, 0.66, 11)); // ornithomimus_s
-		MOBS_DROP_CHANCES.put(22219, new ItemChanceHolder(ORNITHOMINUS_CLAW, 0.33, 11)); // ornithomimus_n
-		MOBS_DROP_CHANCES.put(22224, new ItemChanceHolder(ORNITHOMINUS_CLAW, 0.33, 11)); // ornithomimus_leader2
-		MOBS_DROP_CHANCES.put(22203, new ItemChanceHolder(DEINONYCHUS_BONE, 0.65, 11)); // deinonychus_leader
-		MOBS_DROP_CHANCES.put(22204, new ItemChanceHolder(DEINONYCHUS_BONE, 0.32, 11)); // deinonychus
-		MOBS_DROP_CHANCES.put(22205, new ItemChanceHolder(DEINONYCHUS_BONE, 0.66, 11)); // deinonychus_s
-		MOBS_DROP_CHANCES.put(22220, new ItemChanceHolder(DEINONYCHUS_BONE, 0.32, 11)); // deinonychus_n
-		MOBS_DROP_CHANCES.put(22225, new ItemChanceHolder(DEINONYCHUS_BONE, 0.32, 11)); // deinonychus_leader2
-		MOBS_DROP_CHANCES.put(22208, new ItemChanceHolder(PACHYCEPHALOSAURUS_SKIN, 0.50, 11)); // pachycephalosaurus_ldr
-		MOBS_DROP_CHANCES.put(22209, new ItemChanceHolder(PACHYCEPHALOSAURUS_SKIN, 0.50, 11)); // pachycephalosaurus
-		MOBS_DROP_CHANCES.put(22210, new ItemChanceHolder(PACHYCEPHALOSAURUS_SKIN, 0.50, 11)); // pachycephalosaurus_s
-		MOBS_DROP_CHANCES.put(22221, new ItemChanceHolder(PACHYCEPHALOSAURUS_SKIN, 0.49, 11)); // pachycephalosaurus_n
-		MOBS_DROP_CHANCES.put(22226, new ItemChanceHolder(PACHYCEPHALOSAURUS_SKIN, 0.50, 11)); // pachycephalosaurus_ldr2
-	}
+	private static final QuestItemChanceHolder DIARY_FRAGMENT = new QuestItemChanceHolder(8768, 50L);
+	private static final QuestItemChanceHolder ORNITHOMINUS_CLAW = new QuestItemChanceHolder(8770, DINO_DROPS_LIMIT);
+	private static final QuestItemChanceHolder DEINONYCHUS_BONE = new QuestItemChanceHolder(8771, DINO_DROPS_LIMIT);
+	private static final QuestItemChanceHolder PACHYCEPHALOSAURUS_SKIN = new QuestItemChanceHolder(8772, DINO_DROPS_LIMIT);
+	// Droplists
+	private static final QuestDroplist DROPLIST_DIARY = QuestDroplist.builder()
+			.addSingleDrop(22196, DIARY_FRAGMENT, 51.0) // velociraptor_leader
+			.addSingleDrop(22197, DIARY_FRAGMENT, 51.0) // velociraptor
+			.addSingleDrop(22198, DIARY_FRAGMENT, 51.0) // velociraptor_s
+			.addSingleDrop(22218, DIARY_FRAGMENT, 25.0) // velociraptor_n
+			.addSingleDrop(22223, DIARY_FRAGMENT, 26.0) // velociraptor_leader2
+			.build();
+	private static final QuestDroplist DROPLIST_DINO = QuestDroplist.builder()
+			.addSingleDrop(22200, ORNITHOMINUS_CLAW, 66.0) // ornithomimus_leader
+			.addSingleDrop(22201, ORNITHOMINUS_CLAW, 33.0) // ornithomimus
+			.addSingleDrop(22202, ORNITHOMINUS_CLAW, 66.0) // ornithomimus_s
+			.addSingleDrop(22219, ORNITHOMINUS_CLAW, 33.0) // ornithomimus_n
+			.addSingleDrop(22224, ORNITHOMINUS_CLAW, 33.0) // ornithomimus_leader2
+			.addSingleDrop(22203, DEINONYCHUS_BONE, 65.0) // deinonychus_leader
+			.addSingleDrop(22204, DEINONYCHUS_BONE, 32.0) // deinonychus
+			.addSingleDrop(22205, DEINONYCHUS_BONE, 66.0) // deinonychus_s
+			.addSingleDrop(22220, DEINONYCHUS_BONE, 32.0) // deinonychus_n
+			.addSingleDrop(22225, DEINONYCHUS_BONE, 32.0) // deinonychus_leader2
+			.addSingleDrop(22208, PACHYCEPHALOSAURUS_SKIN, 50.0) // pachycephalosaurus_ldr
+			.addSingleDrop(22209, PACHYCEPHALOSAURUS_SKIN, 50.0) // pachycephalosaurus
+			.addSingleDrop(22210, PACHYCEPHALOSAURUS_SKIN, 50.0) // pachycephalosaurus_s
+			.addSingleDrop(22221, PACHYCEPHALOSAURUS_SKIN, 49.0) // pachycephalosaurus_n
+			.addSingleDrop(22226, PACHYCEPHALOSAURUS_SKIN, 50.0) // pachycephalosaurus_ldr2
+			.build();
 	
 	public Q00111_ElrokianHuntersProof() {
 		super(111, Q00111_ElrokianHuntersProof.class.getSimpleName(), "Elrokian Hunter's Proof");
 		addStartNpc(MARQUEZ);
 		addTalkId(MARQUEZ, MUSHIKA, ASAMAH, KIRIKACHIN);
-		addKillId(MOBS_DROP_CHANCES.keySet());
-		registerQuestItems(DIARY_FRAGMENT, EXPEDITION_MEMBERS_LETTER, ORNITHOMINUS_CLAW, DEINONYCHUS_BONE, PACHYCEPHALOSAURUS_SKIN, PRACTICE_ELROKIAN_TRAP);
+		addKillId(DROPLIST_DIARY.getNpcIds());
+		addKillId(DROPLIST_DINO.getNpcIds());
+		registerQuestItems(DIARY_FRAGMENT.getId(), EXPEDITION_MEMBERS_LETTER, ORNITHOMINUS_CLAW.getId(), DEINONYCHUS_BONE.getId(), PACHYCEPHALOSAURUS_SKIN.getId(), PRACTICE_ELROKIAN_TRAP);
 	}
 	
 	@Override
@@ -193,26 +194,20 @@ public final class Q00111_ElrokianHuntersProof extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final QuestState qs = getRandomPartyMemberState(player, -1, 3, npc);
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			final ItemChanceHolder item = MOBS_DROP_CHANCES.get(npc.getId());
-			if (item.getCount() == qs.getMemoState()) {
-				if (qs.isCond(4)) {
-					if (giveItemRandomly(qs.getPlayer(), npc, item.getId(), 1, 50, item.getChance(), true)) {
-						qs.setCond(5);
-					}
-				} else if (qs.isCond(10)) {
-					if (giveItemRandomly(qs.getPlayer(), npc, item.getId(), 1, 10, item.getChance(), true) //
-						&& (getQuestItemsCount(qs.getPlayer(), ORNITHOMINUS_CLAW) >= 10) //
-						&& (getQuestItemsCount(qs.getPlayer(), DEINONYCHUS_BONE) >= 10) //
-						&& (getQuestItemsCount(qs.getPlayer(), PACHYCEPHALOSAURUS_SKIN) >= 10)) {
-						qs.setCond(11);
-					}
+			if (qs.isMemoState(4) && qs.isCond(4)
+					&& giveItemRandomly(qs.getPlayer(), npc, DROPLIST_DIARY.get(npc), true)) {
+				qs.setCond(5);
+			} else if (qs.isMemoState(11) && qs.isCond(10)) {
+				if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST_DINO.get(npc), true)
+						&& hasItemsAtLimit(qs.getPlayer(), ORNITHOMINUS_CLAW, DEINONYCHUS_BONE, PACHYCEPHALOSAURUS_SKIN)) {
+					qs.setCond(11);
 				}
 			}
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
@@ -249,10 +244,10 @@ public final class Q00111_ElrokianHuntersProof extends Quest {
 								break;
 							}
 							case 4: {
-								if (getQuestItemsCount(player, DIARY_FRAGMENT) < 50) {
+								if (!hasItemsAtLimit(player, DIARY_FRAGMENT)) {
 									htmltext = "32113-16.html";
 								} else {
-									takeItems(player, DIARY_FRAGMENT, -1);
+									takeItems(player, DIARY_FRAGMENT.getId(), -1);
 									qs.setMemoState(5);
 									htmltext = "32113-17.html";
 								}
@@ -324,15 +319,15 @@ public final class Q00111_ElrokianHuntersProof extends Quest {
 								break;
 							}
 							case 11: {
-								if ((getQuestItemsCount(player, ORNITHOMINUS_CLAW) < 10) || (getQuestItemsCount(player, DEINONYCHUS_BONE) < 10) || (getQuestItemsCount(player, PACHYCEPHALOSAURUS_SKIN) < 10)) {
+								if (!hasItemsAtLimit(player, ORNITHOMINUS_CLAW, DEINONYCHUS_BONE, PACHYCEPHALOSAURUS_SKIN)) {
 									htmltext = "32115-10.html";
 								} else {
 									qs.setMemoState(12);
 									qs.setCond(12, true);
 									giveItems(player, PRACTICE_ELROKIAN_TRAP, 1);
-									takeItems(player, ORNITHOMINUS_CLAW, -1);
-									takeItems(player, DEINONYCHUS_BONE, -1);
-									takeItems(player, PACHYCEPHALOSAURUS_SKIN, -1);
+									takeItems(player, ORNITHOMINUS_CLAW.getId(), -1);
+									takeItems(player, DEINONYCHUS_BONE.getId(), -1);
+									takeItems(player, PACHYCEPHALOSAURUS_SKIN.getId(), -1);
 									htmltext = "32115-11.html";
 								}
 								break;
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00117_TheOceanOfDistantStars/Q00117_TheOceanOfDistantStars.java b/src/main/java/com/l2jserver/datapack/quests/Q00117_TheOceanOfDistantStars/Q00117_TheOceanOfDistantStars.java
index e2c2948873..5db418c81b 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00117_TheOceanOfDistantStars/Q00117_TheOceanOfDistantStars.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00117_TheOceanOfDistantStars/Q00117_TheOceanOfDistantStars.java
@@ -18,12 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00117_TheOceanOfDistantStars;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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.util.Util;
 
@@ -40,24 +39,21 @@ public final class Q00117_TheOceanOfDistantStars extends Quest {
 	private static final int BOX = 32076;
 	// Items
 	private static final int ENGRAVED_HAMMER = 8488;
-	private static final int BOOK_OF_GREY_STAR = 8495;
+	private static final QuestItemChanceHolder BOOK_OF_GREY_STAR = new QuestItemChanceHolder(8495, 1L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22023, BOOK_OF_GREY_STAR, 17.9) // Bandit Warrior
+			.addSingleDrop(22024, BOOK_OF_GREY_STAR, 10.0) // Bandit Inspector
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 39;
-	// Monsters
-	private static final int BANDIT_WARRIOR = 22023;
-	private static final int BANDIT_INSPECTOR = 22024;
-	private static final Map<Integer, Double> MONSTER_DROP_CHANCES = new HashMap<>();
-	static {
-		MONSTER_DROP_CHANCES.put(BANDIT_WARRIOR, 0.179);
-		MONSTER_DROP_CHANCES.put(BANDIT_INSPECTOR, 0.1);
-	}
 	
 	public Q00117_TheOceanOfDistantStars() {
 		super(117, Q00117_TheOceanOfDistantStars.class.getSimpleName(), "The Ocean of Distant Stars");
 		addStartNpc(ABEY);
 		addTalkId(ABEY, GHOST_OF_A_RAILROAD_ENGINEER, GHOST_OF_AN_ANCIENT_RAILROAD_ENGINEER, BOX, OBI);
-		addKillId(BANDIT_WARRIOR, BANDIT_INSPECTOR);
-		registerQuestItems(ENGRAVED_HAMMER, BOOK_OF_GREY_STAR);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(ENGRAVED_HAMMER, BOOK_OF_GREY_STAR.getId());
 	}
 	
 	@Override
@@ -153,10 +149,10 @@ public final class Q00117_TheOceanOfDistantStars extends Quest {
 				break;
 			}
 			case "32052-07.html": {
-				if (qs.isMemoState(7) && hasQuestItems(player, BOOK_OF_GREY_STAR)) {
+				if (qs.isMemoState(7) && hasQuestItems(player, BOOK_OF_GREY_STAR.getId())) {
 					qs.setMemoState(8);
 					qs.setCond(9, true);
-					takeItems(player, BOOK_OF_GREY_STAR, -1);
+					takeItems(player, BOOK_OF_GREY_STAR.getId(), -1);
 					htmltext = event;
 				}
 				break;
@@ -169,11 +165,11 @@ public final class Q00117_TheOceanOfDistantStars extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 7, 3, npc);
 		
-		if ((qs == null) || !Util.checkIfInRange(1500, npc, killer, true)) {
+		if ((qs == null) || !Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
 			return null;
 		}
 		
-		if (giveItemRandomly(killer, npc, BOOK_OF_GREY_STAR, 1, 1, MONSTER_DROP_CHANCES.get(npc.getId()), true)) {
+		if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)) {
 			qs.setCond(8);
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -268,7 +264,7 @@ public final class Q00117_TheOceanOfDistantStars extends Quest {
 							break;
 						}
 						case 7: {
-							if (hasQuestItems(player, BOOK_OF_GREY_STAR)) {
+							if (hasQuestItems(player, BOOK_OF_GREY_STAR.getId())) {
 								htmltext = "32052-06.html";
 							} else {
 								htmltext = "32052-08.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00118_ToLeadAndBeLed/Q00118_ToLeadAndBeLed.java b/src/main/java/com/l2jserver/datapack/quests/Q00118_ToLeadAndBeLed/Q00118_ToLeadAndBeLed.java
index 238e0c6fcb..a42a7f62fd 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00118_ToLeadAndBeLed/Q00118_ToLeadAndBeLed.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00118_ToLeadAndBeLed/Q00118_ToLeadAndBeLed.java
@@ -22,11 +22,15 @@ import com.l2jserver.datapack.quests.Q00123_TheLeaderAndTheFollower.Q00123_TheLe
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 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.util.Util;
 
+import java.util.List;
+
 /**
  * To Lead And Be Led (118)
  * @author ivantotov
@@ -34,26 +38,32 @@ import com.l2jserver.gameserver.util.Util;
 public final class Q00118_ToLeadAndBeLed extends Quest {
 	// NPC
 	private static final int BLACKSMITH_PINTER = 30298;
-	// Items
-	private static final int CRYSTAL_D = 1458;
-	private static final int BLOOD_OF_MAILLE_LIZARDMAN = 8062;
-	private static final int LEG_OF_KING_ARANEID = 8063;
-	// Reward
-	private static final int CLAN_OATH_HELM = 7850;
-	private static final int CLAN_OATH_ARMOR = 7851;
-	private static final int CLAN_OATH_GAUNTLETS_HEAVY_ARMOR = 7852;
-	private static final int CLAN_OATH_SABATON_HEAVY_ARMOR = 7853;
-	private static final int CLAN_OATH_BRIGANDINE = 7854;
-	private static final int CLAN_OATH_LEATHER_GLOVES_LIGHT_ARMOR = 7855;
-	private static final int CLAN_OATH_BOOTS_LIGHT_ARMOR = 7856;
-	private static final int CLAN_OATH_AKETON = 7857;
-	private static final int CLAN_OATH_PADDED_GLOVES_ROBE = 7858;
-	private static final int CLAN_OATH_SANDALS_ROBE = 7859;
 	// Monster
 	private static final int MAILLE_LIZARDMAN = 20919;
 	private static final int MAILLE_LIZARDMAN_SCOUT = 20920;
 	private static final int MAILLE_LIZARDMAN_GUARD = 20921;
 	private static final int KING_OF_THE_ARANEID = 20927;
+	// Items
+	private static final int CRYSTAL_D = 1458;
+	private static final QuestItemChanceHolder BLOOD_OF_MAILLE_LIZARDMAN = new QuestItemChanceHolder(8062, 7.0, 10L);
+	private static final QuestItemChanceHolder LEG_OF_KING_ARANEID = new QuestItemChanceHolder(8063, 7.0, 8L);
+	// Rewards
+	private static final ItemHolder CLAN_OATH_HELM = new ItemHolder(7850, 1);
+	private static final List<ItemHolder> REWARDS_HEAVY = List.of(
+			CLAN_OATH_HELM,
+			new ItemHolder(7851, 1), // Clan Oath Armor
+			new ItemHolder(7852, 1), // Clan Oath Gauntlets
+			new ItemHolder(7853, 1)); // Clan Oath Sabatons
+	private static final List<ItemHolder> REWARDS_LIGHT = List.of(
+			CLAN_OATH_HELM,
+			new ItemHolder(7854, 1), // Clan Oath Brigandine
+			new ItemHolder(7855, 1), // Clan Oath Leather Gloves
+			new ItemHolder(7856, 1)); // Clan Oath Boots
+	private static final List<ItemHolder> REWARDS_ROBE = List.of(
+			CLAN_OATH_HELM,
+			new ItemHolder(7857, 1), // Clan Oath Aketon
+			new ItemHolder(7858, 1), // Clan Oath Padded Gloves
+			new ItemHolder(7859, 1)); // Clan Oath Sandals
 	// Misc
 	private static final int MIN_LEVEL = 19;
 	private static final int CRYSTAL_COUNT_1 = 922;
@@ -64,7 +74,7 @@ public final class Q00118_ToLeadAndBeLed extends Quest {
 		addStartNpc(BLACKSMITH_PINTER);
 		addTalkId(BLACKSMITH_PINTER);
 		addKillId(MAILLE_LIZARDMAN, MAILLE_LIZARDMAN_SCOUT, MAILLE_LIZARDMAN_GUARD, KING_OF_THE_ARANEID);
-		registerQuestItems(LEG_OF_KING_ARANEID, BLOOD_OF_MAILLE_LIZARDMAN);
+		registerQuestItems(LEG_OF_KING_ARANEID.getId(), BLOOD_OF_MAILLE_LIZARDMAN.getId());
 	}
 	
 	@Override
@@ -149,8 +159,8 @@ public final class Q00118_ToLeadAndBeLed extends Quest {
 				break;
 			}
 			case "30298-05d.html": {
-				if (qs.isMemoState(1) && (getQuestItemsCount(player, BLOOD_OF_MAILLE_LIZARDMAN) >= 10)) {
-					takeItems(player, BLOOD_OF_MAILLE_LIZARDMAN, -1);
+				if (qs.isMemoState(1) && hasItemsAtLimit(player, BLOOD_OF_MAILLE_LIZARDMAN)) {
+					takeItems(player, BLOOD_OF_MAILLE_LIZARDMAN.getId(), -1);
 					qs.setMemoState(2);
 					qs.setMemoStateEx(1, 1);
 					qs.setCond(3, true);
@@ -159,8 +169,8 @@ public final class Q00118_ToLeadAndBeLed extends Quest {
 				break;
 			}
 			case "30298-05e.html": {
-				if (qs.isMemoState(1) && (getQuestItemsCount(player, BLOOD_OF_MAILLE_LIZARDMAN) >= 10)) {
-					takeItems(player, BLOOD_OF_MAILLE_LIZARDMAN, -1);
+				if (qs.isMemoState(1) && hasItemsAtLimit(player, BLOOD_OF_MAILLE_LIZARDMAN)) {
+					takeItems(player, BLOOD_OF_MAILLE_LIZARDMAN.getId(), -1);
 					qs.setMemoState(2);
 					qs.setMemoStateEx(1, 2);
 					qs.setCond(4, true);
@@ -169,8 +179,8 @@ public final class Q00118_ToLeadAndBeLed extends Quest {
 				break;
 			}
 			case "30298-05f.html": {
-				if (qs.isMemoState(1) && (getQuestItemsCount(player, BLOOD_OF_MAILLE_LIZARDMAN) >= 10)) {
-					takeItems(player, BLOOD_OF_MAILLE_LIZARDMAN, -1);
+				if (qs.isMemoState(1) && hasItemsAtLimit(player, BLOOD_OF_MAILLE_LIZARDMAN)) {
+					takeItems(player, BLOOD_OF_MAILLE_LIZARDMAN.getId(), -1);
 					qs.setMemoState(2);
 					qs.setMemoStateEx(1, 3);
 					qs.setCond(5, true);
@@ -187,28 +197,20 @@ public final class Q00118_ToLeadAndBeLed extends Quest {
 		final QuestState qs = getQuestState(killer, false);
 		if ((qs != null) && qs.isStarted()) {
 			switch (npc.getId()) {
-				case MAILLE_LIZARDMAN:
-				case MAILLE_LIZARDMAN_SCOUT:
-				case MAILLE_LIZARDMAN_GUARD: {
-					if (qs.isMemoState(1)) {
-						if (giveItemRandomly(killer, npc, BLOOD_OF_MAILLE_LIZARDMAN, 1, 10, 7, true)) {
-							qs.setCond(2);
-						}
+				case MAILLE_LIZARDMAN, MAILLE_LIZARDMAN_SCOUT, MAILLE_LIZARDMAN_GUARD -> {
+					if (qs.isMemoState(1) && giveItemRandomly(qs.getPlayer(), npc, BLOOD_OF_MAILLE_LIZARDMAN, true)) {
+						qs.setCond(2);
 					}
-					break;
 				}
-				case KING_OF_THE_ARANEID: {
-					if (qs.isMemoState(4)) {
-						if (killer.getSponsor() > 0) {
-							final L2PcInstance c0 = L2World.getInstance().getPlayer(killer.getSponsor());
-							if ((c0 != null) && Util.checkIfInRange(1500, npc, c0, true)) {
-								if (giveItemRandomly(killer, npc, LEG_OF_KING_ARANEID, 1, 8, 7, true)) {
-									qs.setCond(8);
-								}
+				case KING_OF_THE_ARANEID -> {
+					if (qs.isMemoState(4) && killer.getSponsor() > 0) {
+						final L2PcInstance sponsor = L2World.getInstance().getPlayer(killer.getSponsor());
+						if (Util.checkIfInRange(1500, npc, sponsor, true)) {
+							if (giveItemRandomly(qs.getPlayer(), npc, LEG_OF_KING_ARANEID, true)) {
+								qs.setCond(8);
 							}
 						}
 					}
-					break;
 				}
 			}
 		}
@@ -236,7 +238,7 @@ public final class Q00118_ToLeadAndBeLed extends Quest {
 			}
 			case State.STARTED: {
 				if (qs.isMemoState(1)) {
-					if (getQuestItemsCount(player, BLOOD_OF_MAILLE_LIZARDMAN) < 10) {
+					if (!hasItemsAtLimit(player, BLOOD_OF_MAILLE_LIZARDMAN)) {
 						htmltext = "30298-04.html";
 					} else {
 						htmltext = "30298-05.html";
@@ -251,8 +253,8 @@ public final class Q00118_ToLeadAndBeLed extends Quest {
 							htmltext = "30298-06c.html";
 						}
 					} else {
-						final L2PcInstance c0 = L2World.getInstance().getPlayer(player.getSponsor());
-						if ((c0 != null) && Util.checkIfInRange(1500, npc, c0, true)) {
+						final L2PcInstance sponsor = L2World.getInstance().getPlayer(player.getSponsor());
+						if (Util.checkIfInRange(1500, npc, sponsor, true)) {
 							htmltext = "30298-07.html";
 						} else {
 							if (qs.getMemoStateEx(1) == 1) {
@@ -269,27 +271,18 @@ public final class Q00118_ToLeadAndBeLed extends Quest {
 					qs.setCond(7, true);
 					htmltext = "30298-15.html";
 				} else if (qs.isMemoState(4)) {
-					if (getQuestItemsCount(player, LEG_OF_KING_ARANEID) < 8) {
+					if (!hasItemsAtLimit(player, LEG_OF_KING_ARANEID)) {
 						htmltext = "30298-16.html";
 					} else {
 						if (qs.getMemoStateEx(1) == 1) {
-							giveItems(player, CLAN_OATH_HELM, 1);
-							giveItems(player, CLAN_OATH_ARMOR, 1);
-							giveItems(player, CLAN_OATH_GAUNTLETS_HEAVY_ARMOR, 1);
-							giveItems(player, CLAN_OATH_SABATON_HEAVY_ARMOR, 1);
-							takeItems(player, LEG_OF_KING_ARANEID, -1);
+							giveItems(player, REWARDS_HEAVY, 1);
+							takeItems(player, LEG_OF_KING_ARANEID.getId(), -1);
 						} else if (qs.getMemoStateEx(1) == 2) {
-							giveItems(player, CLAN_OATH_HELM, 1);
-							giveItems(player, CLAN_OATH_BRIGANDINE, 1);
-							giveItems(player, CLAN_OATH_LEATHER_GLOVES_LIGHT_ARMOR, 1);
-							giveItems(player, CLAN_OATH_BOOTS_LIGHT_ARMOR, 1);
-							takeItems(player, LEG_OF_KING_ARANEID, -1);
+							giveItems(player, REWARDS_LIGHT, 1);
+							takeItems(player, LEG_OF_KING_ARANEID.getId(), -1);
 						} else if (qs.getMemoStateEx(1) == 3) {
-							giveItems(player, CLAN_OATH_HELM, 1);
-							giveItems(player, CLAN_OATH_AKETON, 1);
-							giveItems(player, CLAN_OATH_PADDED_GLOVES_ROBE, 1);
-							giveItems(player, CLAN_OATH_SANDALS_ROBE, 1);
-							takeItems(player, LEG_OF_KING_ARANEID, -1);
+							giveItems(player, REWARDS_ROBE, 1);
+							takeItems(player, LEG_OF_KING_ARANEID.getId(), -1);
 						}
 						qs.exitQuest(false, true);
 						htmltext = "30298-17.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00123_TheLeaderAndTheFollower/Q00123_TheLeaderAndTheFollower.java b/src/main/java/com/l2jserver/datapack/quests/Q00123_TheLeaderAndTheFollower/Q00123_TheLeaderAndTheFollower.java
index bbc861f841..9ecc4daff1 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00123_TheLeaderAndTheFollower/Q00123_TheLeaderAndTheFollower.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00123_TheLeaderAndTheFollower/Q00123_TheLeaderAndTheFollower.java
@@ -22,11 +22,15 @@ import com.l2jserver.datapack.quests.Q00118_ToLeadAndBeLed.Q00118_ToLeadAndBeLed
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 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.util.Util;
 
+import java.util.List;
+
 /**
  * The Leader And The Follower (123)
  * @author ivantotov
@@ -34,24 +38,30 @@ import com.l2jserver.gameserver.util.Util;
 public final class Q00123_TheLeaderAndTheFollower extends Quest {
 	// NPC
 	private static final int HEAD_BLACKSMITH_NEWYEAR = 31961;
-	// Items
-	private static final int CRYSTAL_D = 1458;
-	private static final int BRUIN_LIZARDMAN_BLOOD = 8549;
-	private static final int PICOT_ARANEIDS_LEG = 8550;
-	// Reward
-	private static final int CLAN_OATH_HELM = 7850;
-	private static final int CLAN_OATH_ARMOR = 7851;
-	private static final int CLAN_OATH_GAUNTLETS_HEAVY_ARMOR = 7852;
-	private static final int CLAN_OATH_SABATON_HEAVY_ARMOR = 7853;
-	private static final int CLAN_OATH_BRIGANDINE = 7854;
-	private static final int CLAN_OATH_LEATHER_GLOVES_LIGHT_ARMOR = 7855;
-	private static final int CLAN_OATH_BOOTS_LIGHT_ARMOR = 7856;
-	private static final int CLAN_OATH_AKETON = 7857;
-	private static final int CLAN_OATH_PADDED_GLOVES_ROBE = 7858;
-	private static final int CLAN_OATH_SANDALS_ROBE = 7859;
 	// Quest Monster
 	private static final int BRUIN_LIZARDMAN = 27321;
 	private static final int PICOT_ARANEID = 27322;
+	// Items
+	private static final int CRYSTAL_D = 1458;
+	private static final QuestItemChanceHolder BRUIN_LIZARDMAN_BLOOD = new QuestItemChanceHolder(8549, 7.0, 10L);
+	private static final QuestItemChanceHolder PICOT_ARANEIDS_LEG = new QuestItemChanceHolder(8550, 7.0, 8L);
+	// Rewards
+	private static final ItemHolder CLAN_OATH_HELM = new ItemHolder(7850, 1);
+	private static final List<ItemHolder> REWARDS_HEAVY = List.of(
+			CLAN_OATH_HELM,
+			new ItemHolder(7851, 1), // Clan Oath Armor
+			new ItemHolder(7852, 1), // Clan Oath Gauntlets
+			new ItemHolder(7853, 1)); // Clan Oath Sabatons
+	private static final List<ItemHolder> REWARDS_LIGHT = List.of(
+			CLAN_OATH_HELM,
+			new ItemHolder(7854, 1), // Clan Oath Brigandine
+			new ItemHolder(7855, 1), // Clan Oath Leather Gloves
+			new ItemHolder(7856, 1)); // Clan Oath Boots
+	private static final List<ItemHolder> REWARDS_ROBE = List.of(
+			CLAN_OATH_HELM,
+			new ItemHolder(7857, 1), // Clan Oath Aketon
+			new ItemHolder(7858, 1), // Clan Oath Padded Gloves
+			new ItemHolder(7859, 1)); // Clan Oath Sandals
 	// Misc
 	private static final int MIN_LEVEL = 19;
 	private static final int CRYSTAL_COUNT_1 = 922;
@@ -62,7 +72,7 @@ public final class Q00123_TheLeaderAndTheFollower extends Quest {
 		addStartNpc(HEAD_BLACKSMITH_NEWYEAR);
 		addTalkId(HEAD_BLACKSMITH_NEWYEAR);
 		addKillId(BRUIN_LIZARDMAN, PICOT_ARANEID);
-		registerQuestItems(BRUIN_LIZARDMAN_BLOOD, PICOT_ARANEIDS_LEG);
+		registerQuestItems(BRUIN_LIZARDMAN_BLOOD.getId(), PICOT_ARANEIDS_LEG.getId());
 	}
 	
 	@Override
@@ -147,8 +157,8 @@ public final class Q00123_TheLeaderAndTheFollower extends Quest {
 				break;
 			}
 			case "31961-05d.html": {
-				if (qs.isMemoState(1) && (getQuestItemsCount(player, BRUIN_LIZARDMAN_BLOOD) >= 10)) {
-					takeItems(player, BRUIN_LIZARDMAN_BLOOD, -1);
+				if (qs.isMemoState(1) && hasItemsAtLimit(player, BRUIN_LIZARDMAN_BLOOD)) {
+					takeItems(player, BRUIN_LIZARDMAN_BLOOD.getId(), -1);
 					qs.setMemoState(2);
 					qs.setMemoStateEx(1, 1);
 					qs.setCond(3, true);
@@ -157,8 +167,8 @@ public final class Q00123_TheLeaderAndTheFollower extends Quest {
 				break;
 			}
 			case "31961-05e.html": {
-				if (qs.isMemoState(1) && (getQuestItemsCount(player, BRUIN_LIZARDMAN_BLOOD) >= 10)) {
-					takeItems(player, BRUIN_LIZARDMAN_BLOOD, -1);
+				if (qs.isMemoState(1) && hasItemsAtLimit(player, BRUIN_LIZARDMAN_BLOOD)) {
+					takeItems(player, BRUIN_LIZARDMAN_BLOOD.getId(), -1);
 					qs.setMemoState(2);
 					qs.setMemoStateEx(1, 2);
 					qs.setCond(4, true);
@@ -167,8 +177,8 @@ public final class Q00123_TheLeaderAndTheFollower extends Quest {
 				break;
 			}
 			case "31961-05f.html": {
-				if (qs.isMemoState(1) && (getQuestItemsCount(player, BRUIN_LIZARDMAN_BLOOD) >= 10)) {
-					takeItems(player, BRUIN_LIZARDMAN_BLOOD, -1);
+				if (qs.isMemoState(1) && hasItemsAtLimit(player, BRUIN_LIZARDMAN_BLOOD)) {
+					takeItems(player, BRUIN_LIZARDMAN_BLOOD.getId(), -1);
 					qs.setMemoState(2);
 					qs.setMemoStateEx(1, 3);
 					qs.setCond(5, true);
@@ -186,26 +196,20 @@ public final class Q00123_TheLeaderAndTheFollower extends Quest {
 		final QuestState qs = getQuestState(killer, false);
 		if ((qs != null) && qs.isStarted()) {
 			switch (npc.getId()) {
-				case BRUIN_LIZARDMAN: {
-					if (qs.isMemoState(1)) {
-						if (giveItemRandomly(killer, npc, BRUIN_LIZARDMAN_BLOOD, 1, 10, 7, true)) {
-							qs.setCond(2);
-						}
+				case BRUIN_LIZARDMAN -> {
+					if (qs.isMemoState(1) && giveItemRandomly(qs.getPlayer(), npc, BRUIN_LIZARDMAN_BLOOD, true)) {
+						qs.setCond(2);
 					}
-					break;
 				}
-				case PICOT_ARANEID: {
-					if (qs.isMemoState(4)) {
-						if (killer.getSponsor() > 0) {
-							final L2PcInstance c0 = L2World.getInstance().getPlayer(killer.getSponsor());
-							if ((c0 != null) && Util.checkIfInRange(1500, npc, c0, true)) {
-								if (giveItemRandomly(killer, npc, PICOT_ARANEIDS_LEG, 1, 8, 7, true)) {
-									qs.setCond(8);
-								}
+				case PICOT_ARANEID -> {
+					if (qs.isMemoState(4) && killer.getSponsor() > 0) {
+						final L2PcInstance sponsor = L2World.getInstance().getPlayer(killer.getSponsor());
+						if (Util.checkIfInRange(1500, npc, sponsor, true)) {
+							if (giveItemRandomly(qs.getPlayer(), npc, PICOT_ARANEIDS_LEG, true)) {
+								qs.setCond(8);
 							}
 						}
 					}
-					break;
 				}
 			}
 		}
@@ -233,7 +237,7 @@ public final class Q00123_TheLeaderAndTheFollower extends Quest {
 			}
 			case State.STARTED: {
 				if (qs.isMemoState(1)) {
-					if (getQuestItemsCount(player, BRUIN_LIZARDMAN_BLOOD) < 10) {
+					if (!hasItemsAtLimit(player, BRUIN_LIZARDMAN_BLOOD)) {
 						htmltext = "31961-04.html";
 					} else {
 						htmltext = "31961-05.html";
@@ -248,8 +252,8 @@ public final class Q00123_TheLeaderAndTheFollower extends Quest {
 							htmltext = "31961-06c.html";
 						}
 					} else {
-						final L2PcInstance c0 = L2World.getInstance().getPlayer(player.getSponsor());
-						if ((c0 != null) && Util.checkIfInRange(1500, npc, c0, true)) {
+						final L2PcInstance sponsor = L2World.getInstance().getPlayer(player.getSponsor());
+						if (Util.checkIfInRange(1500, npc, sponsor, true)) {
 							htmltext = "31961-07.html";
 						} else {
 							if (qs.getMemoStateEx(1) == 1) {
@@ -266,27 +270,18 @@ public final class Q00123_TheLeaderAndTheFollower extends Quest {
 					qs.setCond(7, true);
 					htmltext = "31961-15.html";
 				} else if (qs.isMemoState(4)) {
-					if (getQuestItemsCount(player, PICOT_ARANEIDS_LEG) < 8) {
+					if (!hasItemsAtLimit(player, PICOT_ARANEIDS_LEG)) {
 						htmltext = "31961-16.html";
 					} else {
 						if (qs.getMemoStateEx(1) == 1) {
-							giveItems(player, CLAN_OATH_HELM, 1);
-							giveItems(player, CLAN_OATH_ARMOR, 1);
-							giveItems(player, CLAN_OATH_GAUNTLETS_HEAVY_ARMOR, 1);
-							giveItems(player, CLAN_OATH_SABATON_HEAVY_ARMOR, 1);
-							takeItems(player, PICOT_ARANEIDS_LEG, -1);
+							giveItems(player, REWARDS_HEAVY, 1);
+							takeItems(player, PICOT_ARANEIDS_LEG.getId(), -1);
 						} else if (qs.getMemoStateEx(1) == 2) {
-							giveItems(player, CLAN_OATH_HELM, 1);
-							giveItems(player, CLAN_OATH_BRIGANDINE, 1);
-							giveItems(player, CLAN_OATH_LEATHER_GLOVES_LIGHT_ARMOR, 1);
-							giveItems(player, CLAN_OATH_BOOTS_LIGHT_ARMOR, 1);
-							takeItems(player, PICOT_ARANEIDS_LEG, -1);
+							giveItems(player, REWARDS_LIGHT, 1);
+							takeItems(player, PICOT_ARANEIDS_LEG.getId(), -1);
 						} else if (qs.getMemoStateEx(1) == 3) {
-							giveItems(player, CLAN_OATH_HELM, 1);
-							giveItems(player, CLAN_OATH_AKETON, 1);
-							giveItems(player, CLAN_OATH_PADDED_GLOVES_ROBE, 1);
-							giveItems(player, CLAN_OATH_SANDALS_ROBE, 1);
-							takeItems(player, PICOT_ARANEIDS_LEG, -1);
+							giveItems(player, REWARDS_ROBE, 1);
+							takeItems(player, PICOT_ARANEIDS_LEG.getId(), -1);
 						}
 						qs.exitQuest(false, true);
 						htmltext = "31961-17.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00125_TheNameOfEvil1/Q00125_TheNameOfEvil1.java b/src/main/java/com/l2jserver/datapack/quests/Q00125_TheNameOfEvil1/Q00125_TheNameOfEvil1.java
index 187386f855..6ac10707e7 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00125_TheNameOfEvil1/Q00125_TheNameOfEvil1.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00125_TheNameOfEvil1/Q00125_TheNameOfEvil1.java
@@ -18,16 +18,13 @@
  */
 package com.l2jserver.datapack.quests.Q00125_TheNameOfEvil1;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00124_MeetingTheElroki.Q00124_MeetingTheElroki;
 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;
 import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
@@ -44,36 +41,32 @@ public class Q00125_TheNameOfEvil1 extends Quest {
 	private static final int BALU_KAIMU = 32120;
 	private static final int CHUTA_KAIMU = 32121;
 	// Items
-	private static final int ORNITHOMIMUS_CLAW = 8779;
-	private static final int DEINONYCHUS_BONE = 8780;
 	private static final int EPITAPH_OF_WISDOM = 8781;
 	private static final int GAZKH_FRAGMENT = 8782;
+	private static final QuestItemChanceHolder ORNITHOMIMUS_CLAW = new QuestItemChanceHolder(8779, 2L);
+	private static final QuestItemChanceHolder DEINONYCHUS_BONE = new QuestItemChanceHolder(8780, 2L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22200, ORNITHOMIMUS_CLAW, 66.1)
+			.addSingleDrop(22201, ORNITHOMIMUS_CLAW, 33.0)
+			.addSingleDrop(22202, ORNITHOMIMUS_CLAW, 66.1)
+			.addSingleDrop(22219, ORNITHOMIMUS_CLAW, 32.7)
+			.addSingleDrop(22224, ORNITHOMIMUS_CLAW, 32.7)
+			.addSingleDrop(22203, DEINONYCHUS_BONE, 65.1)
+			.addSingleDrop(22204, DEINONYCHUS_BONE, 32.6)
+			.addSingleDrop(22205, DEINONYCHUS_BONE, 65.1)
+			.addSingleDrop(22220, DEINONYCHUS_BONE, 31.9)
+			.addSingleDrop(22225, DEINONYCHUS_BONE, 31.9)
+			.build();
 	// Skills
 	private static final int REPRESENTATION_ENTER_THE_SAILREN_NEST_QUEST_ID = 5089;
 	
-	private static final Map<Integer, Integer> ORNITHOMIMUS = new HashMap<>();
-	private static final Map<Integer, Integer> DEINONYCHUS = new HashMap<>();
-	
-	static {
-		ORNITHOMIMUS.put(22200, 661);
-		ORNITHOMIMUS.put(22201, 330);
-		ORNITHOMIMUS.put(22202, 661);
-		ORNITHOMIMUS.put(22219, 327);
-		ORNITHOMIMUS.put(22224, 327);
-		DEINONYCHUS.put(22203, 651);
-		DEINONYCHUS.put(22204, 326);
-		DEINONYCHUS.put(22205, 651);
-		DEINONYCHUS.put(22220, 319);
-		DEINONYCHUS.put(22225, 319);
-	}
-	
 	public Q00125_TheNameOfEvil1() {
 		super(125, Q00125_TheNameOfEvil1.class.getSimpleName(), "The Name of Evil - 1");
 		addStartNpc(MUSHIKA);
 		addTalkId(MUSHIKA, KARAKAWEI, ULU_KAIMU, BALU_KAIMU, CHUTA_KAIMU);
-		addKillId(ORNITHOMIMUS.keySet());
-		addKillId(DEINONYCHUS.keySet());
-		registerQuestItems(ORNITHOMIMUS_CLAW, DEINONYCHUS_BONE, EPITAPH_OF_WISDOM, GAZKH_FRAGMENT);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(ORNITHOMIMUS_CLAW.getId(), DEINONYCHUS_BONE.getId(), EPITAPH_OF_WISDOM, GAZKH_FRAGMENT);
 	}
 	
 	@Override
@@ -228,34 +221,14 @@ public class Q00125_TheNameOfEvil1 extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 3);
-		if (partyMember == null) {
-			return null;
-		}
-		
-		final QuestState st = getQuestState(partyMember, false);
-		int npcId = npc.getId();
-		if (ORNITHOMIMUS.containsKey(npcId)) {
-			if (st.getQuestItemsCount(ORNITHOMIMUS_CLAW) < 2) {
-				double chance = ORNITHOMIMUS.get(npcId) * rates().getRateQuestDrop();
-				if (getRandom(1000) < chance) {
-					st.giveItems(ORNITHOMIMUS_CLAW, 1);
-					st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-				}
-			}
-		} else if (DEINONYCHUS.containsKey(npcId)) {
-			if (st.getQuestItemsCount(DEINONYCHUS_BONE) < 2) {
-				double chance = DEINONYCHUS.get(npcId) * rates().getRateQuestDrop();
-				if (getRandom(1000) < chance) {
-					st.giveItems(DEINONYCHUS_BONE, 1);
-					st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-				}
+		QuestState st = getRandomPartyMemberState(player, 3, 1, npc);
+		if (st != null && giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), false)) {
+			if (hasItemsAtLimit(st.getPlayer(), ORNITHOMIMUS_CLAW, DEINONYCHUS_BONE)) {
+				st.setCond(4, true);
+			} else {
+				playSound(st.getPlayer(), Sound.ITEMSOUND_QUEST_ITEMGET);
 			}
 		}
-		
-		if ((st.getQuestItemsCount(ORNITHOMIMUS_CLAW) == 2) && (st.getQuestItemsCount(DEINONYCHUS_BONE) == 2)) {
-			st.setCond(4, true);
-		}
 		return super.onKill(npc, player, isSummon);
 	}
 	
@@ -315,9 +288,9 @@ public class Q00125_TheNameOfEvil1 extends Quest {
 							htmltext = "32117-10.html";
 							break;
 						case 4:
-							if ((st.getQuestItemsCount(ORNITHOMIMUS_CLAW) >= 2) && (st.getQuestItemsCount(DEINONYCHUS_BONE) >= 2)) {
-								st.takeItems(ORNITHOMIMUS_CLAW, -1);
-								st.takeItems(DEINONYCHUS_BONE, -1);
+							if (hasItemsAtLimit(st.getPlayer(), ORNITHOMIMUS_CLAW, DEINONYCHUS_BONE)) {
+								st.takeItems(ORNITHOMIMUS_CLAW.getId(), -1);
+								st.takeItems(DEINONYCHUS_BONE.getId(), -1);
 								htmltext = "32117-11.html";
 							}
 							break;
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00154_SacrificeToTheSea/Q00154_SacrificeToTheSea.java b/src/main/java/com/l2jserver/datapack/quests/Q00154_SacrificeToTheSea/Q00154_SacrificeToTheSea.java
index d097117eba..0b77d285ec 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00154_SacrificeToTheSea/Q00154_SacrificeToTheSea.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00154_SacrificeToTheSea/Q00154_SacrificeToTheSea.java
@@ -20,6 +20,7 @@ package com.l2jserver.datapack.quests.Q00154_SacrificeToTheSea;
 
 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;
 
@@ -33,9 +34,9 @@ public final class Q00154_SacrificeToTheSea extends Quest {
 	private static final int CRISTEL = 30051;
 	private static final int ROLLFNAN = 30055;
 	// Items
-	private static final int FOX_FUR = 1032;
 	private static final int FOX_FUR_YAM = 1033;
 	private static final int MAIDEN_DOLL = 1034;
+	private static final QuestItemChanceHolder FOX_FUR = new QuestItemChanceHolder(1032, 30.0, 10L);
 	// Monsters
 	private static final int ELDER_KELTIR = 20544;
 	private static final int YOUNG_KELTIR = 20545;
@@ -50,7 +51,7 @@ public final class Q00154_SacrificeToTheSea extends Quest {
 		addStartNpc(ROCKSWELL);
 		addTalkId(ROCKSWELL, CRISTEL, ROLLFNAN);
 		addKillId(ELDER_KELTIR, YOUNG_KELTIR, KELTIR);
-		registerQuestItems(FOX_FUR, FOX_FUR_YAM, MAIDEN_DOLL);
+		registerQuestItems(FOX_FUR.getId(), FOX_FUR_YAM, MAIDEN_DOLL);
 	}
 	
 	@Override
@@ -106,7 +107,7 @@ public final class Q00154_SacrificeToTheSea extends Quest {
 						break;
 					}
 					case 2: {
-						takeItems(talker, FOX_FUR, -1);
+						takeItems(talker, FOX_FUR.getId(), -1);
 						giveItems(talker, FOX_FUR_YAM, 1);
 						qs.setCond(3, true);
 						htmltext = "30051-01.html";
@@ -151,7 +152,7 @@ public final class Q00154_SacrificeToTheSea extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 1, 3, npc);
-		if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, FOX_FUR, 1, 10, 0.3, true)) {
+		if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, FOX_FUR, true)) {
 			qs.setCond(2);
 		}
 		return super.onKill(npc, killer, isSummon);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00175_TheWayOfTheWarrior/Q00175_TheWayOfTheWarrior.java b/src/main/java/com/l2jserver/datapack/quests/Q00175_TheWayOfTheWarrior/Q00175_TheWayOfTheWarrior.java
index 44cce07678..dd8aae24c1 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00175_TheWayOfTheWarrior/Q00175_TheWayOfTheWarrior.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00175_TheWayOfTheWarrior/Q00175_TheWayOfTheWarrior.java
@@ -23,6 +23,7 @@ import com.l2jserver.gameserver.enums.audio.Voice;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
@@ -31,6 +32,8 @@ import com.l2jserver.gameserver.network.NpcStringId;
 import com.l2jserver.gameserver.network.serverpackets.ExShowScreenMessage;
 import com.l2jserver.gameserver.network.serverpackets.SocialAction;
 
+import java.util.List;
+
 /**
  * The Way of the Warrior (175)
  * @author ivantotov
@@ -40,8 +43,8 @@ public final class Q00175_TheWayOfTheWarrior extends Quest {
 	private static final int PERWAN = 32133;
 	private static final int KEKROPUS = 32138;
 	// Items
-	private static final ItemHolder WOLF_TAIL = new ItemHolder(9807, 5);
-	private static final ItemHolder MUERTOS_CLAW = new ItemHolder(9808, 10);
+	private static final QuestItemChanceHolder WOLF_TAIL = new QuestItemChanceHolder(9807, 50.0, 5L);
+	private static final QuestItemChanceHolder MUERTOS_CLAW = new QuestItemChanceHolder(9808, 10L);
 	// Message
 	private static final ExShowScreenMessage MESSAGE = new ExShowScreenMessage(NpcStringId.ACQUISITION_OF_RACE_SPECIFIC_WEAPON_COMPLETE_N_GO_FIND_THE_NEWBIE_GUIDE, 2, 5000);
 	// Misc
@@ -51,14 +54,13 @@ public final class Q00175_TheWayOfTheWarrior extends Quest {
 	// Rewards
 	private static final int WARRIORS_SWORD = 9720;
 	private static final ItemHolder SOULSHOTS_NO_GRADE_FOR_ROOKIES = new ItemHolder(5789, 7000);
-	private static final ItemHolder[] REWARDS = {
+	private static final List<ItemHolder> REWARDS = List.of(
 		new ItemHolder(1060, 100), // Lesser Healing Potion
 		new ItemHolder(4412, 10), // Echo Crystal - Theme of Battle
 		new ItemHolder(4413, 10), // Echo Crystal - Theme of Love
 		new ItemHolder(4414, 10), // Echo Crystal - Theme of Solitude
 		new ItemHolder(4415, 10), // Echo Crystal - Theme of Feast
-		new ItemHolder(4416, 10), // Echo Crystal - Theme of Celebration
-	};
+		new ItemHolder(4416, 10)); // Echo Crystal - Theme of Celebration
 	// Monsters
 	private static final int MOUNTAIN_WEREWOLF = 22235;
 	private static final int[] MONSTERS = {
@@ -110,9 +112,7 @@ public final class Q00175_TheWayOfTheWarrior extends Quest {
 				if (hasItem(player, MUERTOS_CLAW)) {
 					takeItem(player, MUERTOS_CLAW);
 					giveAdena(player, 8799, true);
-					for (ItemHolder reward : REWARDS) {
-						giveItems(player, reward);
-					}
+					giveItems(player, REWARDS);
 					giveNewbieReward(player);
 					giveItems(player, WARRIORS_SWORD, 1);
 					addExpAndSp(player, 20739, 1777);
@@ -135,19 +135,19 @@ public final class Q00175_TheWayOfTheWarrior extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		if (npc.getId() == MOUNTAIN_WEREWOLF) {
-			final QuestState qs = getRandomPartyMemberState(player, 2, 3, npc);
-			if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, WOLF_TAIL.getId(), 1, WOLF_TAIL.getCount(), 0.5, true)) {
-				qs.setCond(3, true);
+			final QuestState qs = getRandomPartyMemberState(killer, 2, 3, npc);
+			if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, WOLF_TAIL, true)) {
+				qs.setCond(3);
 			}
 		} else {
-			final QuestState qs = getRandomPartyMemberState(player, 7, 3, npc);
-			if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, MUERTOS_CLAW.getId(), 1, MUERTOS_CLAW.getCount(), 1.0, true)) {
-				qs.setCond(8, true);
+			final QuestState qs = getRandomPartyMemberState(killer, 7, 3, npc);
+			if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, MUERTOS_CLAW, true)) {
+				qs.setCond(8);
 			}
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
@@ -261,4 +261,4 @@ public final class Q00175_TheWayOfTheWarrior extends Quest {
 			player.sendPacket(MESSAGE);
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00212_TrialOfDuty/Q00212_TrialOfDuty.java b/src/main/java/com/l2jserver/datapack/quests/Q00212_TrialOfDuty/Q00212_TrialOfDuty.java
index e57e8e4605..1c55594cc1 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00212_TrialOfDuty/Q00212_TrialOfDuty.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00212_TrialOfDuty/Q00212_TrialOfDuty.java
@@ -23,7 +23,7 @@ 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.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.items.L2Weapon;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
@@ -49,16 +49,16 @@ public final class Q00212_TrialOfDuty extends Quest {
 	private static final int KNIGHTS_TEAR = 2635;
 	private static final int MIRROR_OF_ORPIC = 2636;
 	private static final int TEAR_OF_CONFESSION = 2637;
-	private static final ItemHolder REPORT_PIECE = new ItemHolder(2638, 10);
 	private static final int TALIANUSS_REPORT = 2639;
 	private static final int TEAR_OF_LOYALTY = 2640;
-	private static final ItemHolder MILITAS_ARTICLE = new ItemHolder(2641, 20);
 	private static final int SAINTS_ASHES_URN = 2641;
 	private static final int ATHEBALDTS_SKULL = 2643;
 	private static final int ATHEBALDTS_RIBS = 2644;
 	private static final int ATHEBALDTS_SHIN = 2645;
 	private static final int LETTER_OF_WINDAWOOD = 2646;
 	private static final int OLD_KNIGHTS_SWORD = 3027;
+	private static final QuestItemChanceHolder REPORT_PIECE = new QuestItemChanceHolder(2638, 10L);
+	private static final QuestItemChanceHolder MILITAS_ARTICLE = new QuestItemChanceHolder(2641, 20L);
 	// Monsters
 	private static final int HANGMAN_TREE = 20144;
 	private static final int SKELETON_MARAUDER = 20190;
@@ -139,13 +139,12 @@ public final class Q00212_TrialOfDuty extends Quest {
 		if ((qs == null) || !Util.checkIfInRange(1500, killer, npc, true)) {
 			return super.onKill(npc, killer, isSummon);
 		}
-		
+
 		switch (npc.getId()) {
-			case SKELETON_MARAUDER:
-			case SKELETON_RAIDER: {
+			case SKELETON_MARAUDER, SKELETON_RAIDER -> {
 				if (qs.isMemoState(2)) {
 					final int flag = qs.getInt("flag");
-					
+
 					if (getRandom(100) < (flag * 10)) {
 						addSpawn(SPIRIT_OF_SIR_HEROD, npc);
 						qs.set("flag", 0);
@@ -153,35 +152,29 @@ public final class Q00212_TrialOfDuty extends Quest {
 						qs.set("flag", flag + 1);
 					}
 				}
-				break;
 			}
-			case SPIRIT_OF_SIR_HEROD: {
+			case SPIRIT_OF_SIR_HEROD -> {
 				if (qs.isMemoState(2)) {
 					final L2Weapon weapon = killer.getActiveWeaponItem();
-					
+
 					if ((weapon != null) && (weapon.getId() == OLD_KNIGHTS_SWORD)) {
 						giveItems(killer, KNIGHTS_TEAR, 1);
 						qs.setMemoState(3);
 						qs.setCond(3, true);
 					}
 				}
-				break;
 			}
-			case STRAIN:
-			case GHOUL: {
-				if (qs.isMemoState(5) && !hasQuestItems(killer, TALIANUSS_REPORT)) {
-					if (giveItemRandomly(killer, npc, REPORT_PIECE.getId(), 1, REPORT_PIECE.getCount(), 1, true)) {
-						takeItem(killer, REPORT_PIECE);
-						giveItems(killer, TALIANUSS_REPORT, 1);
-						qs.setCond(6);
-					}
+			case STRAIN, GHOUL -> {
+				if (qs.isMemoState(5) && !hasQuestItems(killer, TALIANUSS_REPORT) && giveItemRandomly(qs.getPlayer(), npc, REPORT_PIECE, true)) {
+					takeItem(killer, REPORT_PIECE);
+					giveItems(killer, TALIANUSS_REPORT, 1);
+					qs.setCond(6);
 				}
-				break;
 			}
-			case HANGMAN_TREE: {
+			case HANGMAN_TREE -> {
 				if (qs.isMemoState(6)) {
 					final int flag = qs.getInt("flag");
-					
+
 					if (getRandom(100) < ((flag - 3) * 33)) {
 						addSpawn(SPIRIT_OF_SIR_TALIANUS, npc);
 						qs.set("flag", 0);
@@ -190,20 +183,13 @@ public final class Q00212_TrialOfDuty extends Quest {
 						qs.set("flag", flag + 1);
 					}
 				}
-				break;
 			}
-			case LETO_LIZARDMAN:
-			case LETO_LIZARDMAN_ARCHER:
-			case LETO_LIZARDMAN_SOLDIER:
-			case LETO_LIZARDMAN_WARRIOR:
-			case LETO_LIZARDMAN_SHAMAN:
-			case LETO_LIZARDMAN_OVERLORD: {
-				if (qs.isMemoState(9) && giveItemRandomly(killer, npc, MILITAS_ARTICLE.getId(), 1, MILITAS_ARTICLE.getCount(), 1, true)) {
+			case LETO_LIZARDMAN, LETO_LIZARDMAN_ARCHER, LETO_LIZARDMAN_SOLDIER, LETO_LIZARDMAN_WARRIOR, LETO_LIZARDMAN_SHAMAN, LETO_LIZARDMAN_OVERLORD -> {
+				if (qs.isMemoState(9) && giveItemRandomly(qs.getPlayer(), npc, MILITAS_ARTICLE, true)) {
 					qs.setCond(12);
 				}
-				break;
 			}
-			case BREKA_ORC_OVERLORD: {
+			case BREKA_ORC_OVERLORD -> {
 				if (qs.isMemoState(11)) {
 					if (!hasQuestItems(killer, ATHEBALDTS_SKULL)) {
 						giveItems(killer, ATHEBALDTS_SKULL, 1);
@@ -216,7 +202,6 @@ public final class Q00212_TrialOfDuty extends Quest {
 						qs.setCond(15, true);
 					}
 				}
-				break;
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00216_TrialOfTheGuildsman/Q00216_TrialOfTheGuildsman.java b/src/main/java/com/l2jserver/datapack/quests/Q00216_TrialOfTheGuildsman/Q00216_TrialOfTheGuildsman.java
index 8fd1a6d909..2bca44137c 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00216_TrialOfTheGuildsman/Q00216_TrialOfTheGuildsman.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00216_TrialOfTheGuildsman/Q00216_TrialOfTheGuildsman.java
@@ -22,22 +22,45 @@ 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.itemcontainer.Inventory;
 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.network.serverpackets.SocialAction;
 import com.l2jserver.gameserver.util.Util;
 
+import static com.l2jserver.gameserver.model.quest.QuestDroplist.singleDropItem;
+
 /**
  * Trial Of The Guildsman (216)
  * @author ivantotov
  */
 public final class Q00216_TrialOfTheGuildsman extends Quest {
+	// Npcs
 	private static final int WAREHOUSE_KEEPER_VALKON = 30103;
 	private static final int WAREHOUSE_KEEPER_NORMAN = 30210;
 	private static final int BLACKSMITH_ALTRAN = 30283;
 	private static final int BLACKSMITH_PINTER = 30298;
 	private static final int BLACKSMITH_DUNING = 30688;
+	// Monsters
+	private static final int ANT = 20079;
+	private static final int ANT_CAPTAIN = 20080;
+	private static final int ANT_OVERSEER = 20081;
+	private static final int GRANITE_GOLEM = 20083;
+	private static final int MANDRAGORA_SPROUT1 = 20154;
+	private static final int MANDRAGORA_SAPLONG = 20155;
+	private static final int MANDRAGORA_BLOSSOM = 20156;
+	private static final int SILENOS = 20168;
+	private static final int STRAIN = 20200;
+	private static final int GHOUL = 20201;
+	private static final int DEAD_SEEKER = 20202;
+	private static final int MANDRAGORA_SPROUT2 = 20223;
+	private static final int BREKA_ORC = 20267;
+	private static final int BREKA_ORC_ARCHER = 20268;
+	private static final int BREKA_ORC_SHAMAN = 20269;
+	private static final int BREKA_ORC_OVERLORD = 20270;
+	private static final int BREKA_ORC_WARRIOR = 20271;
 	// Items
 	private static final int RECIPE_JOURNEYMAN_RING = 3024;
 	private static final int RECIPE_AMBER_BEAD = 3025;
@@ -51,37 +74,27 @@ public final class Q00216_TrialOfTheGuildsman extends Quest {
 	private static final int DUNINGS_INSTRUCTIONS = 3127;
 	private static final int DUNINGS_KEY = 3128;
 	private static final int NORMANS_LIST = 3129;
-	private static final int GRAY_BONE_POWDER = 3130;
-	private static final int GRANITE_WHETSTONE = 3131;
-	private static final int RED_PIGMENT = 3132;
-	private static final int BRAIDED_YARN = 3133;
 	private static final int JOURNEYMAN_GEM = 3134;
 	private static final int PINTERS_INSTRUCTIONS = 3135;
-	private static final int AMBER_BEAD = 3136;
 	private static final int AMBER_LUMP = 3137;
 	private static final int JOURNEYMAN_DECO_BEADS = 3138;
 	private static final int JOURNEYMAN_RING = 3139;
+	private static final QuestItemChanceHolder GRAY_BONE_POWDER = new QuestItemChanceHolder(3130, 5L, 70L);
+	private static final QuestItemChanceHolder GRANITE_WHETSTONE = new QuestItemChanceHolder(3131, 7L, 70L);
+	private static final QuestItemChanceHolder RED_PIGMENT = new QuestItemChanceHolder(3132, 7L, 70L);
+	private static final QuestItemChanceHolder BRAIDED_YARN = new QuestItemChanceHolder(3133, 10L, 70L);
+	private static final QuestItemChanceHolder AMBER_BEAD = new QuestItemChanceHolder(3136, 70L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(GRANITE_GOLEM, GRANITE_WHETSTONE)
+			.addSingleDrop(SILENOS, BRAIDED_YARN)
+			.addSingleDrop(STRAIN, GRAY_BONE_POWDER)
+			.addSingleDrop(GHOUL, GRAY_BONE_POWDER)
+			.addSingleDrop(DEAD_SEEKER, RED_PIGMENT)
+			.build();
 	// Reward
 	private static final int MARK_OF_GUILDSMAN = 3119;
 	private static final int DIMENSIONAL_DIAMOND = 7562;
-	// Monsters
-	private static final int ANT = 20079;
-	private static final int ANT_CAPTAIN = 20080;
-	private static final int ANT_OVERSEER = 20081;
-	private static final int GRANITE_GOLEM = 20083;
-	private static final int MANDRAGORA_SPROUT1 = 20154;
-	private static final int MANDRAGORA_SAPLONG = 20155;
-	private static final int MANDRAGORA_BLOSSOM = 20156;
-	private static final int SILENOS = 20168;
-	private static final int STRAIN = 20200;
-	private static final int GHOUL = 20201;
-	private static final int DEAD_SEEKER = 20202;
-	private static final int MANDRAGORA_SPROUT2 = 20223;
-	private static final int BREKA_ORC = 20267;
-	private static final int BREKA_ORC_ARCHER = 20268;
-	private static final int BREKA_ORC_SHAMAN = 20269;
-	private static final int BREKA_ORC_OVERLORD = 20270;
-	private static final int BREKA_ORC_WARRIOR = 20271;
 	// Misc
 	private static final int MIN_LVL = 35;
 	
@@ -90,7 +103,7 @@ public final class Q00216_TrialOfTheGuildsman extends Quest {
 		addStartNpc(WAREHOUSE_KEEPER_VALKON);
 		addTalkId(WAREHOUSE_KEEPER_VALKON, WAREHOUSE_KEEPER_NORMAN, BLACKSMITH_ALTRAN, BLACKSMITH_PINTER, BLACKSMITH_DUNING);
 		addKillId(ANT, ANT_CAPTAIN, ANT_OVERSEER, GRANITE_GOLEM, MANDRAGORA_SPROUT1, MANDRAGORA_SAPLONG, MANDRAGORA_BLOSSOM, SILENOS, STRAIN, GHOUL, DEAD_SEEKER, MANDRAGORA_SPROUT2, BREKA_ORC, BREKA_ORC_ARCHER, BREKA_ORC_SHAMAN, BREKA_ORC_OVERLORD, BREKA_ORC_WARRIOR);
-		registerQuestItems(RECIPE_JOURNEYMAN_RING, RECIPE_AMBER_BEAD, VALKONS_RECOMMENDATION, MANDRAGORA_BERRY, ALLTRANS_INSTRUCTIONS, ALLTRANS_1ST_RECOMMENDATION, ALLTRANS_2ND_RECOMMENDATION, NORMANS_INSTRUCTIONS, NORMANS_RECEIPT, DUNINGS_INSTRUCTIONS, DUNINGS_KEY, NORMANS_LIST, GRAY_BONE_POWDER, GRANITE_WHETSTONE, RED_PIGMENT, BRAIDED_YARN, JOURNEYMAN_GEM, PINTERS_INSTRUCTIONS, AMBER_BEAD, AMBER_LUMP, JOURNEYMAN_DECO_BEADS, JOURNEYMAN_RING);
+		registerQuestItems(RECIPE_JOURNEYMAN_RING, RECIPE_AMBER_BEAD, VALKONS_RECOMMENDATION, MANDRAGORA_BERRY, ALLTRANS_INSTRUCTIONS, ALLTRANS_1ST_RECOMMENDATION, ALLTRANS_2ND_RECOMMENDATION, NORMANS_INSTRUCTIONS, NORMANS_RECEIPT, DUNINGS_INSTRUCTIONS, DUNINGS_KEY, NORMANS_LIST, GRAY_BONE_POWDER.getId(), GRANITE_WHETSTONE.getId(), RED_PIGMENT.getId(), BRAIDED_YARN.getId(), JOURNEYMAN_GEM, PINTERS_INSTRUCTIONS, AMBER_BEAD.getId(), AMBER_LUMP, JOURNEYMAN_DECO_BEADS, JOURNEYMAN_RING);
 	}
 	
 	@Override
@@ -227,47 +240,35 @@ public final class Q00216_TrialOfTheGuildsman extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		switch (npc.getId()) {
-			case ANT:
-			case ANT_CAPTAIN:
-			case ANT_OVERSEER: {
+			case ANT, ANT_CAPTAIN, ANT_OVERSEER -> {
 				final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
 				if (qs != null) {
 					int count = 0;
 					if ((qs.getPlayer().getClassId() == ClassId.scavenger) && npc.isSweepActive()) {
 						count += 5;
 					}
-					
+
 					if (getRandomBoolean() && (qs.getPlayer().getClassId() == ClassId.artisan)) {
 						giveItems(qs.getPlayer(), AMBER_LUMP, 1);
 						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_MIDDLE);
 					}
-					
-					if ((getQuestItemsCount(qs.getPlayer(), AMBER_BEAD) + count) < 70) {
+
+					if ((getQuestItemsCount(qs.getPlayer(), AMBER_BEAD.getId()) + count) < AMBER_BEAD.getLimit()) {
 						count += 5;
 					}
-					
+
 					if (count > 0) {
-						giveItemRandomly(qs.getPlayer(), npc, AMBER_BEAD, count, 70, 1.0, true);
+						giveItemRandomly(qs.getPlayer(), npc, singleDropItem(AMBER_BEAD, count), AMBER_BEAD.getLimit(), true);
 					}
 				}
-				break;
 			}
-			case GRANITE_GOLEM: {
+			case GRANITE_GOLEM, SILENOS, STRAIN, GHOUL, DEAD_SEEKER -> {
 				final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
 				if (qs != null) {
-					giveItems(qs.getPlayer(), GRANITE_WHETSTONE, 7);
-					if (getQuestItemsCount(qs.getPlayer(), GRANITE_WHETSTONE) == 70) {
-						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_MIDDLE);
-					} else {
-						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_ITEMGET);
-					}
+					giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 				}
-				break;
 			}
-			case MANDRAGORA_SPROUT1:
-			case MANDRAGORA_SAPLONG:
-			case MANDRAGORA_BLOSSOM:
-			case MANDRAGORA_SPROUT2: {
+			case MANDRAGORA_SPROUT1, MANDRAGORA_SAPLONG, MANDRAGORA_BLOSSOM, MANDRAGORA_SPROUT2 -> {
 				final QuestState qs = getQuestState(killer, false);
 				if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, killer, true)) {
 					if (hasQuestItems(killer, VALKONS_RECOMMENDATION) && !hasQuestItems(killer, MANDRAGORA_BERRY)) {
@@ -275,50 +276,8 @@ public final class Q00216_TrialOfTheGuildsman extends Quest {
 						qs.setCond(4, true);
 					}
 				}
-				break;
-			}
-			case SILENOS: {
-				final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
-				if (qs != null) {
-					giveItems(qs.getPlayer(), BRAIDED_YARN, 10);
-					if (getQuestItemsCount(qs.getPlayer(), BRAIDED_YARN) == 70) {
-						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_MIDDLE);
-					} else {
-						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_ITEMGET);
-					}
-				}
-				break;
-			}
-			case STRAIN:
-			case GHOUL: {
-				final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
-				if (qs != null) {
-					giveItems(qs.getPlayer(), GRAY_BONE_POWDER, 5);
-					if (getQuestItemsCount(qs.getPlayer(), GRAY_BONE_POWDER) == 70) {
-						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_MIDDLE);
-					} else {
-						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_ITEMGET);
-					}
-				}
-				break;
-			}
-			case DEAD_SEEKER: {
-				final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
-				if (qs != null) {
-					giveItems(qs.getPlayer(), RED_PIGMENT, 7);
-					if (getQuestItemsCount(qs.getPlayer(), RED_PIGMENT) == 70) {
-						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_MIDDLE);
-					} else {
-						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_ITEMGET);
-					}
-				}
-				break;
 			}
-			case BREKA_ORC:
-			case BREKA_ORC_ARCHER:
-			case BREKA_ORC_SHAMAN:
-			case BREKA_ORC_OVERLORD:
-			case BREKA_ORC_WARRIOR: {
+			case BREKA_ORC, BREKA_ORC_ARCHER, BREKA_ORC_SHAMAN, BREKA_ORC_OVERLORD, BREKA_ORC_WARRIOR -> {
 				final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
 				if (qs != null) {
 					if (getQuestItemsCount(qs.getPlayer(), DUNINGS_KEY) >= 29) {
@@ -330,7 +289,6 @@ public final class Q00216_TrialOfTheGuildsman extends Quest {
 						playSound(qs.getPlayer(), Sound.ITEMSOUND_QUEST_ITEMGET);
 					}
 				}
-				break;
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -378,12 +336,12 @@ public final class Q00216_TrialOfTheGuildsman extends Quest {
 						} else if (hasQuestItems(player, NORMANS_INSTRUCTIONS) && (getQuestItemsCount(player, DUNINGS_KEY) >= 30)) {
 							htmltext = "30210-07.html";
 						} else if (hasQuestItems(player, NORMANS_LIST)) {
-							if ((getQuestItemsCount(player, GRAY_BONE_POWDER) >= 70) && (getQuestItemsCount(player, GRANITE_WHETSTONE) >= 70) && (getQuestItemsCount(player, RED_PIGMENT) >= 70) && (getQuestItemsCount(player, BRAIDED_YARN) >= 70)) {
+							if (hasItemsAtLimit(player, GRAY_BONE_POWDER, GRANITE_WHETSTONE, RED_PIGMENT, BRAIDED_YARN)) {
 								takeItems(player, NORMANS_LIST, 1);
-								takeItems(player, GRAY_BONE_POWDER, -1);
-								takeItems(player, GRANITE_WHETSTONE, -1);
-								takeItems(player, RED_PIGMENT, -1);
-								takeItems(player, BRAIDED_YARN, -1);
+								takeItems(player, GRAY_BONE_POWDER.getId(), -1);
+								takeItems(player, GRANITE_WHETSTONE.getId(), -1);
+								takeItems(player, RED_PIGMENT.getId(), -1);
+								takeItems(player, BRAIDED_YARN.getId(), -1);
 								giveItems(player, JOURNEYMAN_GEM, 7);
 								if (getQuestItemsCount(player, JOURNEYMAN_DECO_BEADS) >= 7) {
 									qs.setCond(6, true);
@@ -420,12 +378,12 @@ public final class Q00216_TrialOfTheGuildsman extends Quest {
 						if (hasQuestItems(player, ALLTRANS_2ND_RECOMMENDATION)) {
 							htmltext = "30298-02.html";
 						} else if (hasQuestItems(player, PINTERS_INSTRUCTIONS)) {
-							if (getQuestItemsCount(player, AMBER_BEAD) < 70) {
+							if (!hasItemsAtLimit(player, AMBER_BEAD)) {
 								htmltext = "30298-06.html";
 							} else {
 								takeItems(player, RECIPE_AMBER_BEAD, 1);
 								takeItems(player, PINTERS_INSTRUCTIONS, 1);
-								takeItems(player, AMBER_BEAD, -1);
+								takeItems(player, AMBER_BEAD.getId(), -1);
 								takeItems(player, AMBER_LUMP, -1);
 								giveItems(player, JOURNEYMAN_DECO_BEADS, 7);
 								if (getQuestItemsCount(player, JOURNEYMAN_GEM) >= 7) {
@@ -465,40 +423,17 @@ public final class Q00216_TrialOfTheGuildsman extends Quest {
 	
 	@Override
 	public boolean checkPartyMember(L2PcInstance player, L2Npc npc) {
-		boolean check = false;
 		switch (npc.getId()) {
-			case ANT:
-			case ANT_CAPTAIN:
-			case ANT_OVERSEER: {
-				check = hasQuestItems(player, ALLTRANS_INSTRUCTIONS, PINTERS_INSTRUCTIONS) && (getQuestItemsCount(player, AMBER_BEAD) < 70);
-				break;
-			}
-			case GRANITE_GOLEM: {
-				check = hasQuestItems(player, ALLTRANS_INSTRUCTIONS, NORMANS_LIST) && (getQuestItemsCount(player, GRANITE_WHETSTONE) < 70);
-				break;
-			}
-			case SILENOS: {
-				check = hasQuestItems(player, ALLTRANS_INSTRUCTIONS, NORMANS_LIST) && (getQuestItemsCount(player, BRAIDED_YARN) < 70);
-				break;
+			case ANT, ANT_CAPTAIN, ANT_OVERSEER -> {
+				return hasQuestItems(player, ALLTRANS_INSTRUCTIONS, PINTERS_INSTRUCTIONS) && !hasItemsAtLimit(player, AMBER_BEAD);
 			}
-			case STRAIN:
-			case GHOUL: {
-				check = hasQuestItems(player, ALLTRANS_INSTRUCTIONS, NORMANS_LIST) && (getQuestItemsCount(player, GRAY_BONE_POWDER) < 70);
-				break;
+			case GRANITE_GOLEM, SILENOS, STRAIN, GHOUL, DEAD_SEEKER -> {
+				return hasQuestItems(player, ALLTRANS_INSTRUCTIONS, NORMANS_LIST) && !hasItemsAtLimit(player, DROPLIST.get(npc).item());
 			}
-			case DEAD_SEEKER: {
-				check = hasQuestItems(player, ALLTRANS_INSTRUCTIONS, NORMANS_LIST) && (getQuestItemsCount(player, RED_PIGMENT) < 70);
-				break;
-			}
-			case BREKA_ORC:
-			case BREKA_ORC_ARCHER:
-			case BREKA_ORC_SHAMAN:
-			case BREKA_ORC_OVERLORD:
-			case BREKA_ORC_WARRIOR: {
-				check = hasQuestItems(player, ALLTRANS_INSTRUCTIONS, NORMANS_INSTRUCTIONS, DUNINGS_INSTRUCTIONS) && (getQuestItemsCount(player, DUNINGS_KEY) < 30);
-				break;
+			case BREKA_ORC, BREKA_ORC_ARCHER, BREKA_ORC_SHAMAN, BREKA_ORC_OVERLORD, BREKA_ORC_WARRIOR -> {
+				return hasQuestItems(player, ALLTRANS_INSTRUCTIONS, NORMANS_INSTRUCTIONS, DUNINGS_INSTRUCTIONS) && (getQuestItemsCount(player, DUNINGS_KEY) < 30);
 			}
 		}
-		return check;
+		return false;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00222_TestOfTheDuelist/Q00222_TestOfTheDuelist.java b/src/main/java/com/l2jserver/datapack/quests/Q00222_TestOfTheDuelist/Q00222_TestOfTheDuelist.java
index 30dee980a7..ab82b6e7df 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00222_TestOfTheDuelist/Q00222_TestOfTheDuelist.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00222_TestOfTheDuelist/Q00222_TestOfTheDuelist.java
@@ -23,7 +23,9 @@ 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.QuestState;
 import com.l2jserver.gameserver.network.serverpackets.SocialAction;
 import com.l2jserver.gameserver.util.Util;
@@ -35,31 +37,6 @@ import com.l2jserver.gameserver.util.Util;
 public final class Q00222_TestOfTheDuelist extends Quest {
 	// NPC
 	private static final int DUELIST_KAIEN = 30623;
-	// Items
-	private static final int ORDER_GLUDIO = 2763;
-	private static final int ORDER_DION = 2764;
-	private static final int ORDER_GIRAN = 2765;
-	private static final int ORDER_OREN = 2766;
-	private static final int ORDER_ADEN = 2767;
-	private static final int PUNCHERS_SHARD = 2768;
-	private static final int NOBLE_ANTS_FEELER = 2769;
-	private static final int DRONES_CHITIN = 2770;
-	private static final int DEAD_SEEKER_FANG = 2771;
-	private static final int OVERLORD_NECKLACE = 2772;
-	private static final int FETTERED_SOULS_CHAIN = 2773;
-	private static final int CHIEDS_AMULET = 2774;
-	private static final int ENCHANTED_EYE_MEAT = 2775;
-	private static final int TAMRIN_ORCS_RING = 2776;
-	private static final int TAMRIN_ORCS_ARROW = 2777;
-	private static final int FINAL_ORDER = 2778;
-	private static final int EXCUROS_SKIN = 2779;
-	private static final int KRATORS_SHARD = 2780;
-	private static final int GRANDIS_SKIN = 2781;
-	private static final int TIMAK_ORCS_BELT = 2782;
-	private static final int LAKINS_MACE = 2783;
-	// Reward
-	private static final int MARK_OF_DUELIST = 2762;
-	private static final int DIMENSIONAL_DIAMOND = 7562;
 	// Monster
 	private static final int PUNCHER = 20085;
 	private static final int NOBLE_ANT_LEADER = 20090;
@@ -76,6 +53,49 @@ public final class Q00222_TestOfTheDuelist extends Quest {
 	private static final int TAMLIN_ORC = 20601;
 	private static final int TAMLIN_ORC_ARCHER = 20602;
 	private static final int LAKIN = 20604;
+	// Items
+	private static final int ORDER_GLUDIO = 2763;
+	private static final int ORDER_DION = 2764;
+	private static final int ORDER_GIRAN = 2765;
+	private static final int ORDER_OREN = 2766;
+	private static final int ORDER_ADEN = 2767;
+	private static final int FINAL_ORDER = 2778;
+	private static final QuestItemChanceHolder PUNCHERS_SHARD = new QuestItemChanceHolder(2768, 10L);
+	private static final QuestItemChanceHolder NOBLE_ANTS_FEELER = new QuestItemChanceHolder(2769, 10L);
+	private static final QuestItemChanceHolder DRONES_CHITIN = new QuestItemChanceHolder(2770, 10L);
+	private static final QuestItemChanceHolder DEAD_SEEKER_FANG = new QuestItemChanceHolder(2771, 10L);
+	private static final QuestItemChanceHolder OVERLORD_NECKLACE = new QuestItemChanceHolder(2772, 10L);
+	private static final QuestItemChanceHolder FETTERED_SOULS_CHAIN = new QuestItemChanceHolder(2773, 10L);
+	private static final QuestItemChanceHolder CHIEFS_AMULET = new QuestItemChanceHolder(2774, 10L);
+	private static final QuestItemChanceHolder ENCHANTED_EYE_MEAT = new QuestItemChanceHolder(2775, 10L);
+	private static final QuestItemChanceHolder TAMLIN_ORCS_RING = new QuestItemChanceHolder(2776, 10L);
+	private static final QuestItemChanceHolder TAMRIN_ORCS_ARROW = new QuestItemChanceHolder(2777, 10L);
+	private static final QuestItemChanceHolder EXCUROS_SKIN = new QuestItemChanceHolder(2779, 3L);
+	private static final QuestItemChanceHolder KRATORS_SHARD = new QuestItemChanceHolder(2780, 3L);
+	private static final QuestItemChanceHolder GRANDIS_SKIN = new QuestItemChanceHolder(2781, 3L);
+	private static final QuestItemChanceHolder TIMAK_ORCS_BELT = new QuestItemChanceHolder(2782, 3L);
+	private static final QuestItemChanceHolder LAKINS_MACE = new QuestItemChanceHolder(2783, 3L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(PUNCHER, PUNCHERS_SHARD)
+			.addSingleDrop(NOBLE_ANT_LEADER, NOBLE_ANTS_FEELER)
+			.addSingleDrop(DEAD_SEEKER, DEAD_SEEKER_FANG)
+			.addSingleDrop(EXCURO, EXCUROS_SKIN)
+			.addSingleDrop(KRATOR, KRATORS_SHARD)
+			.addSingleDrop(MARSH_STAKATO_DRONE, DRONES_CHITIN)
+			.addSingleDrop(BREKA_ORC_OVERLORD, OVERLORD_NECKLACE)
+			.addSingleDrop(FETTERED_SOUL, FETTERED_SOULS_CHAIN)
+			.addSingleDrop(GRANDIS, GRANDIS_SKIN)
+			.addSingleDrop(ENCHANTED_MONSTEREYE, ENCHANTED_EYE_MEAT)
+			.addSingleDrop(LETO_LIZARDMAN_OVERLORD, CHIEFS_AMULET)
+			.addSingleDrop(TIMAK_ORC_OVERLORD, TIMAK_ORCS_BELT)
+			.addSingleDrop(TAMLIN_ORC, TAMLIN_ORCS_RING)
+			.addSingleDrop(TAMLIN_ORC_ARCHER, TAMRIN_ORCS_ARROW)
+			.addSingleDrop(LAKIN, LAKINS_MACE)
+			.build();
+	// Reward
+	private static final int MARK_OF_DUELIST = 2762;
+	private static final int DIMENSIONAL_DIAMOND = 7562;
 	// Misc
 	private static final int MIN_LEVEL = 39;
 	
@@ -84,7 +104,7 @@ public final class Q00222_TestOfTheDuelist extends Quest {
 		addStartNpc(DUELIST_KAIEN);
 		addTalkId(DUELIST_KAIEN);
 		addKillId(PUNCHER, NOBLE_ANT_LEADER, DEAD_SEEKER, EXCURO, KRATOR, MARSH_STAKATO_DRONE, BREKA_ORC_OVERLORD, FETTERED_SOUL, GRANDIS, ENCHANTED_MONSTEREYE, LETO_LIZARDMAN_OVERLORD, TIMAK_ORC_OVERLORD, TAMLIN_ORC, TAMLIN_ORC_ARCHER, LAKIN);
-		registerQuestItems(ORDER_GLUDIO, ORDER_DION, ORDER_GIRAN, ORDER_OREN, ORDER_ADEN, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW, FINAL_ORDER, EXCUROS_SKIN, KRATORS_SHARD, GRANDIS_SKIN, TIMAK_ORCS_BELT, LAKINS_MACE);
+		registerQuestItems(ORDER_GLUDIO, ORDER_DION, ORDER_GIRAN, ORDER_OREN, ORDER_ADEN, PUNCHERS_SHARD.getId(), NOBLE_ANTS_FEELER.getId(), DRONES_CHITIN.getId(), DEAD_SEEKER_FANG.getId(), OVERLORD_NECKLACE.getId(), FETTERED_SOULS_CHAIN.getId(), CHIEFS_AMULET.getId(), ENCHANTED_EYE_MEAT.getId(), TAMLIN_ORCS_RING.getId(), TAMRIN_ORCS_ARROW.getId(), FINAL_ORDER, EXCUROS_SKIN.getId(), KRATORS_SHARD.getId(), GRANDIS_SKIN.getId(), TIMAK_ORCS_BELT.getId(), LAKINS_MACE.getId());
 	}
 	
 	@Override
@@ -144,16 +164,16 @@ public final class Q00222_TestOfTheDuelist extends Quest {
 				break;
 			}
 			case "30623-16.html": {
-				takeItems(player, PUNCHERS_SHARD, -1);
-				takeItems(player, NOBLE_ANTS_FEELER, -1);
-				takeItems(player, DEAD_SEEKER_FANG, -1);
-				takeItems(player, DRONES_CHITIN, -1);
-				takeItems(player, OVERLORD_NECKLACE, -1);
-				takeItems(player, FETTERED_SOULS_CHAIN, -1);
-				takeItems(player, CHIEDS_AMULET, -1);
-				takeItems(player, ENCHANTED_EYE_MEAT, -1);
-				takeItems(player, TAMRIN_ORCS_RING, -1);
-				takeItems(player, TAMRIN_ORCS_ARROW, -1);
+				takeItems(player, PUNCHERS_SHARD.getId(), -1);
+				takeItems(player, NOBLE_ANTS_FEELER.getId(), -1);
+				takeItems(player, DEAD_SEEKER_FANG.getId(), -1);
+				takeItems(player, DRONES_CHITIN.getId(), -1);
+				takeItems(player, OVERLORD_NECKLACE.getId(), -1);
+				takeItems(player, FETTERED_SOULS_CHAIN.getId(), -1);
+				takeItems(player, CHIEFS_AMULET.getId(), -1);
+				takeItems(player, ENCHANTED_EYE_MEAT.getId(), -1);
+				takeItems(player, TAMLIN_ORCS_RING.getId(), -1);
+				takeItems(player, TAMRIN_ORCS_ARROW.getId(), -1);
 				takeItems(player, ORDER_GLUDIO, 1);
 				takeItems(player, ORDER_DION, 1);
 				takeItems(player, ORDER_GIRAN, 1);
@@ -174,207 +194,44 @@ public final class Q00222_TestOfTheDuelist extends Quest {
 		final QuestState qs = getQuestState(killer, false);
 		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, killer, true)) {
 			switch (npc.getId()) {
-				case PUNCHER: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_GLUDIO)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, PUNCHERS_SHARD, 1, 10, 1.0, true) && (getQuestItemsCount(killer, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case NOBLE_ANT_LEADER: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_GLUDIO)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, NOBLE_ANTS_FEELER, 1, 10, 1.0, true) && (getQuestItemsCount(killer, PUNCHERS_SHARD, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case DEAD_SEEKER: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_DION)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, DEAD_SEEKER_FANG, 1, 10, 1.0, true) && (getQuestItemsCount(killer, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case EXCURO: {
-					
-					if (qs.isMemoState(2) && hasQuestItems(killer, FINAL_ORDER)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, EXCUROS_SKIN, 1, 3, 1.0, true) && (getQuestItemsCount(killer, KRATORS_SHARD, LAKINS_MACE, GRANDIS_SKIN, TIMAK_ORCS_BELT) == 12)) {
-							if (i0 >= 5) {
-								qs.setCond(5);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case KRATOR: {
-					if (qs.isMemoState(2) && hasQuestItems(killer, FINAL_ORDER)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, KRATORS_SHARD, 1, 3, 1.0, true) && (getQuestItemsCount(killer, EXCUROS_SKIN, LAKINS_MACE, GRANDIS_SKIN, TIMAK_ORCS_BELT) == 12)) {
-							if (i0 >= 5) {
-								qs.setCond(5);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case MARSH_STAKATO_DRONE: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_DION)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, DRONES_CHITIN, 1, 10, 1.0, true) && (getQuestItemsCount(killer, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case BREKA_ORC_OVERLORD: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_GIRAN)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, OVERLORD_NECKLACE, 1, 10, 1.0, true) && (getQuestItemsCount(killer, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case FETTERED_SOUL: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_GIRAN)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, FETTERED_SOULS_CHAIN, 1, 10, 1.0, true) && (getQuestItemsCount(killer, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case GRANDIS: {
-					if (qs.isMemoState(2) && hasQuestItems(killer, FINAL_ORDER)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, GRANDIS_SKIN, 1, 3, 1.0, true) && (getQuestItemsCount(killer, EXCUROS_SKIN, KRATORS_SHARD, LAKINS_MACE, TIMAK_ORCS_BELT) == 12)) {
-							if (i0 >= 5) {
-								qs.setCond(5);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case ENCHANTED_MONSTEREYE: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_OREN)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, ENCHANTED_EYE_MEAT, 1, 10, 1.0, true) && (getQuestItemsCount(killer, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case LETO_LIZARDMAN_OVERLORD: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_OREN)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, CHIEDS_AMULET, 1, 10, 1.0, true) && (getQuestItemsCount(killer, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case TIMAK_ORC_OVERLORD: {
-					if (qs.isMemoState(2) && hasQuestItems(killer, FINAL_ORDER)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, TIMAK_ORCS_BELT, 1, 3, 1.0, true) && (getQuestItemsCount(killer, EXCUROS_SKIN, KRATORS_SHARD, LAKINS_MACE, GRANDIS_SKIN) == 12)) {
-							if (i0 >= 5) {
-								qs.setCond(5);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case TAMLIN_ORC: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_ADEN)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, TAMRIN_ORCS_RING, 1, 10, 1.0, true) && (getQuestItemsCount(killer, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_ARROW) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case TAMLIN_ORC_ARCHER: {
-					if (qs.isMemoState(1) && hasQuestItems(killer, ORDER_ADEN)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, TAMRIN_ORCS_ARROW, 1, 10, 1.0, true) && (getQuestItemsCount(killer, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING) == 90)) {
-							if (i0 >= 9) {
-								qs.setCond(3);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
-				case LAKIN: {
-					if (qs.isMemoState(2) && hasQuestItems(killer, FINAL_ORDER)) {
-						final int i0 = qs.getMemoStateEx(1);
-						qs.setMemoStateEx(1, i0 + 1);
-						if (giveItemRandomly(killer, npc, LAKINS_MACE, 1, 3, 1.0, true) && (getQuestItemsCount(killer, EXCUROS_SKIN, KRATORS_SHARD, GRANDIS_SKIN, TIMAK_ORCS_BELT) == 12)) {
-							if (i0 >= 5) {
-								qs.setCond(5);
-							}
-							qs.setMemoStateEx(1, 0);
-						}
-					}
-					break;
-				}
+				case PUNCHER, NOBLE_ANT_LEADER ->
+						handleDropsAndQuestStateUpdate(qs, npc, 1, ORDER_GLUDIO, hasAllDrops(qs.getPlayer()), 9, 3);
+				case DEAD_SEEKER, MARSH_STAKATO_DRONE ->
+						handleDropsAndQuestStateUpdate(qs, npc, 1, ORDER_DION, hasAllDrops(qs.getPlayer()), 9, 3);
+				case BREKA_ORC_OVERLORD, FETTERED_SOUL ->
+						handleDropsAndQuestStateUpdate(qs, npc, 1, ORDER_GIRAN, hasAllDrops(qs.getPlayer()), 9, 3);
+				case ENCHANTED_MONSTEREYE, LETO_LIZARDMAN_OVERLORD ->
+						handleDropsAndQuestStateUpdate(qs, npc, 1, ORDER_OREN, hasAllDrops(qs.getPlayer()), 9, 3);
+				case TAMLIN_ORC, TAMLIN_ORC_ARCHER ->
+						handleDropsAndQuestStateUpdate(qs, npc, 1, ORDER_ADEN, hasAllDrops(qs.getPlayer()), 9, 3);
+				case EXCURO, KRATOR, GRANDIS, TIMAK_ORC_OVERLORD, LAKIN ->
+						handleDropsAndQuestStateUpdate(qs, npc, 2, FINAL_ORDER, hasAllFinalOrderDrops(qs.getPlayer()), 5, 5);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
-	
+
+	private void handleDropsAndQuestStateUpdate(QuestState qs, L2Npc npc, int requiredMemoState, int requiredItemId, boolean hasAllDrops, int memoStateForUpdate, int condToSet) {
+		if (qs.isMemoState(requiredMemoState) && hasQuestItems(qs.getPlayer(), requiredItemId)) {
+			final int memoState = qs.getMemoStateEx(1);
+			qs.setMemoStateEx(1, memoState + 1);
+			if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true) && hasAllDrops) {
+				if (memoState >= memoStateForUpdate) {
+					qs.setCond(condToSet);
+				}
+				qs.setMemoStateEx(1, 0);
+			}
+		}
+	}
+
+	private boolean hasAllDrops(L2PcInstance player) {
+		return hasItemsAtLimit(player, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEFS_AMULET, ENCHANTED_EYE_MEAT, TAMLIN_ORCS_RING, TAMRIN_ORCS_ARROW);
+	}
+
+	private boolean hasAllFinalOrderDrops(L2PcInstance player) {
+		return hasItemsAtLimit(player, EXCUROS_SKIN, KRATORS_SHARD, LAKINS_MACE, GRANDIS_SKIN, TIMAK_ORCS_BELT);
+	}
+
 	@Override
 	public String onTalk(L2Npc npc, L2PcInstance player) {
 		final QuestState qs = getQuestState(player, true);
@@ -391,13 +248,13 @@ public final class Q00222_TestOfTheDuelist extends Quest {
 			}
 		} else if (qs.isStarted()) {
 			if (hasQuestItems(player, ORDER_GLUDIO, ORDER_DION, ORDER_GIRAN, ORDER_OREN, ORDER_ADEN)) {
-				if (getQuestItemsCount(player, PUNCHERS_SHARD, NOBLE_ANTS_FEELER, DRONES_CHITIN, DEAD_SEEKER_FANG, OVERLORD_NECKLACE, FETTERED_SOULS_CHAIN, CHIEDS_AMULET, ENCHANTED_EYE_MEAT, TAMRIN_ORCS_RING, TAMRIN_ORCS_ARROW) == 100) {
+				if (hasAllDrops(player)) {
 					htmltext = "30623-13.html";
 				} else {
 					htmltext = "30623-14.html";
 				}
 			} else if (hasQuestItems(player, FINAL_ORDER)) {
-				if (getQuestItemsCount(player, EXCUROS_SKIN, KRATORS_SHARD, LAKINS_MACE, GRANDIS_SKIN, TIMAK_ORCS_BELT) == 15) {
+				if (hasAllFinalOrderDrops(player)) {
 					giveAdena(player, 161806, true);
 					giveItems(player, MARK_OF_DUELIST, 1);
 					addExpAndSp(player, 894888, 61408);
@@ -413,4 +270,4 @@ public final class Q00222_TestOfTheDuelist extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00230_TestOfTheSummoner/Q00230_TestOfTheSummoner.java b/src/main/java/com/l2jserver/datapack/quests/Q00230_TestOfTheSummoner/Q00230_TestOfTheSummoner.java
index 934d647e37..42d7cd108d 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00230_TestOfTheSummoner/Q00230_TestOfTheSummoner.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00230_TestOfTheSummoner/Q00230_TestOfTheSummoner.java
@@ -18,16 +18,15 @@
  */
 package com.l2jserver.datapack.quests.Q00230_TestOfTheSummoner;
 
-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.L2Summon;
 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.holders.SkillHolder;
 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.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
@@ -36,6 +35,9 @@ import com.l2jserver.gameserver.network.serverpackets.SocialAction;
 import com.l2jserver.gameserver.util.Broadcast;
 import com.l2jserver.gameserver.util.Util;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Test Of The Summoner (230)
  * @author ivantotov
@@ -50,17 +52,36 @@ public final class Q00230_TestOfTheSummoner extends Quest {
 	private static final int SUMMONER_BASILLA = 30638;
 	private static final int SUMMONER_CELESTIEL = 30639;
 	private static final int SUMMONER_BRYNTHEA = 30640;
+	// Monster
+	private static final int NOBLE_ANT = 20089;
+	private static final int NOBLE_ANT_LEADER = 20090;
+	private static final int WYRM = 20176;
+	private static final int TYRANT = 20192;
+	private static final int TYRANT_KINGPIN = 20193;
+	private static final int BREKA_ORC = 20267;
+	private static final int BREKA_ORC_ARCHER = 20268;
+	private static final int BREKA_ORC_SHAMAN = 20269;
+	private static final int BREKA_ORC_OVERLORD = 20270;
+	private static final int BREKA_ORC_WARRIOR = 20271;
+	private static final int FETTERED_SOUL = 20552;
+	private static final int WINDSUS = 20553;
+	private static final int GIANT_FUNGUS = 20555;
+	private static final int MANASHEN_GARGOYLE = 20563;
+	private static final int LETO_LIZARDMAN = 20577;
+	private static final int LETO_LIZARDMAN_ARCHER = 20578;
+	private static final int LETO_LIZARDMAN_SOLDIER = 20579;
+	private static final int LETO_LIZARDMAN_WARRIOR = 20580;
+	private static final int LETO_LIZARDMAN_SHAMAN = 20581;
+	private static final int LETO_LIZARDMAN_OVERLORD = 20582;
+	private static final int KARUL_BUGBEAR = 20600;
+	// Quest Monster
+	private static final int PAKO_THE_CAT = 27102;
+	private static final int UNICORN_RACER = 27103;
+	private static final int SHADOW_TUREN = 27104;
+	private static final int MIMI_THE_CAT = 27105;
+	private static final int UNICORN_PHANTASM = 27106;
+	private static final int SILHOUETTE_TILFO = 27107;
 	// Items
-	private static final int LETOLIZARDMAN_AMULET = 3337;
-	private static final int SAC_OF_REDSPORES = 3338;
-	private static final int KARULBUGBEAR_TOTEM = 3339;
-	private static final int SHARDS_OF_MANASHEN = 3340;
-	private static final int BREKAORC_TOTEM = 3341;
-	private static final int CRIMSON_BLOODSTONE = 3342;
-	private static final int TALONS_OF_TYRANT = 3343;
-	private static final int WINGS_OF_DRONEANT = 3344;
-	private static final int TUSK_OF_WINDSUS = 3345;
-	private static final int FANGS_OF_WYRM = 3346;
 	private static final int LARAS_1ST_LIST = 3347;
 	private static final int LARAS_2ND_LIST = 3348;
 	private static final int LARAS_3RD_LIST = 3349;
@@ -104,43 +125,69 @@ public final class Q00230_TestOfTheSummoner extends Quest {
 	private static final int CRYSTAL_OF_FOUL_6TH = 3387;
 	private static final int CRYSTAL_OF_DEFEAT_6TH = 3388;
 	private static final int CRYSTAL_OF_VICTORY_6TH = 3389;
+	private static final QuestItemChanceHolder LETOLIZARDMAN_AMULET = new QuestItemChanceHolder(3337, 30L);
+	private static final QuestItemChanceHolder SAC_OF_REDSPORES = new QuestItemChanceHolder(3338, 2L, 30L);
+	private static final QuestItemChanceHolder KARULBUGBEAR_TOTEM = new QuestItemChanceHolder(3339, 2L, 30L);
+	private static final QuestItemChanceHolder SHARDS_OF_MANASHEN = new QuestItemChanceHolder(3340, 2L, 30L);
+	private static final QuestItemChanceHolder BREKAORC_TOTEM = new QuestItemChanceHolder(3341, 30L);
+	private static final QuestItemChanceHolder CRIMSON_BLOODSTONE = new QuestItemChanceHolder(3342, 6L, 30L);
+	private static final QuestItemChanceHolder TALONS_OF_TYRANT = new QuestItemChanceHolder(3343, 3L, 30L);
+	private static final QuestItemChanceHolder WINGS_OF_DRONEANT = new QuestItemChanceHolder(3344, 2L, 30L);
+	private static final QuestItemChanceHolder TUSK_OF_WINDSUS = new QuestItemChanceHolder(3345, 3L, 30L);
+	private static final QuestItemChanceHolder FANGS_OF_WYRM = new QuestItemChanceHolder(3346, 3L, 30L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(NOBLE_ANT, WINGS_OF_DRONEANT)
+			.addSingleDrop(NOBLE_ANT_LEADER, WINGS_OF_DRONEANT)
+			.addSingleDrop(WYRM, FANGS_OF_WYRM)
+			.addSingleDrop(TYRANT, TALONS_OF_TYRANT)
+			.addSingleDrop(TYRANT_KINGPIN, TALONS_OF_TYRANT)
+			.addSingleDrop(BREKA_ORC, BREKAORC_TOTEM)
+			.addSingleDrop(BREKA_ORC_ARCHER, BREKAORC_TOTEM)
+			.addSingleDrop(BREKA_ORC_WARRIOR, BREKAORC_TOTEM)
+			.addSingleDrop(BREKA_ORC_SHAMAN, BREKAORC_TOTEM, 2L)
+			.addSingleDrop(BREKA_ORC_OVERLORD, BREKAORC_TOTEM, 2L)
+			.addSingleDrop(FETTERED_SOUL, CRIMSON_BLOODSTONE)
+			.addSingleDrop(WINDSUS, TUSK_OF_WINDSUS)
+			.addSingleDrop(GIANT_FUNGUS, SAC_OF_REDSPORES)
+			.addSingleDrop(MANASHEN_GARGOYLE, SHARDS_OF_MANASHEN)
+			.bulkAddSingleDrop(LETOLIZARDMAN_AMULET)
+				.withNpcs(LETO_LIZARDMAN, LETO_LIZARDMAN_ARCHER, LETO_LIZARDMAN_SOLDIER, LETO_LIZARDMAN_WARRIOR).build()
+			.addSingleDrop(LETO_LIZARDMAN_SHAMAN,LETOLIZARDMAN_AMULET, 2L)
+			.addSingleDrop(LETO_LIZARDMAN_OVERLORD, LETOLIZARDMAN_AMULET, 2L)
+			.addSingleDrop(KARUL_BUGBEAR, KARULBUGBEAR_TOTEM)
+			.build();
 	// Reward
 	private static final int MARK_OF_SUMMONER = 3336;
 	private static final int DIMENSIONAL_DIAMOND = 7562;
-	// Monster
-	private static final int NOBLE_ANT = 20089;
-	private static final int NOBLE_ANT_LEADER = 20090;
-	private static final int WYRM = 20176;
-	private static final int TYRANT = 20192;
-	private static final int TYRANT_KINGPIN = 20193;
-	private static final int BREKA_ORC = 20267;
-	private static final int BREKA_ORC_ARCHER = 20268;
-	private static final int BREKA_ORC_SHAMAN = 20269;
-	private static final int BREKA_ORC_OVERLORD = 20270;
-	private static final int BREKA_ORC_WARRIOR = 20271;
-	private static final int FETTERED_SOUL = 20552;
-	private static final int WINDSUS = 20553;
-	private static final int GIANT_FUNGUS = 20555;
-	private static final int MANASHEN_GARGOYLE = 20563;
-	private static final int LETO_LIZARDMAN = 20577;
-	private static final int LETO_LIZARDMAN_ARCHER = 20578;
-	private static final int LETO_LIZARDMAN_SOLDIER = 20579;
-	private static final int LETO_LIZARDMAN_WARRIOR = 20580;
-	private static final int LETO_LIZARDMAN_SHAMAN = 20581;
-	private static final int LETO_LIZARDMAN_OVERLORD = 20582;
-	private static final int KARUL_BUGBEAR = 20600;
-	// Quest Monster
-	private static final int PAKO_THE_CAT = 27102;
-	private static final int UNICORN_RACER = 27103;
-	private static final int SHADOW_TUREN = 27104;
-	private static final int MIMI_THE_CAT = 27105;
-	private static final int UNICORN_PHANTASM = 27106;
-	private static final int SILHOUETTE_TILFO = 27107;
 	// Skill
 	private static final SkillHolder REDUCTION_IN_RECOVERY_TIME = new SkillHolder(4126, 1);
 	// Misc
 	private static final int MIN_LEVEL = 39;
-	
+	private static final Map<Integer, Integer> MOBS_REQUIRED_ITEMS = new HashMap<>();
+	static {
+		MOBS_REQUIRED_ITEMS.put(NOBLE_ANT, LARAS_5TH_LIST);
+		MOBS_REQUIRED_ITEMS.put(NOBLE_ANT_LEADER, LARAS_5TH_LIST);
+		MOBS_REQUIRED_ITEMS.put(WYRM, LARAS_5TH_LIST);
+		MOBS_REQUIRED_ITEMS.put(TYRANT, LARAS_4TH_LIST);
+		MOBS_REQUIRED_ITEMS.put(TYRANT_KINGPIN, LARAS_4TH_LIST);
+		MOBS_REQUIRED_ITEMS.put(BREKA_ORC, LARAS_3RD_LIST);
+		MOBS_REQUIRED_ITEMS.put(BREKA_ORC_ARCHER, LARAS_3RD_LIST);
+		MOBS_REQUIRED_ITEMS.put(BREKA_ORC_WARRIOR, LARAS_3RD_LIST);
+		MOBS_REQUIRED_ITEMS.put(BREKA_ORC_SHAMAN, LARAS_3RD_LIST);
+		MOBS_REQUIRED_ITEMS.put(BREKA_ORC_OVERLORD, LARAS_3RD_LIST);
+		MOBS_REQUIRED_ITEMS.put(FETTERED_SOUL, LARAS_3RD_LIST);
+		MOBS_REQUIRED_ITEMS.put(WINDSUS, LARAS_4TH_LIST);
+		MOBS_REQUIRED_ITEMS.put(GIANT_FUNGUS, LARAS_1ST_LIST);
+		MOBS_REQUIRED_ITEMS.put(MANASHEN_GARGOYLE, LARAS_2ND_LIST);
+		MOBS_REQUIRED_ITEMS.put(LETO_LIZARDMAN, LARAS_1ST_LIST);
+		MOBS_REQUIRED_ITEMS.put(LETO_LIZARDMAN_ARCHER, LARAS_1ST_LIST);
+		MOBS_REQUIRED_ITEMS.put(LETO_LIZARDMAN_SOLDIER, LARAS_1ST_LIST);
+		MOBS_REQUIRED_ITEMS.put(LETO_LIZARDMAN_WARRIOR, LARAS_1ST_LIST);
+		MOBS_REQUIRED_ITEMS.put(LETO_LIZARDMAN_SHAMAN, LARAS_1ST_LIST);
+		MOBS_REQUIRED_ITEMS.put(LETO_LIZARDMAN_OVERLORD, LARAS_1ST_LIST);
+		MOBS_REQUIRED_ITEMS.put(KARUL_BUGBEAR, LARAS_2ND_LIST);
+	}
 	private static final Map<Integer, MonsterData> MONSTERS = new HashMap<>();
 	static {
 		MONSTERS.put(PAKO_THE_CAT, new MonsterData(CRYSTAL_OF_INPROGRESS_1ST, CRYSTAL_OF_VICTORY_1ST, NpcStringId.IM_SORRY_LORD));
@@ -158,7 +205,7 @@ public final class Q00230_TestOfTheSummoner extends Quest {
 		addKillId(NOBLE_ANT, NOBLE_ANT_LEADER, WYRM, TYRANT, TYRANT_KINGPIN, BREKA_ORC, BREKA_ORC_ARCHER, BREKA_ORC_SHAMAN, BREKA_ORC_OVERLORD, BREKA_ORC_WARRIOR, FETTERED_SOUL, WINDSUS, GIANT_FUNGUS, MANASHEN_GARGOYLE, LETO_LIZARDMAN, LETO_LIZARDMAN_ARCHER, LETO_LIZARDMAN_SOLDIER, LETO_LIZARDMAN_WARRIOR, LETO_LIZARDMAN_SHAMAN, LETO_LIZARDMAN_OVERLORD, KARUL_BUGBEAR);
 		addKillId(MONSTERS.keySet());
 		addAttackId(PAKO_THE_CAT, UNICORN_RACER, SHADOW_TUREN, MIMI_THE_CAT, UNICORN_PHANTASM, SILHOUETTE_TILFO);
-		registerQuestItems(LETOLIZARDMAN_AMULET, SAC_OF_REDSPORES, KARULBUGBEAR_TOTEM, SHARDS_OF_MANASHEN, BREKAORC_TOTEM, CRIMSON_BLOODSTONE, TALONS_OF_TYRANT, WINGS_OF_DRONEANT, TUSK_OF_WINDSUS, FANGS_OF_WYRM, LARAS_1ST_LIST, LARAS_2ND_LIST, LARAS_3RD_LIST, LARAS_4TH_LIST, LARAS_5TH_LIST, GALATEAS_LETTER, BEGINNERS_ARCANA, ALMORS_ARCANA, CAMONIELL_ARCANA, BELTHUS_ARCANA, BASILLIA_ARCANA, CELESTIEL_ARCANA, BRYNTHEA_ARCANA, CRYSTAL_OF_STARTING_1ST, CRYSTAL_OF_INPROGRESS_1ST, CRYSTAL_OF_FOUL_1ST, CRYSTAL_OF_DEFEAT_1ST, CRYSTAL_OF_VICTORY_1ST, CRYSTAL_OF_STARTING_2ND, CRYSTAL_OF_INPROGRESS_2ND, CRYSTAL_OF_FOUL_2ND, CRYSTAL_OF_DEFEAT_2ND, CRYSTAL_OF_VICTORY_2ND, CRYSTAL_OF_STARTING_3RD, CRYSTAL_OF_INPROGRESS_3RD, CRYSTAL_OF_FOUL_3RD, CRYSTAL_OF_DEFEAT_3RD, CRYSTAL_OF_VICTORY_3RD, CRYSTAL_OF_STARTING_4TH, CRYSTAL_OF_INPROGRESS_4TH, CRYSTAL_OF_FOUL_4TH, CRYSTAL_OF_DEFEAT_4TH, CRYSTAL_OF_VICTORY_4TH, CRYSTAL_OF_STARTING_5TH, CRYSTAL_OF_INPROGRESS_5TH, CRYSTAL_OF_FOUL_5TH, CRYSTAL_OF_DEFEAT_5TH, CRYSTAL_OF_VICTORY_5TH, CRYSTAL_OF_STARTING_6TH, CRYSTAL_OF_INPROGRESS_6TH, CRYSTAL_OF_FOUL_6TH, CRYSTAL_OF_DEFEAT_6TH, CRYSTAL_OF_VICTORY_6TH);
+		registerQuestItems(LETOLIZARDMAN_AMULET.getId(), SAC_OF_REDSPORES.getId(), KARULBUGBEAR_TOTEM.getId(), SHARDS_OF_MANASHEN.getId(), BREKAORC_TOTEM.getId(), CRIMSON_BLOODSTONE.getId(), TALONS_OF_TYRANT.getId(), WINGS_OF_DRONEANT.getId(), TUSK_OF_WINDSUS.getId(), FANGS_OF_WYRM.getId(), LARAS_1ST_LIST, LARAS_2ND_LIST, LARAS_3RD_LIST, LARAS_4TH_LIST, LARAS_5TH_LIST, GALATEAS_LETTER, BEGINNERS_ARCANA, ALMORS_ARCANA, CAMONIELL_ARCANA, BELTHUS_ARCANA, BASILLIA_ARCANA, CELESTIEL_ARCANA, BRYNTHEA_ARCANA, CRYSTAL_OF_STARTING_1ST, CRYSTAL_OF_INPROGRESS_1ST, CRYSTAL_OF_FOUL_1ST, CRYSTAL_OF_DEFEAT_1ST, CRYSTAL_OF_VICTORY_1ST, CRYSTAL_OF_STARTING_2ND, CRYSTAL_OF_INPROGRESS_2ND, CRYSTAL_OF_FOUL_2ND, CRYSTAL_OF_DEFEAT_2ND, CRYSTAL_OF_VICTORY_2ND, CRYSTAL_OF_STARTING_3RD, CRYSTAL_OF_INPROGRESS_3RD, CRYSTAL_OF_FOUL_3RD, CRYSTAL_OF_DEFEAT_3RD, CRYSTAL_OF_VICTORY_3RD, CRYSTAL_OF_STARTING_4TH, CRYSTAL_OF_INPROGRESS_4TH, CRYSTAL_OF_FOUL_4TH, CRYSTAL_OF_DEFEAT_4TH, CRYSTAL_OF_VICTORY_4TH, CRYSTAL_OF_STARTING_5TH, CRYSTAL_OF_INPROGRESS_5TH, CRYSTAL_OF_FOUL_5TH, CRYSTAL_OF_DEFEAT_5TH, CRYSTAL_OF_VICTORY_5TH, CRYSTAL_OF_STARTING_6TH, CRYSTAL_OF_INPROGRESS_6TH, CRYSTAL_OF_FOUL_6TH, CRYSTAL_OF_DEFEAT_6TH, CRYSTAL_OF_VICTORY_6TH);
 	}
 	
 	@Override
@@ -599,103 +646,18 @@ public final class Q00230_TestOfTheSummoner 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 NOBLE_ANT:
-				case NOBLE_ANT_LEADER: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_5TH_LIST)) {
-						giveItemRandomly(killer, npc, WINGS_OF_DRONEANT, 2, 30, 1.0, true);
-					}
-					break;
-				}
-				case WYRM: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_5TH_LIST)) {
-						giveItemRandomly(killer, npc, FANGS_OF_WYRM, 3, 30, 1.0, true);
-					}
-					break;
-				}
-				case TYRANT:
-				case TYRANT_KINGPIN: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_4TH_LIST)) {
-						giveItemRandomly(killer, npc, TALONS_OF_TYRANT, 3, 30, 1.0, true);
-					}
-					break;
-				}
-				case BREKA_ORC:
-				case BREKA_ORC_ARCHER:
-				case BREKA_ORC_WARRIOR: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_3RD_LIST)) {
-						giveItemRandomly(killer, npc, BREKAORC_TOTEM, 1, 30, 1.0, true);
-					}
-					break;
-				}
-				case BREKA_ORC_SHAMAN:
-				case BREKA_ORC_OVERLORD: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_3RD_LIST)) {
-						giveItemRandomly(killer, npc, BREKAORC_TOTEM, 2, 30, 1.0, true);
-					}
-					break;
-				}
-				case FETTERED_SOUL: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_3RD_LIST)) {
-						giveItemRandomly(killer, npc, CRIMSON_BLOODSTONE, 6, 30, 1.0, true);
-					}
-					break;
-				}
-				case WINDSUS: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_4TH_LIST)) {
-						giveItemRandomly(killer, npc, TUSK_OF_WINDSUS, 3, 30, 1.0, true);
-					}
-					break;
-				}
-				case GIANT_FUNGUS: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_1ST_LIST)) {
-						giveItemRandomly(killer, npc, SAC_OF_REDSPORES, 2, 30, 1.0, true);
-					}
-					break;
-				}
-				case MANASHEN_GARGOYLE: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_2ND_LIST)) {
-						giveItemRandomly(killer, npc, SHARDS_OF_MANASHEN, 2, 30, 1.0, true);
-					}
-					break;
-				}
-				case LETO_LIZARDMAN:
-				case LETO_LIZARDMAN_ARCHER:
-				case LETO_LIZARDMAN_SOLDIER:
-				case LETO_LIZARDMAN_WARRIOR: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_1ST_LIST)) {
-						giveItemRandomly(killer, npc, LETOLIZARDMAN_AMULET, 1, 30, 1.0, true);
-					}
-					break;
-				}
-				case LETO_LIZARDMAN_SHAMAN:
-				case LETO_LIZARDMAN_OVERLORD: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_1ST_LIST)) {
-						giveItemRandomly(killer, npc, LETOLIZARDMAN_AMULET, 2, 30, 1.0, true);
-					}
-					break;
-				}
-				case KARUL_BUGBEAR: {
-					if (!hasQuestItems(killer, GALATEAS_LETTER) && hasQuestItems(killer, LARAS_2ND_LIST)) {
-						giveItemRandomly(killer, npc, KARULBUGBEAR_TOTEM, 2, 30, 1.0, true);
-					}
-					break;
-				}
-				case SILHOUETTE_TILFO:
-				case UNICORN_PHANTASM:
-				case MIMI_THE_CAT:
-				case SHADOW_TUREN:
-				case UNICORN_RACER:
-				case PAKO_THE_CAT: {
-					final MonsterData data = MONSTERS.get(npc.getId());
-					if (hasQuestItems(killer, data.getCrystalOfInprogress())) {
-						npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, data.getNpcStringId()));
-						takeItems(killer, data.getCrystalOfInprogress(), 1);
-						giveItems(killer, data.getCrystalOfVictory(), 1);
-						playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
-					}
-					break;
+		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
+			if (DROPLIST.get(npc) != null
+					&& !hasQuestItems(qs.getPlayer(), GALATEAS_LETTER)
+					&& hasQuestItems(qs.getPlayer(), MOBS_REQUIRED_ITEMS.get(npc.getId()))) {
+				giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
+			} else if (MONSTERS.get(npc.getId()) != null) {
+				final MonsterData data = MONSTERS.get(npc.getId());
+				if (hasQuestItems(killer, data.getCrystalOfInprogress())) {
+					npc.broadcastPacket(new NpcSay(npc, Say2.NPC_ALL, data.getNpcStringId()));
+					takeItems(killer, data.getCrystalOfInprogress(), 1);
+					giveItems(killer, data.getCrystalOfVictory(), 1);
+					playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
 				}
 			}
 		}
@@ -746,9 +708,9 @@ public final class Q00230_TestOfTheSummoner extends Quest {
 						if (!hasAtLeastOneQuestItem(player, LARAS_1ST_LIST, LARAS_2ND_LIST, LARAS_3RD_LIST, LARAS_4TH_LIST, LARAS_5TH_LIST)) {
 							htmltext = "30063-03.html";
 						} else if (hasQuestItems(player, LARAS_1ST_LIST)) {
-							if ((getQuestItemsCount(player, LETOLIZARDMAN_AMULET) >= 30) && (getQuestItemsCount(player, SAC_OF_REDSPORES) >= 30)) {
-								takeItems(player, LETOLIZARDMAN_AMULET, -1);
-								takeItems(player, SAC_OF_REDSPORES, -1);
+							if (hasItemsAtLimit(player, LETOLIZARDMAN_AMULET, SAC_OF_REDSPORES)) {
+								takeItems(player, LETOLIZARDMAN_AMULET.getId(), -1);
+								takeItems(player, SAC_OF_REDSPORES.getId(), -1);
 								takeItems(player, LARAS_1ST_LIST, 1);
 								giveItems(player, BEGINNERS_ARCANA, 2);
 								qs.setCond(3, true);
@@ -757,9 +719,9 @@ public final class Q00230_TestOfTheSummoner extends Quest {
 								htmltext = "30063-05.html";
 							}
 						} else if (hasQuestItems(player, LARAS_2ND_LIST)) {
-							if ((getQuestItemsCount(player, KARULBUGBEAR_TOTEM) >= 30) && (getQuestItemsCount(player, SHARDS_OF_MANASHEN) >= 30)) {
-								takeItems(player, KARULBUGBEAR_TOTEM, -1);
-								takeItems(player, SHARDS_OF_MANASHEN, -1);
+							if (hasItemsAtLimit(player, KARULBUGBEAR_TOTEM, SHARDS_OF_MANASHEN)) {
+								takeItems(player, KARULBUGBEAR_TOTEM.getId(), -1);
+								takeItems(player, SHARDS_OF_MANASHEN.getId(), -1);
 								takeItems(player, LARAS_2ND_LIST, 1);
 								giveItems(player, BEGINNERS_ARCANA, 2);
 								qs.setCond(3, true);
@@ -768,9 +730,9 @@ public final class Q00230_TestOfTheSummoner extends Quest {
 								htmltext = "30063-07.html";
 							}
 						} else if (hasQuestItems(player, LARAS_3RD_LIST)) {
-							if ((getQuestItemsCount(player, BREKAORC_TOTEM) >= 30) && (getQuestItemsCount(player, CRIMSON_BLOODSTONE) >= 30)) {
-								takeItems(player, BREKAORC_TOTEM, -1);
-								takeItems(player, CRIMSON_BLOODSTONE, -1);
+							if (hasItemsAtLimit(player, BREKAORC_TOTEM, CRIMSON_BLOODSTONE)) {
+								takeItems(player, BREKAORC_TOTEM.getId(), -1);
+								takeItems(player, CRIMSON_BLOODSTONE.getId(), -1);
 								takeItems(player, LARAS_3RD_LIST, 1);
 								giveItems(player, BEGINNERS_ARCANA, 2);
 								qs.setCond(3, true);
@@ -779,9 +741,9 @@ public final class Q00230_TestOfTheSummoner extends Quest {
 								htmltext = "30063-09.html";
 							}
 						} else if (hasQuestItems(player, LARAS_4TH_LIST)) {
-							if ((getQuestItemsCount(player, TALONS_OF_TYRANT) >= 30) && (getQuestItemsCount(player, TUSK_OF_WINDSUS) >= 30)) {
-								takeItems(player, TALONS_OF_TYRANT, -1);
-								takeItems(player, TUSK_OF_WINDSUS, -1);
+							if (hasItemsAtLimit(player, TALONS_OF_TYRANT, TUSK_OF_WINDSUS)) {
+								takeItems(player, TALONS_OF_TYRANT.getId(), -1);
+								takeItems(player, TUSK_OF_WINDSUS.getId(), -1);
 								takeItems(player, LARAS_4TH_LIST, 1);
 								giveItems(player, BEGINNERS_ARCANA, 2);
 								qs.setCond(3, true);
@@ -790,9 +752,9 @@ public final class Q00230_TestOfTheSummoner extends Quest {
 								htmltext = "30063-11.html";
 							}
 						} else if (hasQuestItems(player, LARAS_5TH_LIST)) {
-							if ((getQuestItemsCount(player, WINGS_OF_DRONEANT) >= 30) && (getQuestItemsCount(player, FANGS_OF_WYRM) >= 30)) {
-								takeItems(player, WINGS_OF_DRONEANT, -1);
-								takeItems(player, FANGS_OF_WYRM, -1);
+							if (hasItemsAtLimit(player, WINGS_OF_DRONEANT, FANGS_OF_WYRM)) {
+								takeItems(player, WINGS_OF_DRONEANT.getId(), -1);
+								takeItems(player, FANGS_OF_WYRM.getId(), -1);
 								takeItems(player, LARAS_5TH_LIST, 1);
 								giveItems(player, BEGINNERS_ARCANA, 2);
 								qs.setCond(3, true);
@@ -986,4 +948,4 @@ public final class Q00230_TestOfTheSummoner extends Quest {
 			return _npcStringId;
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00233_TestOfTheWarSpirit/Q00233_TestOfTheWarSpirit.java b/src/main/java/com/l2jserver/datapack/quests/Q00233_TestOfTheWarSpirit/Q00233_TestOfTheWarSpirit.java
index 5e1712b384..efec254dc9 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00233_TestOfTheWarSpirit/Q00233_TestOfTheWarSpirit.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00233_TestOfTheWarSpirit/Q00233_TestOfTheWarSpirit.java
@@ -23,7 +23,9 @@ 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.QuestState;
 import com.l2jserver.gameserver.network.serverpackets.SocialAction;
 import com.l2jserver.gameserver.util.Util;
@@ -42,14 +44,21 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 	private static final int SHADOW_ORIM = 30630;
 	private static final int ANCESTOR_MARTANKUS = 30649;
 	private static final int SEER_PEKIRON = 30682;
+	// Monster
+	private static final int NOBLE_ANT = 20089;
+	private static final int NOBLE_ANT_LEADER = 20090;
+	private static final int MEDUSA = 20158;
+	private static final int PORTA = 20213;
+	private static final int EXCURO = 20214;
+	private static final int MORDERO = 20215;
+	private static final int LETO_LIZARDMAN_SHAMAN = 20581;
+	private static final int LETO_LIZARDMAN_OVERLORD = 20582;
+	private static final int TAMLIN_ORC = 20601;
+	private static final int TAMLIN_ORC_ARCHER = 20602;
 	// Items
 	private static final int VENDETTA_TOTEM = 2880;
-	private static final int TAMLIN_ORC_HEAD = 2881;
 	private static final int WARSPIRIT_TOTEM = 2882;
 	private static final int ORIMS_CONTRACT = 2883;
-	private static final int PORTAS_EYE = 2884;
-	private static final int EXCUROS_SCALE = 2885;
-	private static final int MORDEOS_TALON = 2886;
 	private static final int BRAKIS_REMAINS1 = 2887;
 	private static final int PEKIRONS_TOTEM = 2888;
 	private static final int TONARS_SKULL = 2889;
@@ -78,20 +87,19 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 	private static final int TONARS_REMAINS2 = 2912;
 	private static final int HERMODTS_REMAINS2 = 2913;
 	private static final int KIRUNAS_REMAINS2 = 2914;
+	private static final QuestItemChanceHolder TAMLIN_ORC_HEAD = new QuestItemChanceHolder(2881, 13L);
+	private static final QuestItemChanceHolder PORTAS_EYE = new QuestItemChanceHolder(2884, 2L, 10L);
+	private static final QuestItemChanceHolder EXCUROS_SCALE = new QuestItemChanceHolder(2885, 5L, 10L);
+	private static final QuestItemChanceHolder MORDEOS_TALON = new QuestItemChanceHolder(2886, 5L, 10L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(PORTA, PORTAS_EYE)
+			.addSingleDrop(EXCURO, EXCUROS_SCALE)
+			.addSingleDrop(MORDERO, MORDEOS_TALON)
+			.build();
 	// Reward
 	private static final int MARK_OF_WARSPIRIT = 2879;
 	private static final int DIMENSIONAL_DIAMOND = 7562;
-	// Monster
-	private static final int NOBLE_ANT = 20089;
-	private static final int NOBLE_ANT_LEADER = 20090;
-	private static final int MEDUSA = 20158;
-	private static final int PORTA = 20213;
-	private static final int EXCURO = 20214;
-	private static final int MORDERO = 20215;
-	private static final int LETO_LIZARDMAN_SHAMAN = 20581;
-	private static final int LETO_LIZARDMAN_OVERLORD = 20582;
-	private static final int TAMLIN_ORC = 20601;
-	private static final int TAMLIN_ORC_ARCHER = 20602;
 	// Quest Monster
 	private static final int STENOA_GORGON_QUEEN = 27108;
 	// Misc
@@ -102,7 +110,7 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 		addStartNpc(SEER_SOMAK);
 		addTalkId(SEER_SOMAK, PRIESTESS_VIVYAN, TRADER_SARIEN, SEER_RACOY, SEER_MANAKIA, SHADOW_ORIM, ANCESTOR_MARTANKUS, SEER_PEKIRON);
 		addKillId(NOBLE_ANT, NOBLE_ANT_LEADER, MEDUSA, PORTA, EXCURO, MORDERO, LETO_LIZARDMAN_SHAMAN, LETO_LIZARDMAN_OVERLORD, TAMLIN_ORC, TAMLIN_ORC_ARCHER, STENOA_GORGON_QUEEN);
-		registerQuestItems(VENDETTA_TOTEM, TAMLIN_ORC_HEAD, WARSPIRIT_TOTEM, ORIMS_CONTRACT, PORTAS_EYE, EXCUROS_SCALE, MORDEOS_TALON, BRAKIS_REMAINS1, PEKIRONS_TOTEM, TONARS_SKULL, TONARS_RIB_BONE, TONARS_SPINE, TONARS_ARM_BONE, TONARS_THIGH_BONE, TONARS_REMAINS1, MANAKIAS_TOTEM, HERMODTS_SKULL, HERMODTS_RIB_BONE, HERMODTS_SPINE, HERMODTS_ARM_BONE, HERMODTS_THIGH_BONE, HERMODTS_REMAINS1, RACOYS_TOTEM, VIVIANTES_LETTER, INSECT_DIAGRAM_BOOK, KIRUNAS_SKULL, KIRUNAS_RIB_BONE, KIRUNAS_SPINE, KIRUNAS_ARM_BONE, KIRUNAS_THIGH_BONE, KIRUNAS_REMAINS1, BRAKIS_REMAINS2, TONARS_REMAINS2, HERMODTS_REMAINS2, KIRUNAS_REMAINS2);
+		registerQuestItems(VENDETTA_TOTEM, TAMLIN_ORC_HEAD.getId(), WARSPIRIT_TOTEM, ORIMS_CONTRACT, PORTAS_EYE.getId(), EXCUROS_SCALE.getId(), MORDEOS_TALON.getId(), BRAKIS_REMAINS1, PEKIRONS_TOTEM, TONARS_SKULL, TONARS_RIB_BONE, TONARS_SPINE, TONARS_ARM_BONE, TONARS_THIGH_BONE, TONARS_REMAINS1, MANAKIAS_TOTEM, HERMODTS_SKULL, HERMODTS_RIB_BONE, HERMODTS_SPINE, HERMODTS_ARM_BONE, HERMODTS_THIGH_BONE, HERMODTS_REMAINS1, RACOYS_TOTEM, VIVIANTES_LETTER, INSECT_DIAGRAM_BOOK, KIRUNAS_SKULL, KIRUNAS_RIB_BONE, KIRUNAS_SPINE, KIRUNAS_ARM_BONE, KIRUNAS_THIGH_BONE, KIRUNAS_REMAINS1, BRAKIS_REMAINS2, TONARS_REMAINS2, HERMODTS_REMAINS2, KIRUNAS_REMAINS2);
 	}
 	
 	@Override
@@ -185,8 +193,7 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 		final QuestState qs = getQuestState(killer, false);
 		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, killer, true)) {
 			switch (npc.getId()) {
-				case NOBLE_ANT:
-				case NOBLE_ANT_LEADER: {
+				case NOBLE_ANT, NOBLE_ANT_LEADER -> {
 					if (hasQuestItems(killer, RACOYS_TOTEM, INSECT_DIAGRAM_BOOK)) {
 						final int i0 = getRandom(100);
 						if (i0 > 65) {
@@ -212,9 +219,8 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 							}
 						}
 					}
-					break;
 				}
-				case MEDUSA: {
+				case MEDUSA -> {
 					if (hasQuestItems(killer, MANAKIAS_TOTEM)) {
 						if (!hasQuestItems(killer, HERMODTS_RIB_BONE)) {
 							giveItems(killer, HERMODTS_RIB_BONE, 1);
@@ -230,28 +236,13 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 							playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
 						}
 					}
-					break;
-				}
-				case PORTA: {
-					if (hasQuestItems(killer, ORIMS_CONTRACT)) {
-						giveItemRandomly(killer, npc, PORTAS_EYE, 2, 10, 1.0, true);
-					}
-					break;
-				}
-				case EXCURO: {
-					if (hasQuestItems(killer, ORIMS_CONTRACT)) {
-						giveItemRandomly(killer, npc, EXCUROS_SCALE, 5, 10, 1.0, true);
-					}
-					break;
 				}
-				case MORDERO: {
+				case PORTA, EXCURO, MORDERO -> {
 					if (hasQuestItems(killer, ORIMS_CONTRACT)) {
-						giveItemRandomly(killer, npc, MORDEOS_TALON, 5, 10, 1.0, true);
+						giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 					}
-					break;
 				}
-				case LETO_LIZARDMAN_SHAMAN:
-				case LETO_LIZARDMAN_OVERLORD: {
+				case LETO_LIZARDMAN_SHAMAN, LETO_LIZARDMAN_OVERLORD -> {
 					if (hasQuestItems(killer, PEKIRONS_TOTEM)) {
 						if (!hasQuestItems(killer, TONARS_SKULL)) {
 							giveItems(killer, TONARS_SKULL, 1);
@@ -270,23 +261,17 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 							playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
 						}
 					}
-					break;
 				}
-				case TAMLIN_ORC:
-				case TAMLIN_ORC_ARCHER: {
-					if (hasQuestItems(killer, VENDETTA_TOTEM)) {
-						if (giveItemRandomly(killer, npc, TAMLIN_ORC_HEAD, 1, 13, 1.0, true)) {
-							qs.setCond(4, true);
-						}
+				case TAMLIN_ORC, TAMLIN_ORC_ARCHER -> {
+					if (hasQuestItems(killer, VENDETTA_TOTEM) && giveItemRandomly(qs.getPlayer(), npc, TAMLIN_ORC_HEAD, true)) {
+						qs.setCond(4);
 					}
-					break;
 				}
-				case STENOA_GORGON_QUEEN: {
+				case STENOA_GORGON_QUEEN -> {
 					if (hasQuestItems(killer, MANAKIAS_TOTEM) && !hasQuestItems(killer, HERMODTS_SKULL)) {
 						giveItems(killer, HERMODTS_SKULL, 1);
 						playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
 					}
-					break;
 				}
 			}
 		}
@@ -329,7 +314,7 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 							htmltext = "30510-06.html";
 						}
 					} else if (hasQuestItems(player, VENDETTA_TOTEM)) {
-						if (getQuestItemsCount(player, TAMLIN_ORC_HEAD) < 13) {
+						if (!hasItemsAtLimit(player, TAMLIN_ORC_HEAD)) {
 							htmltext = "30510-08.html";
 						} else {
 							takeItems(player, VENDETTA_TOTEM, 1);
@@ -427,13 +412,13 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 					if (!hasAtLeastOneQuestItem(player, ORIMS_CONTRACT, BRAKIS_REMAINS1, BRAKIS_REMAINS2, VENDETTA_TOTEM)) {
 						htmltext = "30630-01.html";
 					} else if (hasQuestItems(player, ORIMS_CONTRACT)) {
-						if ((getQuestItemsCount(player, PORTAS_EYE) + getQuestItemsCount(player, EXCUROS_SCALE) + getQuestItemsCount(player, MORDEOS_TALON)) < 30) {
+						if (!hasItemsAtLimit(player, PORTAS_EYE, EXCUROS_SCALE, MORDEOS_TALON)) {
 							htmltext = "30630-05.html";
 						} else {
 							takeItems(player, ORIMS_CONTRACT, 1);
-							takeItems(player, PORTAS_EYE, -1);
-							takeItems(player, EXCUROS_SCALE, -1);
-							takeItems(player, MORDEOS_TALON, -1);
+							takeItems(player, PORTAS_EYE.getId(), -1);
+							takeItems(player, EXCUROS_SCALE.getId(), -1);
+							takeItems(player, MORDEOS_TALON.getId(), -1);
 							giveItems(player, BRAKIS_REMAINS1, 1);
 							if (hasQuestItems(player, HERMODTS_REMAINS1, KIRUNAS_REMAINS1, TONARS_REMAINS1)) {
 								qs.setCond(2);
@@ -483,4 +468,4 @@ public final class Q00233_TestOfTheWarSpirit extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00234_FatesWhisper/Q00234_FatesWhisper.java b/src/main/java/com/l2jserver/datapack/quests/Q00234_FatesWhisper/Q00234_FatesWhisper.java
index dba0c7a68f..5c9bdd5433 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00234_FatesWhisper/Q00234_FatesWhisper.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00234_FatesWhisper/Q00234_FatesWhisper.java
@@ -18,16 +18,17 @@
  */
 package com.l2jserver.datapack.quests.Q00234_FatesWhisper;
 
-import static com.l2jserver.gameserver.network.NpcStringId.WHO_DARES_TO_TRY_AND_STEAL_MY_NOBLE_BLOOD;
-
 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;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
 import com.l2jserver.gameserver.network.serverpackets.NpcSay;
 
+import static com.l2jserver.gameserver.network.NpcStringId.WHO_DARES_TO_TRY_AND_STEAL_MY_NOBLE_BLOOD;
+
 /**
  * Fate's Whisper (234)
  * @author Zealar
@@ -44,9 +45,6 @@ public final class Q00234_FatesWhisper extends Quest {
 	private static final int CHEST_OF_GOLKONDA = 31029;
 	private static final int CHEST_OF_HALLATE = 31030;
 	// Quest Items
-	private static final int Q_BLOODY_FABRIC_Q0234 = 14361;
-	private static final int Q_WHITE_FABRIC_Q0234 = 14362;
-	private static final int Q_STAR_OF_DESTINY = 5011;
 	private static final int Q_PIPETTE_KNIFE = 4665;
 	private static final int Q_REIRIAS_SOULORB = 4666;
 	private static final int Q_INFERNIUM_SCEPTER_1 = 4667;
@@ -56,6 +54,9 @@ public final class Q00234_FatesWhisper extends Quest {
 	private static final int Q_MAESTRO_REORINS_MOLD = 4671;
 	private static final int Q_INFERNIUM_VARNISH = 4672;
 	private static final int Q_RED_PIPETTE_KNIFE = 4673;
+	private static final int Q_STAR_OF_DESTINY = 5011;
+	private static final int Q_WHITE_FABRIC_Q0234 = 14362;
+	private static final QuestItemChanceHolder Q_BLOODY_FABRIC_Q0234 = new QuestItemChanceHolder(14361);
 	// Other Items
 	private static final int CRYSTAL_B = 1460;
 	// Monsters
@@ -149,7 +150,7 @@ public final class Q00234_FatesWhisper extends Quest {
 		
 		addSpawnId(COFFER_OF_THE_DEAD, CHEST_OF_KERNON, CHEST_OF_HALLATE, CHEST_OF_GOLKONDA);
 		addAttackId(BAIUM);
-		registerQuestItems(Q_BLOODY_FABRIC_Q0234, Q_WHITE_FABRIC_Q0234, Q_PIPETTE_KNIFE, Q_REIRIAS_SOULORB, Q_INFERNIUM_SCEPTER_1, Q_INFERNIUM_SCEPTER_2, Q_INFERNIUM_SCEPTER_3, Q_MAESTRO_REORINS_HAMMER, Q_MAESTRO_REORINS_MOLD, Q_INFERNIUM_VARNISH, Q_RED_PIPETTE_KNIFE);
+		registerQuestItems(Q_BLOODY_FABRIC_Q0234.getId(), Q_WHITE_FABRIC_Q0234, Q_PIPETTE_KNIFE, Q_REIRIAS_SOULORB, Q_INFERNIUM_SCEPTER_1, Q_INFERNIUM_SCEPTER_2, Q_INFERNIUM_SCEPTER_3, Q_MAESTRO_REORINS_HAMMER, Q_MAESTRO_REORINS_MOLD, Q_INFERNIUM_VARNISH, Q_RED_PIPETTE_KNIFE);
 	}
 	
 	@Override
@@ -207,7 +208,7 @@ public final class Q00234_FatesWhisper extends Quest {
 					return "30833-01.html";
 				}
 				
-				final long bloodyFabricCount = qs.getQuestItemsCount(Q_BLOODY_FABRIC_Q0234);
+				final long bloodyFabricCount = qs.getQuestItemsCount(Q_BLOODY_FABRIC_Q0234.getId());
 				final long whiteFabricCount = qs.getQuestItemsCount(Q_WHITE_FABRIC_Q0234);
 				final long whiteBloodyFabricCount = bloodyFabricCount + whiteFabricCount;
 				if (qs.isMemoState(8) && !qs.hasQuestItems(Q_RED_PIPETTE_KNIFE) && (whiteBloodyFabricCount <= 0)) {
@@ -226,7 +227,7 @@ public final class Q00234_FatesWhisper extends Quest {
 				}
 				if (qs.isMemoState(8) && !qs.hasQuestItems(Q_RED_PIPETTE_KNIFE) && (bloodyFabricCount >= 30) && (whiteBloodyFabricCount >= 30)) {
 					qs.giveItems(Q_MAESTRO_REORINS_MOLD, 1);
-					qs.takeItems(Q_BLOODY_FABRIC_Q0234, -1);
+					qs.takeItems(Q_BLOODY_FABRIC_Q0234.getId(), -1);
 					qs.setMemoState(9);
 					qs.setCond(10, true);
 					qs.showQuestionMark(234);
@@ -234,7 +235,7 @@ public final class Q00234_FatesWhisper extends Quest {
 				}
 				if (qs.isMemoState(8) && !qs.hasQuestItems(Q_RED_PIPETTE_KNIFE) && (whiteBloodyFabricCount < 30) && (whiteBloodyFabricCount > 0)) {
 					qs.giveItems(Q_WHITE_FABRIC_Q0234, 30 - whiteFabricCount);
-					qs.takeItems(Q_BLOODY_FABRIC_Q0234, -1);
+					qs.takeItems(Q_BLOODY_FABRIC_Q0234.getId(), -1);
 					return "30833-03e.html";
 				}
 				if (qs.getMemoState() >= 9) {
@@ -897,23 +898,15 @@ public final class Q00234_FatesWhisper extends Quest {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
 		if (qs != null) {
 			switch (npc.getId()) {
-				case PLATINUM_TRIBE_GRUNT:
-				case PLATINUM_TRIBE_ARCHER:
-				case PLATINUM_TRIBE_WARRIOR:
-				case PLATINUM_TRIBE_SHAMAN:
-				case PLATINUM_TRIBE_LORD:
-				case GUARDIAN_ANGEL:
-				case SEAL_ANGEL:
-				case SEAL_ANGEL_R: {
-					giveItemRandomly(qs.getPlayer(), npc, Q_BLOODY_FABRIC_Q0234, 1, 0, 1, false);
+				case PLATINUM_TRIBE_GRUNT, PLATINUM_TRIBE_ARCHER, PLATINUM_TRIBE_WARRIOR, PLATINUM_TRIBE_SHAMAN, PLATINUM_TRIBE_LORD, GUARDIAN_ANGEL, SEAL_ANGEL, SEAL_ANGEL_R -> {
+					giveItemRandomly(qs.getPlayer(), npc, Q_BLOODY_FABRIC_Q0234, false);
 					qs.takeItems(Q_WHITE_FABRIC_Q0234, 1);
-					if (qs.getQuestItemsCount(Q_BLOODY_FABRIC_Q0234) >= 29) {
+					if (qs.getQuestItemsCount(Q_BLOODY_FABRIC_Q0234.getId()) >= 29) {
 						qs.setCond(9, true);
 						qs.showQuestionMark(234);
 					} else {
 						qs.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
 					}
-					break;
 				}
 			}
 			
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00235_MimirsElixir/Q00235_MimirsElixir.java b/src/main/java/com/l2jserver/datapack/quests/Q00235_MimirsElixir/Q00235_MimirsElixir.java
index ebe20b3dad..1f4d9b6318 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00235_MimirsElixir/Q00235_MimirsElixir.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00235_MimirsElixir/Q00235_MimirsElixir.java
@@ -18,18 +18,18 @@
  */
 package com.l2jserver.datapack.quests.Q00235_MimirsElixir;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.enums.Race;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.QuestItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
 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.network.serverpackets.SocialAction;
 
+import java.util.Map;
+
 /**
  * Mimir's Elixir (235)
  * @author Adry_85
@@ -42,30 +42,33 @@ public final class Q00235_MimirsElixir extends Quest {
 	// Items
 	private static final int STAR_OF_DESTINY = 5011;
 	private static final int MAGISTERS_MIXING_STONE = 5905;
-	private static final int BLOOD_FIRE = 6318;
 	private static final int MIMIRS_ELIXIR = 6319;
 	private static final int PURE_SILVER = 6320;
 	private static final int TRUE_GOLD = 6321;
-	private static final int SAGES_STONE = 6322;
+	private static final QuestItemChanceHolder BLOOD_FIRE = new QuestItemChanceHolder(6318, 1L);
+	private static final QuestItemChanceHolder SAGES_STONE = new QuestItemChanceHolder(6322, 1L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20965, SAGES_STONE) // chimera_piece
+			.addSingleDrop(21090, BLOOD_FIRE) // bloody_guardian
+			.build();
 	// Reward
 	private static final int ENCHANT_WEAPON_A = 729;
 	// Misc
 	private static final int MIN_LEVEL = 75;
+	private static final Map<Integer, Integer> ITEM_STATE = Map.of(
+			SAGES_STONE.getId(), 4,
+			BLOOD_FIRE.getId(), 1
+	);
 	// Skill
 	private static final SkillHolder QUEST_MIMIRS_ELIXIR = new SkillHolder(4339);
-	// Mobs
-	private static final Map<Integer, QuestItemHolder> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20965, new QuestItemHolder(SAGES_STONE, 4, 1)); // chimera_piece
-		MOBS.put(21090, new QuestItemHolder(BLOOD_FIRE, 7, 1)); // bloody_guardian
-	}
-	
+
 	public Q00235_MimirsElixir() {
 		super(235, Q00235_MimirsElixir.class.getSimpleName(), "Mimir's Elixir");
 		addStartNpc(LADD);
 		addTalkId(LADD, JOAN, ALCHEMISTS_MIXING_URN);
-		addKillId(MOBS.keySet());
-		registerQuestItems(MAGISTERS_MIXING_STONE, BLOOD_FIRE, MIMIRS_ELIXIR, TRUE_GOLD, SAGES_STONE);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(MAGISTERS_MIXING_STONE, BLOOD_FIRE.getId(), MIMIRS_ELIXIR, TRUE_GOLD, SAGES_STONE.getId());
 	}
 	
 	@Override
@@ -146,9 +149,9 @@ public final class Q00235_MimirsElixir extends Quest {
 				break;
 			}
 			case "30718-06.html": {
-				if (st.isMemoState(4) && hasQuestItems(player, SAGES_STONE)) {
+				if (st.isMemoState(4) && hasQuestItems(player, SAGES_STONE.getId())) {
 					giveItems(player, TRUE_GOLD, 1);
-					takeItems(player, SAGES_STONE, -1);
+					takeItems(player, SAGES_STONE.getId(), -1);
 					st.setMemoState(5);
 					st.setCond(5, true);
 					htmltext = event;
@@ -179,14 +182,14 @@ public final class Q00235_MimirsElixir extends Quest {
 			}
 			case "BLOOD_FIRE": {
 				if (st.isMemoState(7)) {
-					htmltext = ((hasQuestItems(player, BLOOD_FIRE)) ? "31149-08.html" : "31149-03.html");
+					htmltext = ((hasQuestItems(player, BLOOD_FIRE.getId())) ? "31149-08.html" : "31149-03.html");
 				}
 				break;
 			}
 			case "31149-11.html": {
-				if (st.isMemoState(7) && hasQuestItems(player, BLOOD_FIRE, PURE_SILVER, TRUE_GOLD)) {
+				if (st.isMemoState(7) && hasQuestItems(player, BLOOD_FIRE.getId(), PURE_SILVER, TRUE_GOLD)) {
 					giveItems(player, MIMIRS_ELIXIR, 1);
-					takeItems(player, -1, BLOOD_FIRE, PURE_SILVER, TRUE_GOLD);
+					takeItems(player, -1, BLOOD_FIRE.getId(), PURE_SILVER, TRUE_GOLD);
 					st.setMemoState(8);
 					st.setCond(8, true);
 					htmltext = event;
@@ -198,19 +201,19 @@ public final class Q00235_MimirsElixir extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		if (getRandom(5) == 0) {
-			L2PcInstance luckyPlayer = getRandomPartyMember(player, npc);
+			L2PcInstance luckyPlayer = getRandomPartyMember(killer, npc);
 			if (luckyPlayer != null) {
-				final QuestItemHolder item = MOBS.get(npc.getId());
-				if (giveItemRandomly(luckyPlayer, npc, item.getId(), item.getCount(), item.getCount(), 1.0, true)) {
-					final QuestState st = luckyPlayer.getQuestState(getName());
-					st.setMemoState(item.getChance());
-					st.setCond(item.getChance());
+				final QuestState st = luckyPlayer.getQuestState(getName());
+				if (giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+					int itemId = DROPLIST.get(npc).item().getId();
+					st.setMemoState(ITEM_STATE.get(itemId));
+					st.setCond(ITEM_STATE.get(itemId));
 				}
 			}
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00252_ItSmellsDelicious/Q00252_ItSmellsDelicious.java b/src/main/java/com/l2jserver/datapack/quests/Q00252_ItSmellsDelicious/Q00252_ItSmellsDelicious.java
index ac151331f0..066e34a2aa 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00252_ItSmellsDelicious/Q00252_ItSmellsDelicious.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00252_ItSmellsDelicious/Q00252_ItSmellsDelicious.java
@@ -20,6 +20,7 @@ package com.l2jserver.datapack.quests.Q00252_ItSmellsDelicious;
 
 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;
 
@@ -32,8 +33,8 @@ public class Q00252_ItSmellsDelicious extends Quest {
 	// NPC
 	public static final int STAN = 30200;
 	// Items
-	public static final int DIARY = 15500;
-	public static final int COOKBOOK_PAGE = 15501;
+	private static final QuestItemChanceHolder DIARY = new QuestItemChanceHolder(15500, 59.9, 10L);
+	private static final QuestItemChanceHolder COOKBOOK_PAGE = new QuestItemChanceHolder(15501, 36L, 5L);
 	// Monsters
 	private static final int[] MOBS = {
 		22786,
@@ -41,11 +42,6 @@ public class Q00252_ItSmellsDelicious extends Quest {
 		22788
 	};
 	private static final int CHEF = 18908;
-	// Misc
-	private static final double DIARY_CHANCE = 0.599;
-	private static final int DIARY_MAX_COUNT = 10;
-	private static final double COOKBOOK_PAGE_CHANCE = 0.36;
-	private static final int COOKBOOK_PAGE_MAX_COUNT = 5;
 	
 	public Q00252_ItSmellsDelicious() {
 		super(252, Q00252_ItSmellsDelicious.class.getSimpleName(), "It Smells Delicious!");
@@ -53,7 +49,7 @@ public class Q00252_ItSmellsDelicious extends Quest {
 		addTalkId(STAN);
 		addKillId(CHEF);
 		addKillId(MOBS);
-		registerQuestItems(DIARY, COOKBOOK_PAGE);
+		registerQuestItems(DIARY.getId(), COOKBOOK_PAGE.getId());
 	}
 	
 	@Override
@@ -89,24 +85,17 @@ public class Q00252_ItSmellsDelicious extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs;
-		if (npc.getId() == CHEF) // only the killer gets quest items from the chef
-		{
+		if (npc.getId() == CHEF) { // only the killer gets quest items from the chef
 			qs = getQuestState(killer, false);
 			if ((qs != null) && qs.isCond(1)) {
-				if (giveItemRandomly(killer, npc, COOKBOOK_PAGE, 1, COOKBOOK_PAGE_MAX_COUNT, COOKBOOK_PAGE_CHANCE, true)) {
-					if (hasMaxDiaries(qs)) {
-						qs.setCond(2, true);
-					}
+				if (giveItemRandomly(qs.getPlayer(), npc, COOKBOOK_PAGE, true) && hasItemsAtLimit(qs.getPlayer(), DIARY)) {
+					qs.setCond(2);
 				}
 			}
 		} else {
 			qs = getRandomPartyMemberState(killer, 1, 3, npc);
-			if (qs != null) {
-				if (giveItemRandomly(qs.getPlayer(), npc, DIARY, 1, DIARY_MAX_COUNT, DIARY_CHANCE, true)) {
-					if (hasMaxCookbookPages(qs)) {
-						qs.setCond(2, true);
-					}
-				}
+			if (qs != null && giveItemRandomly(qs.getPlayer(), npc, DIARY, true) && hasItemsAtLimit(qs.getPlayer(), COOKBOOK_PAGE)) {
+				qs.setCond(2);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -114,7 +103,7 @@ public class Q00252_ItSmellsDelicious extends Quest {
 	
 	@Override
 	public boolean checkPartyMember(QuestState qs, L2Npc npc) {
-		return !hasMaxDiaries(qs);
+		return !hasItemsAtLimit(qs.getPlayer(), DIARY);
 	}
 	
 	@Override
@@ -130,7 +119,7 @@ public class Q00252_ItSmellsDelicious extends Quest {
 					htmltext = "30200-06.html";
 					break;
 				case 2:
-					if (hasMaxDiaries(qs) && hasMaxCookbookPages(qs)) {
+					if (hasItemsAtLimit(qs.getPlayer(), DIARY, COOKBOOK_PAGE)) {
 						htmltext = "30200-07.html";
 					}
 					break;
@@ -140,12 +129,4 @@ public class Q00252_ItSmellsDelicious extends Quest {
 		}
 		return htmltext;
 	}
-	
-	private static boolean hasMaxDiaries(QuestState qs) {
-		return (getQuestItemsCount(qs.getPlayer(), DIARY) >= DIARY_MAX_COUNT);
-	}
-	
-	private static boolean hasMaxCookbookPages(QuestState qs) {
-		return (getQuestItemsCount(qs.getPlayer(), COOKBOOK_PAGE) >= COOKBOOK_PAGE_MAX_COUNT);
-	}
 }
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00261_CollectorsDream/Q00261_CollectorsDream.java b/src/main/java/com/l2jserver/datapack/quests/Q00261_CollectorsDream/Q00261_CollectorsDream.java
index d4d9e4eb4e..31336f7594 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00261_CollectorsDream/Q00261_CollectorsDream.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00261_CollectorsDream/Q00261_CollectorsDream.java
@@ -20,6 +20,7 @@ package com.l2jserver.datapack.quests.Q00261_CollectorsDream;
 
 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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -42,10 +43,9 @@ public final class Q00261_CollectorsDream extends Quest {
 		20466, // Pincer Spider
 	};
 	// Item
-	private static final int SPIDER_LEG = 1087;
+	private static final QuestItemChanceHolder SPIDER_LEG = new QuestItemChanceHolder(1087, 8L);
 	// Misc
 	private static final int MIN_LVL = 15;
-	private static final int MAX_LEG_COUNT = 8;
 	// Message
 	private static final ExShowScreenMessage MESSAGE = new ExShowScreenMessage(NpcStringId.LAST_DUTY_COMPLETE_N_GO_FIND_THE_NEWBIE_GUIDE, 2, 5000);
 	
@@ -54,7 +54,7 @@ public final class Q00261_CollectorsDream extends Quest {
 		addStartNpc(ALSHUPES);
 		addTalkId(ALSHUPES);
 		addKillId(MONSTERS);
-		registerQuestItems(SPIDER_LEG);
+		registerQuestItems(SPIDER_LEG.getId());
 	}
 	
 	@Override
@@ -71,7 +71,7 @@ public final class Q00261_CollectorsDream extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getQuestState(killer, false);
 		if ((st != null) && st.isCond(1) && Util.checkIfInRange(1500, npc, killer, true)) {
-			if (st.giveItemRandomly(SPIDER_LEG, 1, MAX_LEG_COUNT, 1, true)) {
+			if (giveItemRandomly(st.getPlayer(), npc, SPIDER_LEG, true)) {
 				st.setCond(2);
 			}
 		}
@@ -94,7 +94,7 @@ public final class Q00261_CollectorsDream extends Quest {
 						break;
 					}
 					case 2: {
-						if (st.getQuestItemsCount(SPIDER_LEG) >= MAX_LEG_COUNT) {
+						if (hasItemsAtLimit(player, SPIDER_LEG)) {
 							giveNewbieReward(player);
 							st.giveAdena(1000, true);
 							st.addExpAndSp(2000, 0);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00262_TradeWithTheIvoryTower/Q00262_TradeWithTheIvoryTower.java b/src/main/java/com/l2jserver/datapack/quests/Q00262_TradeWithTheIvoryTower/Q00262_TradeWithTheIvoryTower.java
index 0f7f443bf9..1f6dcb2f00 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00262_TradeWithTheIvoryTower/Q00262_TradeWithTheIvoryTower.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00262_TradeWithTheIvoryTower/Q00262_TradeWithTheIvoryTower.java
@@ -18,15 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00262_TradeWithTheIvoryTower;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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,24 +34,22 @@ public final class Q00262_TradeWithTheIvoryTower extends Quest {
 	// NPCs
 	private static final int VOLLODOS = 30137;
 	// Items
-	private static final int SPORE_SAC = 707;
+	private static final QuestItemChanceHolder SPORE_SAC = new QuestItemChanceHolder(707, 10L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20007, SPORE_SAC, 30.0) // Green Fungus
+			.addSingleDrop(20400, SPORE_SAC, 40.0) // Blood Fungus
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 8;
 	private static final int REQUIRED_ITEM_COUNT = 10;
-	// Monsters
-	private static final Map<Integer, Integer> MOBS_SAC = new HashMap<>();
-	
-	static {
-		MOBS_SAC.put(20007, 3); // Green Fungus
-		MOBS_SAC.put(20400, 4); // Blood Fungus
-	}
-	
+
 	public Q00262_TradeWithTheIvoryTower() {
 		super(262, Q00262_TradeWithTheIvoryTower.class.getSimpleName(), "Trade With The Ivory Tower");
 		addStartNpc(VOLLODOS);
 		addTalkId(VOLLODOS);
-		addKillId(MOBS_SAC.keySet());
-		registerQuestItems(SPORE_SAC);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(SPORE_SAC.getId());
 	}
 	
 	@Override
@@ -70,20 +64,9 @@ public final class Q00262_TradeWithTheIvoryTower extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember == null) {
-			return super.onKill(npc, player, isSummon);
-		}
-		
-		final QuestState st = getQuestState(partyMember, false);
-		double chance = MOBS_SAC.get(npc.getId()) * rates().getRateQuestDrop();
-		if (getRandom(10) < chance) {
-			st.rewardItems(SPORE_SAC, 1);
-			if (st.getQuestItemsCount(SPORE_SAC) >= REQUIRED_ITEM_COUNT) {
-				st.setCond(2, true);
-			} else {
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null && giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			st.setCond(2);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
@@ -100,13 +83,13 @@ public final class Q00262_TradeWithTheIvoryTower extends Quest {
 			case State.STARTED: {
 				switch (st.getCond()) {
 					case 1: {
-						if (st.getQuestItemsCount(SPORE_SAC) < REQUIRED_ITEM_COUNT) {
+						if (!hasItemsAtLimit(st.getPlayer(), SPORE_SAC)) {
 							htmltext = "30137-04.html";
 						}
 						break;
 					}
 					case 2: {
-						if (st.getQuestItemsCount(SPORE_SAC) >= REQUIRED_ITEM_COUNT) {
+						if (hasItemsAtLimit(st.getPlayer(), SPORE_SAC)) {
 							htmltext = "30137-05.html";
 							st.giveAdena(3000, true);
 							st.exitQuest(true, true);
@@ -119,4 +102,4 @@ public final class Q00262_TradeWithTheIvoryTower extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00264_KeenClaws/Q00264_KeenClaws.java b/src/main/java/com/l2jserver/datapack/quests/Q00264_KeenClaws/Q00264_KeenClaws.java
index ec55a11224..0fe7a8449c 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00264_KeenClaws/Q00264_KeenClaws.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00264_KeenClaws/Q00264_KeenClaws.java
@@ -18,19 +18,19 @@
  */
 package com.l2jserver.datapack.quests.Q00264_KeenClaws;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-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.ItemHolder;
+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;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * Keen Claws (264)
  * @author xban1x
@@ -39,33 +39,32 @@ public final class Q00264_KeenClaws extends Quest {
 	// Npc
 	private static final int PAINT = 30136;
 	// Item
-	private static final int WOLF_CLAW = 1367;
-	// Monsters
-	private static final Map<Integer, List<ItemHolder>> MONSTER_CHANCES = new HashMap<>();
+	private static final QuestItemChanceHolder WOLF_CLAW = new QuestItemChanceHolder(1367, 50L);
+	// Droplists
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addGroupedDropForSingleItem(20003, WOLF_CLAW, 50.0)
+				.withAmount(2, 50.0).orElse(8)
+			.addSingleDrop(20456, WOLF_CLAW, 125.0)
+			.build();
 	// Rewards
-	private static final Map<Integer, List<ItemHolder>> REWARDS = new HashMap<>();
+	private static final Map<Integer, List<ItemHolder>> REWARDS = Map.of(
+			1, List.of(new ItemHolder(4633, 1)),
+			2, List.of(new ItemHolder(57, 2000)),
+			5, List.of(new ItemHolder(5140, 1)),
+			8, List.of(new ItemHolder(735, 1), new ItemHolder(57, 50)),
+			11, List.of(new ItemHolder(737, 1)),
+			14, List.of(new ItemHolder(734, 1)),
+			17, List.of(new ItemHolder(35, 1), new ItemHolder(57, 50))
+	);
 	// Misc
 	private static final int MIN_LVL = 3;
-	private static final int WOLF_CLAW_COUNT = 50;
-	static {
-		MONSTER_CHANCES.put(20003, Arrays.asList(new ItemHolder(2, 25), new ItemHolder(8, 50)));
-		MONSTER_CHANCES.put(20456, Arrays.asList(new ItemHolder(1, 80), new ItemHolder(2, 100)));
-		
-		REWARDS.put(1, Arrays.asList(new ItemHolder(4633, 1)));
-		REWARDS.put(2, Arrays.asList(new ItemHolder(57, 2000)));
-		REWARDS.put(5, Arrays.asList(new ItemHolder(5140, 1)));
-		REWARDS.put(8, Arrays.asList(new ItemHolder(735, 1), new ItemHolder(57, 50)));
-		REWARDS.put(11, Arrays.asList(new ItemHolder(737, 1)));
-		REWARDS.put(14, Arrays.asList(new ItemHolder(734, 1)));
-		REWARDS.put(17, Arrays.asList(new ItemHolder(35, 1), new ItemHolder(57, 50)));
-	}
 	
 	public Q00264_KeenClaws() {
 		super(264, Q00264_KeenClaws.class.getSimpleName(), "Keen Claws");
 		addStartNpc(PAINT);
 		addTalkId(PAINT);
-		addKillId(MONSTER_CHANCES.keySet());
-		registerQuestItems(WOLF_CLAW);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(WOLF_CLAW.getId());
 	}
 	
 	@Override
@@ -82,14 +81,8 @@ public final class Q00264_KeenClaws extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getQuestState(killer, false);
 		if ((st != null) && st.isCond(1)) {
-			final int random = getRandom(100);
-			for (ItemHolder drop : MONSTER_CHANCES.get(npc.getId())) {
-				if (random < drop.getCount()) {
-					if (st.giveItemRandomly(WOLF_CLAW, drop.getId(), WOLF_CLAW_COUNT, 1, true)) {
-						st.setCond(2);
-					}
-					break;
-				}
+			if (giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+				st.setCond(2);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -111,7 +104,7 @@ public final class Q00264_KeenClaws extends Quest {
 						break;
 					}
 					case 2: {
-						if (st.getQuestItemsCount(WOLF_CLAW) >= WOLF_CLAW_COUNT) {
+						if (hasItemsAtLimit(st.getPlayer(), WOLF_CLAW)) {
 							final int chance = getRandom(17);
 							for (Map.Entry<Integer, List<ItemHolder>> reward : REWARDS.entrySet()) {
 								if (chance < reward.getKey()) {
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00266_PleasOfPixies/Q00266_PleasOfPixies.java b/src/main/java/com/l2jserver/datapack/quests/Q00266_PleasOfPixies/Q00266_PleasOfPixies.java
index ddaab072fb..04a612f625 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00266_PleasOfPixies/Q00266_PleasOfPixies.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00266_PleasOfPixies/Q00266_PleasOfPixies.java
@@ -18,20 +18,20 @@
  */
 package com.l2jserver.datapack.quests.Q00266_PleasOfPixies;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import com.l2jserver.gameserver.enums.Race;
 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.ItemHolder;
+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;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * Pleas of Pixies (266)
  * @author xban1x
@@ -40,23 +40,20 @@ public final class Q00266_PleasOfPixies extends Quest {
 	// NPC
 	private static final int PIXY_MURIKA = 31852;
 	// Items
-	private static final int PREDATORS_FANG = 1334;
-	// Monsters
-	private static final Map<Integer, List<ItemHolder>> MONSTERS = new HashMap<>();
-	static {
-		MONSTERS.put(20537, Arrays.asList(new ItemHolder(10, 2))); // Elder Red Keltir
-		MONSTERS.put(20525, Arrays.asList(new ItemHolder(5, 2), new ItemHolder(10, 3))); // Gray Wolf
-		MONSTERS.put(20534, Arrays.asList(new ItemHolder(6, 1))); // Red Keltir
-		MONSTERS.put(20530, Arrays.asList(new ItemHolder(8, 1))); // Young Red Keltir
-	}
+	private static final QuestItemChanceHolder PREDATORS_FANG = new QuestItemChanceHolder(1334, 100L);
+	// Droplists
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20537, PREDATORS_FANG, 2) // Elder Red Keltir
+			.addSingleDrop(20525, PREDATORS_FANG, 250.0) // Gray Wolf
+			.addSingleDrop(20534, PREDATORS_FANG, 60.0) // Red Keltir
+			.addSingleDrop(20530, PREDATORS_FANG, 80.0) // Young Red Keltir
+			.build();
 	// Rewards
-	private static final Map<Integer, List<ItemHolder>> REWARDS = new HashMap<>();
-	static {
-		REWARDS.put(0, Arrays.asList(new ItemHolder(1337, 1), new ItemHolder(3032, 1))); // Emerald, Recipe: Spiritshot D
-		REWARDS.put(1, Arrays.asList(new ItemHolder(2176, 1), new ItemHolder(1338, 1))); // Recipe: Leather Boots, Blue Onyx
-		REWARDS.put(2, Arrays.asList(new ItemHolder(1339, 1), new ItemHolder(1061, 1))); // Onyx, Greater Healing Potion
-		REWARDS.put(3, Arrays.asList(new ItemHolder(1336, 1), new ItemHolder(1060, 1))); // Glass Shard, Lesser Healing Potion
-	}
+	private static final Map<Integer, List<ItemHolder>> REWARDS = Map.of(
+		0, List.of(new ItemHolder(1337, 1), new ItemHolder(3032, 1)), // Emerald, Recipe: Spiritshot D
+		1, List.of(new ItemHolder(2176, 1), new ItemHolder(1338, 1)), // Recipe: Leather Boots, Blue Onyx
+		2, List.of(new ItemHolder(1339, 1), new ItemHolder(1061, 1)), // Onyx, Greater Healing Potion
+		3, List.of(new ItemHolder(1336, 1), new ItemHolder(1060, 1))); // Glass Shard, Lesser Healing Potion
 	// Misc
 	private static final int MIN_LVL = 3;
 	
@@ -64,8 +61,8 @@ public final class Q00266_PleasOfPixies extends Quest {
 		super(266, Q00266_PleasOfPixies.class.getSimpleName(), "Pleas of Pixies");
 		addStartNpc(PIXY_MURIKA);
 		addTalkId(PIXY_MURIKA);
-		addKillId(MONSTERS.keySet());
-		registerQuestItems(PREDATORS_FANG);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(PREDATORS_FANG.getId());
 	}
 	
 	@Override
@@ -82,14 +79,8 @@ public final class Q00266_PleasOfPixies extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getQuestState(killer, false);
 		if ((st != null) && st.isCond(1)) {
-			final int chance = getRandom(10);
-			for (ItemHolder mob : MONSTERS.get(npc.getId())) {
-				if (chance < mob.getId()) {
-					if (st.giveItemRandomly(npc, PREDATORS_FANG, mob.getCount(), 100, 1.0, true)) {
-						st.setCond(2);
-					}
-					break;
-				}
+			if (giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+				st.setCond(2);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -117,7 +108,7 @@ public final class Q00266_PleasOfPixies extends Quest {
 						break;
 					}
 					case 2: {
-						if (st.getQuestItemsCount(PREDATORS_FANG) >= 100) {
+						if (hasItemsAtLimit(player, PREDATORS_FANG)) {
 							final int chance = getRandom(100);
 							int reward;
 							if (chance < 2) {
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00269_InventionAmbition/Q00269_InventionAmbition.java b/src/main/java/com/l2jserver/datapack/quests/Q00269_InventionAmbition/Q00269_InventionAmbition.java
index 709c44f88b..3911fa9a0f 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00269_InventionAmbition/Q00269_InventionAmbition.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00269_InventionAmbition/Q00269_InventionAmbition.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00269_InventionAmbition;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -35,18 +33,17 @@ public final class Q00269_InventionAmbition extends Quest {
 	private static final int INVENTOR_MARU = 32486;
 	// Items
 	private static final int ENERGY_ORE = 10866;
-	// Monsters
-	private static final Map<Integer, Double> MONSTERS = new HashMap<>();
-	static {
-		MONSTERS.put(21124, 0.46); // Red Eye Barbed Bat
-		MONSTERS.put(21125, 0.48); // Northern Trimden
-		MONSTERS.put(21126, 0.5); // Kerope Werewolf
-		MONSTERS.put(21127, 0.64); // Northern Goblin
-		MONSTERS.put(21128, 0.66); // Spine Golem
-		MONSTERS.put(21129, 0.68); // Kerope Werewolf Chief
-		MONSTERS.put(21130, 0.76); // Northern Goblin Leader
-		MONSTERS.put(21131, 0.78); // Enchanted Spine Golem
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21124, ENERGY_ORE, 46.0) // Red Eye Barbed Bat
+			.addSingleDrop(21125, ENERGY_ORE, 48.0) // Northern Trimden
+			.addSingleDrop(21126, ENERGY_ORE, 50.0) // Kerope Werewolf
+			.addSingleDrop(21127, ENERGY_ORE, 64.0) // Northern Goblin
+			.addSingleDrop(21128, ENERGY_ORE, 66.0) // Spine Golem
+			.addSingleDrop(21129, ENERGY_ORE, 68.0) // Kerope Werewolf Chief
+			.addSingleDrop(21130, ENERGY_ORE, 76.0) // Northern Goblin Leader
+			.addSingleDrop(21131, ENERGY_ORE, 78.0) // Enchanted Spine Golem
+			.build();
 	// Misc
 	private static final int MIN_LVL = 18;
 	
@@ -54,7 +51,7 @@ public final class Q00269_InventionAmbition extends Quest {
 		super(269, Q00269_InventionAmbition.class.getSimpleName(), "Invention Ambition");
 		addStartNpc(INVENTOR_MARU);
 		addTalkId(INVENTOR_MARU);
-		addKillId(MONSTERS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(ENERGY_ORE);
 	}
 	
@@ -97,7 +94,7 @@ public final class Q00269_InventionAmbition extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (st != null) {
-			giveItemRandomly(st.getPlayer(), npc, ENERGY_ORE, 1, 0, MONSTERS.get(npc.getId()), true);
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00275_DarkWingedSpies/Q00275_DarkWingedSpies.java b/src/main/java/com/l2jserver/datapack/quests/Q00275_DarkWingedSpies/Q00275_DarkWingedSpies.java
index a6562ad7c3..fefe79f7b7 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00275_DarkWingedSpies/Q00275_DarkWingedSpies.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00275_DarkWingedSpies/Q00275_DarkWingedSpies.java
@@ -24,11 +24,14 @@ import com.l2jserver.gameserver.model.actor.L2Attackable;
 import com.l2jserver.gameserver.model.actor.L2Character;
 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;
 import com.l2jserver.gameserver.model.quest.State;
 import com.l2jserver.gameserver.util.Util;
 
+import static com.l2jserver.gameserver.model.quest.QuestDroplist.singleDropItem;
+
 /**
  * Dark Winged Spies (275)
  * @author xban1x
@@ -37,15 +40,14 @@ public final class Q00275_DarkWingedSpies extends Quest {
 	// Npc
 	private static final int NERUGA_CHIEF_TANTUS = 30567;
 	// Items
-	private static final int DARKWING_BAT_FANG = 1478;
 	private static final int VARANGKAS_PARASITE = 1479;
+	private static final QuestItemChanceHolder DARKWING_BAT_FANG = new QuestItemChanceHolder(1478, 70L);
 	// Monsters
 	private static final int DARKWING_BAT = 20316;
 	private static final int VARANGKAS_TRACKER = 27043;
 	// Misc
 	private static final int MIN_LVL = 11;
 	private static final int FANG_PRICE = 60;
-	private static final int MAX_BAT_FANG_COUNT = 70;
 	
 	public Q00275_DarkWingedSpies() {
 		super(275, Q00275_DarkWingedSpies.class.getSimpleName(), "Dark Winged Spies");
@@ -53,7 +55,7 @@ public final class Q00275_DarkWingedSpies extends Quest {
 		addTalkId(NERUGA_CHIEF_TANTUS);
 		addKillId(DARKWING_BAT, VARANGKAS_TRACKER);
 		addSeeCreatureId(VARANGKAS_TRACKER);
-		registerQuestItems(DARKWING_BAT_FANG, VARANGKAS_PARASITE);
+		registerQuestItems(DARKWING_BAT_FANG.getId(), VARANGKAS_PARASITE);
 	}
 	
 	@Override
@@ -71,26 +73,24 @@ public final class Q00275_DarkWingedSpies extends Quest {
 		final QuestState st = getQuestState(killer, false);
 		
 		if ((st != null) && st.isCond(1) && Util.checkIfInRange(1500, npc, killer, true)) {
-			final long count = st.getQuestItemsCount(DARKWING_BAT_FANG);
-			
+			final long count = st.getQuestItemsCount(DARKWING_BAT_FANG.getId());
+
 			switch (npc.getId()) {
-				case DARKWING_BAT: {
-					if (st.giveItemRandomly(DARKWING_BAT_FANG, 1, MAX_BAT_FANG_COUNT, 1, true)) {
+				case DARKWING_BAT -> {
+					if (giveItemRandomly(st.getPlayer(), npc, DARKWING_BAT_FANG, true)) {
 						st.setCond(2);
 					} else if ((count > 10) && (count < 66) && (getRandom(100) < 10)) {
 						st.addSpawn(VARANGKAS_TRACKER);
 						st.giveItems(VARANGKAS_PARASITE, 1);
 					}
-					break;
 				}
-				case VARANGKAS_TRACKER: {
+				case VARANGKAS_TRACKER -> {
 					if ((count < 66) && st.hasQuestItems(VARANGKAS_PARASITE)) {
-						if (st.giveItemRandomly(DARKWING_BAT_FANG, 5, MAX_BAT_FANG_COUNT, 1, true)) {
+						if (giveItemRandomly(st.getPlayer(), npc, singleDropItem(DARKWING_BAT_FANG, 5L), DARKWING_BAT_FANG.getLimit(), true)) {
 							st.setCond(2);
 						}
 						st.takeItems(VARANGKAS_PARASITE, -1);
 					}
-					break;
 				}
 			}
 		}
@@ -124,8 +124,8 @@ public final class Q00275_DarkWingedSpies extends Quest {
 						break;
 					}
 					case 2: {
-						final long count = st.getQuestItemsCount(DARKWING_BAT_FANG);
-						if (count >= MAX_BAT_FANG_COUNT) {
+						final long count = st.getQuestItemsCount(DARKWING_BAT_FANG.getId());
+						if (count >= DARKWING_BAT_FANG.getLimit()) {
 							st.giveAdena(count * FANG_PRICE, true);
 							st.exitQuest(true, true);
 							htmltext = "30567-05.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00276_TotemOfTheHestui/Q00276_TotemOfTheHestui.java b/src/main/java/com/l2jserver/datapack/quests/Q00276_TotemOfTheHestui/Q00276_TotemOfTheHestui.java
index 9f49f05b32..0511a2e405 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00276_TotemOfTheHestui/Q00276_TotemOfTheHestui.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00276_TotemOfTheHestui/Q00276_TotemOfTheHestui.java
@@ -18,19 +18,19 @@
  */
 package com.l2jserver.datapack.quests.Q00276_TotemOfTheHestui;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import com.l2jserver.datapack.quests.Q00261_CollectorsDream.Q00261_CollectorsDream;
 import com.l2jserver.gameserver.enums.Race;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 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.util.Util;
 
+import java.util.List;
+
 /**
  * Totem of the Hestui (276)
  * @author xban1x
@@ -40,7 +40,7 @@ public final class Q00276_TotemOfTheHestui extends Quest {
 	private static final int TANAPI = 30571;
 	// Items
 	private static final int KASHA_PARASITE = 1480;
-	private static final int KASHA_CRYSTAL = 1481;
+	private static final QuestItemChanceHolder KASHA_CRYSTAL = new QuestItemChanceHolder(1481, 1L);
 	// Monsters
 	private static final int KASHA_BEAR = 20479;
 	private static final int KASHA_BEAR_TOTEM = 27044;
@@ -50,23 +50,20 @@ public final class Q00276_TotemOfTheHestui extends Quest {
 		1500,
 	};
 	// Misc
-	private static final List<ItemHolder> SPAWN_CHANCES = new ArrayList<>();
+	private static final List<ItemHolder> SPAWN_CHANCES = List.of(
+		new ItemHolder(79, 100),
+		new ItemHolder(69, 20),
+		new ItemHolder(59, 15),
+		new ItemHolder(49, 10),
+		new ItemHolder(39, 2));
 	private static final int MIN_LVL = 15;
 	
-	static {
-		SPAWN_CHANCES.add(new ItemHolder(79, 100));
-		SPAWN_CHANCES.add(new ItemHolder(69, 20));
-		SPAWN_CHANCES.add(new ItemHolder(59, 15));
-		SPAWN_CHANCES.add(new ItemHolder(49, 10));
-		SPAWN_CHANCES.add(new ItemHolder(39, 2));
-	}
-	
 	public Q00276_TotemOfTheHestui() {
 		super(276, Q00276_TotemOfTheHestui.class.getSimpleName(), "Totem of the Hestui");
 		addStartNpc(TANAPI);
 		addTalkId(TANAPI);
 		addKillId(KASHA_BEAR, KASHA_BEAR_TOTEM);
-		registerQuestItems(KASHA_PARASITE, KASHA_CRYSTAL);
+		registerQuestItems(KASHA_PARASITE, KASHA_CRYSTAL.getId());
 	}
 	
 	@Override
@@ -84,7 +81,7 @@ public final class Q00276_TotemOfTheHestui extends Quest {
 		final QuestState st = getQuestState(killer, false);
 		if ((st != null) && st.isCond(1) && Util.checkIfInRange(1500, killer, npc, true)) {
 			switch (npc.getId()) {
-				case KASHA_BEAR: {
+				case KASHA_BEAR -> {
 					final long chance1 = st.getQuestItemsCount(KASHA_PARASITE);
 					final int chance2 = getRandom(100);
 					boolean chance3 = true;
@@ -97,15 +94,13 @@ public final class Q00276_TotemOfTheHestui extends Quest {
 						}
 					}
 					if (chance3) {
-						st.giveItemRandomly(KASHA_PARASITE, 1, 0, 1, true);
+						giveItemRandomly(st.getPlayer(), npc, KASHA_PARASITE, true);
 					}
-					break;
 				}
-				case KASHA_BEAR_TOTEM: {
-					if (st.giveItemRandomly(KASHA_CRYSTAL, 1, 1, 1, true)) {
+				case KASHA_BEAR_TOTEM -> {
+					if (giveItemRandomly(st.getPlayer(), npc, KASHA_CRYSTAL, true)) {
 						st.setCond(2);
 					}
-					break;
 				}
 			}
 		}
@@ -128,7 +123,7 @@ public final class Q00276_TotemOfTheHestui extends Quest {
 						break;
 					}
 					case 2: {
-						if (st.hasQuestItems(KASHA_CRYSTAL)) {
+						if (st.hasQuestItems(KASHA_CRYSTAL.getId())) {
 							Q00261_CollectorsDream.giveNewbieReward(player);
 							for (int reward : REWARDS) {
 								st.rewardItems(reward, 1);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00278_HomeSecurity/Q00278_HomeSecurity.java b/src/main/java/com/l2jserver/datapack/quests/Q00278_HomeSecurity/Q00278_HomeSecurity.java
index e9fc91d9b6..66c3222b61 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00278_HomeSecurity/Q00278_HomeSecurity.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00278_HomeSecurity/Q00278_HomeSecurity.java
@@ -20,9 +20,12 @@ package com.l2jserver.datapack.quests.Q00278_HomeSecurity;
 
 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;
 
+import static com.l2jserver.gameserver.model.quest.QuestDroplist.singleDropItem;
+
 /**
  * Home Security (278)
  * @author malyelfik
@@ -36,16 +39,14 @@ public class Q00278_HomeSecurity extends Quest {
 		18907
 	};
 	// Item
-	private static final int SEL_MAHUM_MANE = 15531;
-	// Misc
-	private static final int SEL_MAHUM_MANE_COUNT = 300;
+	private static final QuestItemChanceHolder SEL_MAHUM_MANE = new QuestItemChanceHolder(15531, 300L);
 	
 	public Q00278_HomeSecurity() {
 		super(278, Q00278_HomeSecurity.class.getSimpleName(), "Home Security");
 		addStartNpc(TUNATUN);
 		addTalkId(TUNATUN);
 		addKillId(MONSTER);
-		registerQuestItems(SEL_MAHUM_MANE);
+		registerQuestItems(SEL_MAHUM_MANE.getId());
 	}
 	
 	@Override
@@ -105,25 +106,20 @@ public class Q00278_HomeSecurity extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final QuestState st = getRandomPartyMemberState(player, 1, 3, npc);
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		final QuestState st = getRandomPartyMemberState(killer, 1, 3, npc);
 		if (st != null) {
 			switch (npc.getId()) {
-				case 18905: // Farm Ravager (Crazy)
-				{
-					final int itemCount = ((getRandom(1000) < 486) ? getRandom(6) + 1 : getRandom(5) + 1);
-					if (st.giveItemRandomly(npc, SEL_MAHUM_MANE, itemCount, SEL_MAHUM_MANE_COUNT, 1.0, true)) {
-						st.setCond(2, true);
+				case 18905 -> { // Farm Ravager (Crazy)
+					final long itemCount = ((getRandom(1000) < 486) ? getRandom(6) + 1 : getRandom(5) + 1);
+					if (giveItemRandomly(st.getPlayer(), npc, singleDropItem(SEL_MAHUM_MANE, itemCount), SEL_MAHUM_MANE.getLimit(), true)) {
+						st.setCond(2);
 					}
-					break;
 				}
-				case 18906: // Farm Bandit
-				case 18907: // Beast Devourer
-				{
-					if (st.giveItemRandomly(npc, SEL_MAHUM_MANE, 1, SEL_MAHUM_MANE_COUNT, 0.85, true)) {
-						st.setCond(2, true);
+				case 18906, 18907 -> { // Farm Bandit, Beast Devourer
+					if (giveItemRandomly(st.getPlayer(), npc, singleDropItem(SEL_MAHUM_MANE, 85.0), SEL_MAHUM_MANE.getLimit(), true)) {
+						st.setCond(2);
 					}
-					break;
 				}
 			}
 		}
@@ -137,9 +133,9 @@ public class Q00278_HomeSecurity extends Quest {
 		if (st.isCreated()) {
 			htmltext = "31537-01.htm";
 		} else if (st.isStarted()) {
-			if (st.isCond(1) || (getQuestItemsCount(player, SEL_MAHUM_MANE) < SEL_MAHUM_MANE_COUNT)) {
+			if (st.isCond(1) || !hasItemsAtLimit(player, SEL_MAHUM_MANE)) {
 				htmltext = "31537-06.html";
-			} else if (st.isCond(2) && (getQuestItemsCount(player, SEL_MAHUM_MANE) >= SEL_MAHUM_MANE_COUNT)) {
+			} else if (st.isCond(2) && hasItemsAtLimit(player, SEL_MAHUM_MANE)) {
 				htmltext = "31537-05.html";
 			}
 		}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00279_TargetOfOpportunity/Q00279_TargetOfOpportunity.java b/src/main/java/com/l2jserver/datapack/quests/Q00279_TargetOfOpportunity/Q00279_TargetOfOpportunity.java
index 049ef1fb53..5ae31abcf2 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00279_TargetOfOpportunity/Q00279_TargetOfOpportunity.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00279_TargetOfOpportunity/Q00279_TargetOfOpportunity.java
@@ -18,14 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00279_TargetOfOpportunity;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-import java.util.Arrays;
-
 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;
 
@@ -36,35 +34,31 @@ import com.l2jserver.gameserver.model.quest.State;
 public final class Q00279_TargetOfOpportunity extends Quest {
 	// NPCs
 	private static final int JERIAN = 32302;
-	private static final int[] MONSTERS = {
-		22373,
-		22374,
-		22375,
-		22376
-	};
 	// Items
-	private static final int[] SEAL_COMPONENTS = {
-		15517,
-		15518,
-		15519,
-		15520
-	};
-	private static final int[] SEAL_BREAKERS = {
-		15515,
-		15516
-	};
-	
+	private static final int SEAL_BREAKER_5TH_FLOOR = 15515;
+	private static final int SEAL_BREAKER_10TH_FLOOR = 15516;
+	private static final QuestItemChanceHolder SEAL_COMPONENTS_PART1 = new QuestItemChanceHolder(15517, 31.1, 1L);
+	private static final QuestItemChanceHolder SEAL_COMPONENTS_PART2 = new QuestItemChanceHolder(15518, 31.1, 1L);
+	private static final QuestItemChanceHolder SEAL_COMPONENTS_PART3 = new QuestItemChanceHolder(15519, 31.1, 1L);
+	private static final QuestItemChanceHolder SEAL_COMPONENTS_PART4 = new QuestItemChanceHolder(15520, 31.1, 1L);
+	// Droplist
+	private static final QuestDroplist DROPLIST_SEAL_COMPONENTS = QuestDroplist.builder()
+			.addSingleDrop(22373, SEAL_COMPONENTS_PART1) // Cosmic Scout
+			.addSingleDrop(22374, SEAL_COMPONENTS_PART2) // Cosmic Watcher
+			.addSingleDrop(22375, SEAL_COMPONENTS_PART3) // Cosmic Priest
+			.addSingleDrop(22376, SEAL_COMPONENTS_PART4) // Cosmic Lord
+			.build();
+
 	public Q00279_TargetOfOpportunity() {
 		super(279, Q00279_TargetOfOpportunity.class.getSimpleName(), "Target of Opportunity");
 		addStartNpc(JERIAN);
 		addTalkId(JERIAN);
-		addKillId(MONSTERS);
-		registerQuestItems(SEAL_COMPONENTS);
+		addKillId(DROPLIST_SEAL_COMPONENTS.getNpcIds());
+		registerQuestItems(SEAL_COMPONENTS_PART1.getId(), SEAL_COMPONENTS_PART2.getId(), SEAL_COMPONENTS_PART3.getId(), SEAL_COMPONENTS_PART4.getId());
 	}
 	
 	@Override
 	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) {
-		String htmltext = event;
 		final QuestState st = getQuestState(player, false);
 		if ((st == null) || (player.getLevel() < 82)) {
 			return getNoQuestMsg(player);
@@ -73,30 +67,25 @@ public final class Q00279_TargetOfOpportunity extends Quest {
 		if (event.equalsIgnoreCase("32302-05.html")) {
 			st.startQuest();
 			st.set("progress", "1");
-		} else if (event.equalsIgnoreCase("32302-08.html") && (st.getInt("progress") == 1) && st.hasQuestItems(SEAL_COMPONENTS[0]) && st.hasQuestItems(SEAL_COMPONENTS[1]) && st.hasQuestItems(SEAL_COMPONENTS[2]) && st.hasQuestItems(SEAL_COMPONENTS[3])) {
-			st.giveItems(SEAL_BREAKERS[0], 1);
-			st.giveItems(SEAL_BREAKERS[1], 1);
+		} else if (event.equalsIgnoreCase("32302-08.html") && (st.getInt("progress") == 1)
+				&& hasQuestItems(st.getPlayer(), SEAL_COMPONENTS_PART1.getId(), SEAL_COMPONENTS_PART2.getId(), SEAL_COMPONENTS_PART3.getId(), SEAL_COMPONENTS_PART4.getId())) {
+			st.giveItems(SEAL_BREAKER_5TH_FLOOR, 1);
+			st.giveItems(SEAL_BREAKER_10TH_FLOOR, 1);
 			st.exitQuest(true, true);
 		}
-		return htmltext;
+		return event;
 	}
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		L2PcInstance pl = getRandomPartyMember(player, "progress", "1");
-		final int idx = Arrays.binarySearch(MONSTERS, npc.getId());
-		if ((pl == null) || (idx < 0)) {
-			return null;
-		}
-		
-		final QuestState st = getQuestState(pl, false);
-		if (getRandom(1000) < (int) (311 * rates().getRateQuestDrop())) {
-			if (!st.hasQuestItems(SEAL_COMPONENTS[idx])) {
-				st.giveItems(SEAL_COMPONENTS[idx], 1);
-				if (haveAllExceptThis(st, idx)) {
+		if (pl != null) {
+			final QuestState st = getQuestState(pl, false);
+			if (giveItemRandomly(st.getPlayer(), npc, DROPLIST_SEAL_COMPONENTS.get(npc), false)) {
+				if (hasItemsAtLimit(st.getPlayer(), SEAL_COMPONENTS_PART1, SEAL_COMPONENTS_PART2, SEAL_COMPONENTS_PART3, SEAL_COMPONENTS_PART4)) {
 					st.setCond(2, true);
 				} else {
-					st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
+					playSound(st.getPlayer(), Sound.ITEMSOUND_QUEST_ITEMGET);
 				}
 			}
 		}
@@ -110,21 +99,8 @@ public final class Q00279_TargetOfOpportunity extends Quest {
 		if (st.getState() == State.CREATED) {
 			htmltext = (player.getLevel() >= 82) ? "32302-01.htm" : "32302-02.html";
 		} else if ((st.getState() == State.STARTED) && (st.getInt("progress") == 1)) {
-			htmltext = (st.hasQuestItems(SEAL_COMPONENTS[0]) && st.hasQuestItems(SEAL_COMPONENTS[1]) && st.hasQuestItems(SEAL_COMPONENTS[2]) && st.hasQuestItems(SEAL_COMPONENTS[3])) ? "32302-07.html" : "32302-06.html";
+			htmltext = hasQuestItems(st.getPlayer(), SEAL_COMPONENTS_PART1.getId(), SEAL_COMPONENTS_PART2.getId(), SEAL_COMPONENTS_PART3.getId(), SEAL_COMPONENTS_PART4.getId()) ? "32302-07.html" : "32302-06.html";
 		}
 		return htmltext;
 	}
-	
-	private static boolean haveAllExceptThis(QuestState st, int idx) {
-		for (int i = 0; i < SEAL_COMPONENTS.length; i++) {
-			if (i == idx) {
-				continue;
-			}
-			
-			if (!st.hasQuestItems(SEAL_COMPONENTS[i])) {
-				return false;
-			}
-		}
-		return true;
-	}
 }
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00280_TheFoodChain/Q00280_TheFoodChain.java b/src/main/java/com/l2jserver/datapack/quests/Q00280_TheFoodChain/Q00280_TheFoodChain.java
index d7d3b7d08a..6308d18d9c 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00280_TheFoodChain/Q00280_TheFoodChain.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00280_TheFoodChain/Q00280_TheFoodChain.java
@@ -18,15 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00280_TheFoodChain;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
+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;
 import com.l2jserver.gameserver.util.Util;
@@ -40,29 +36,19 @@ public final class Q00280_TheFoodChain extends Quest {
 	private static final int BIXON = 32175;
 	// Items
 	private static final int GREY_KELTIR_TOOTH = 9809;
-	private static final int BLACK_WOLF_TOOTH = 9810;
-	// Monsters
-	private static final Map<Integer, Integer> MONSTER_ITEM = new HashMap<>();
-	private static final Map<Integer, List<ItemHolder>> MONSTER_CHANCE = new HashMap<>();
-	static {
-		MONSTER_ITEM.put(22229, GREY_KELTIR_TOOTH);
-		MONSTER_ITEM.put(22230, GREY_KELTIR_TOOTH);
-		MONSTER_ITEM.put(22231, GREY_KELTIR_TOOTH);
-		MONSTER_ITEM.put(22232, BLACK_WOLF_TOOTH);
-		MONSTER_ITEM.put(22233, BLACK_WOLF_TOOTH);
-		MONSTER_CHANCE.put(22229, Arrays.asList(new ItemHolder(1000, 1)));
-		MONSTER_CHANCE.put(22230, Arrays.asList(new ItemHolder(500, 1), new ItemHolder(1000, 2)));
-		MONSTER_CHANCE.put(22231, Arrays.asList(new ItemHolder(1000, 2)));
-		MONSTER_CHANCE.put(22232, Arrays.asList(new ItemHolder(1000, 3)));
-		MONSTER_CHANCE.put(22233, Arrays.asList(new ItemHolder(500, 3), new ItemHolder(1000, 4)));
-	}
+	private static final QuestItemChanceHolder BLACK_WOLF_TOOTH = new QuestItemChanceHolder(9810, 3L, 0L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22229, GREY_KELTIR_TOOTH)
+			.addSingleDrop(22230, GREY_KELTIR_TOOTH, 150.0)
+			.addSingleDrop(22231, GREY_KELTIR_TOOTH, 2L)
+			.addSingleDrop(22232, BLACK_WOLF_TOOTH)
+			.addGroupedDropForSingleItem(22233, BLACK_WOLF_TOOTH, 100.0)
+				.withAmount(4, 50.0).orElse(1)
+			.build();
 	// Rewards
 	private static final int[] REWARDS = new int[] {
-		28,
-		35,
-		41,
-		48,
-		116,
+		28, 35, 41, 48, 116,
 	};
 	// Misc
 	private static final int MIN_LVL = 3;
@@ -72,8 +58,8 @@ public final class Q00280_TheFoodChain extends Quest {
 		super(280, Q00280_TheFoodChain.class.getSimpleName(), "The Food Chain");
 		addStartNpc(BIXON);
 		addTalkId(BIXON);
-		addKillId(MONSTER_ITEM.keySet());
-		registerQuestItems(GREY_KELTIR_TOOTH, BLACK_WOLF_TOOTH);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(GREY_KELTIR_TOOTH, BLACK_WOLF_TOOTH.getId());
 	}
 	
 	@Override
@@ -93,13 +79,14 @@ public final class Q00280_TheFoodChain extends Quest {
 			case "32175-06.html": {
 				if (hasAtLeastOneQuestItem(player, getRegisteredItemIds())) {
 					final long greyTeeth = st.getQuestItemsCount(GREY_KELTIR_TOOTH);
-					final long blackTeeth = st.getQuestItemsCount(BLACK_WOLF_TOOTH);
+					final long blackTeeth = st.getQuestItemsCount(BLACK_WOLF_TOOTH.getId());
 					st.giveAdena(2 * (greyTeeth + blackTeeth), true);
-					takeItems(player, -1, GREY_KELTIR_TOOTH, BLACK_WOLF_TOOTH);
+					takeItems(player, -1, GREY_KELTIR_TOOTH, BLACK_WOLF_TOOTH.getId());
 					htmltext = event;
 				} else {
 					htmltext = "32175-07.html";
 				}
+				break;
 			}
 			case "32175-08.html": {
 				htmltext = event;
@@ -112,13 +99,13 @@ public final class Q00280_TheFoodChain extends Quest {
 			}
 			case "32175-11.html": {
 				final long greyTeeth = st.getQuestItemsCount(GREY_KELTIR_TOOTH);
-				final long blackTeeth = st.getQuestItemsCount(BLACK_WOLF_TOOTH);
+				final long blackTeeth = st.getQuestItemsCount(BLACK_WOLF_TOOTH.getId());
 				if ((greyTeeth + blackTeeth) >= TEETH_COUNT) {
 					if (greyTeeth >= TEETH_COUNT) {
 						st.takeItems(GREY_KELTIR_TOOTH, TEETH_COUNT);
 					} else {
 						st.takeItems(GREY_KELTIR_TOOTH, greyTeeth);
-						st.takeItems(BLACK_WOLF_TOOTH, TEETH_COUNT - greyTeeth);
+						st.takeItems(BLACK_WOLF_TOOTH.getId(), TEETH_COUNT - greyTeeth);
 					}
 					st.rewardItems(REWARDS[getRandom(5)], 1);
 					htmltext = event;
@@ -134,14 +121,8 @@ public final class Q00280_TheFoodChain extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getQuestState(killer, false);
-		if ((st != null) && Util.checkIfInRange(1500, npc, killer, true)) {
-			final int chance = getRandom(1000);
-			for (ItemHolder dropChance : MONSTER_CHANCE.get(npc.getId())) {
-				if (chance < dropChance.getId()) {
-					st.giveItemRandomly(MONSTER_ITEM.get(npc.getId()), dropChance.getCount(), 0, 1, true);
-					break;
-				}
-			}
+		if ((st != null) && Util.checkIfInRange(1500, npc, st.getPlayer(), true)) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -166,4 +147,4 @@ public final class Q00280_TheFoodChain extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00283_TheFewTheProudTheBrave/Q00283_TheFewTheProudTheBrave.java b/src/main/java/com/l2jserver/datapack/quests/Q00283_TheFewTheProudTheBrave/Q00283_TheFewTheProudTheBrave.java
index 12b150959c..02b7754176 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00283_TheFewTheProudTheBrave/Q00283_TheFewTheProudTheBrave.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00283_TheFewTheProudTheBrave/Q00283_TheFewTheProudTheBrave.java
@@ -21,6 +21,7 @@ package com.l2jserver.datapack.quests.Q00283_TheFewTheProudTheBrave;
 import com.l2jserver.datapack.quests.Q00261_CollectorsDream.Q00261_CollectorsDream;
 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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -33,7 +34,7 @@ public final class Q00283_TheFewTheProudTheBrave extends Quest {
 	// NPC
 	private static final int PERWAN = 32133;
 	// Item
-	private static final int CRIMSON_SPIDER_CLAW = 9747;
+	private static final QuestItemChanceHolder CRIMSON_SPIDER_CLAW = new QuestItemChanceHolder(9747, 60.0);
 	// Monster
 	private static final int CRIMSON_SPIDER = 22244;
 	// Misc
@@ -46,7 +47,7 @@ public final class Q00283_TheFewTheProudTheBrave extends Quest {
 		addKillId(CRIMSON_SPIDER);
 		addStartNpc(PERWAN);
 		addTalkId(PERWAN);
-		registerQuestItems(CRIMSON_SPIDER_CLAW);
+		registerQuestItems(CRIMSON_SPIDER_CLAW.getId());
 	}
 	
 	@Override
@@ -68,10 +69,10 @@ public final class Q00283_TheFewTheProudTheBrave extends Quest {
 				break;
 			}
 			case "32133-08.html": {
-				if (st.hasQuestItems(CRIMSON_SPIDER_CLAW)) {
-					final long claws = st.getQuestItemsCount(CRIMSON_SPIDER_CLAW);
+				if (st.hasQuestItems(CRIMSON_SPIDER_CLAW.getId())) {
+					final long claws = st.getQuestItemsCount(CRIMSON_SPIDER_CLAW.getId());
 					st.giveAdena((claws * CLAW_PRICE) + ((claws >= 10) ? BONUS : 0), true);
-					st.takeItems(CRIMSON_SPIDER_CLAW, -1);
+					st.takeItems(CRIMSON_SPIDER_CLAW.getId(), -1);
 					Q00261_CollectorsDream.giveNewbieReward(player);
 					htmltext = event;
 				} else {
@@ -92,7 +93,7 @@ public final class Q00283_TheFewTheProudTheBrave extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (st != null) {
-			st.giveItemRandomly(npc, CRIMSON_SPIDER_CLAW, 1, 0, 0.6, true);
+			giveItemRandomly(st.getPlayer(), npc, CRIMSON_SPIDER_CLAW, true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -107,7 +108,7 @@ public final class Q00283_TheFewTheProudTheBrave extends Quest {
 				break;
 			}
 			case State.STARTED: {
-				htmltext = st.hasQuestItems(CRIMSON_SPIDER_CLAW) ? "32133-04.html" : "32133-05.html";
+				htmltext = st.hasQuestItems(CRIMSON_SPIDER_CLAW.getId()) ? "32133-04.html" : "32133-05.html";
 				break;
 			}
 		}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00284_MuertosFeather/Q00284_MuertosFeather.java b/src/main/java/com/l2jserver/datapack/quests/Q00284_MuertosFeather/Q00284_MuertosFeather.java
index 80ebb6a9b7..4cb11ee36a 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00284_MuertosFeather/Q00284_MuertosFeather.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00284_MuertosFeather/Q00284_MuertosFeather.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00284_MuertosFeather;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -35,16 +33,15 @@ public final class Q00284_MuertosFeather extends Quest {
 	private static final int TREVOR = 32166;
 	// Item
 	private static final int MUERTOS_FEATHER = 9748;
-	// Monsters
-	private static final Map<Integer, Double> MOB_DROP_CHANCE = new HashMap<>();
-	static {
-		MOB_DROP_CHANCE.put(22239, 0.500); // Muertos Guard
-		MOB_DROP_CHANCE.put(22240, 0.533); // Muertos Scout
-		MOB_DROP_CHANCE.put(22242, 0.566); // Muertos Warrior
-		MOB_DROP_CHANCE.put(22243, 0.600); // Muertos Captain
-		MOB_DROP_CHANCE.put(22245, 0.633); // Muertos Lieutenant
-		MOB_DROP_CHANCE.put(22246, 0.633); // Muertos Commander
-	}
+	// Droplists
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22239, MUERTOS_FEATHER, 50.0)
+			.addSingleDrop(22240, MUERTOS_FEATHER, 53.3)
+			.addSingleDrop(22242, MUERTOS_FEATHER, 56.6)
+			.addSingleDrop(22243, MUERTOS_FEATHER, 60.0)
+			.addSingleDrop(22245, MUERTOS_FEATHER, 63.3)
+			.addSingleDrop(22246, MUERTOS_FEATHER, 63.3)
+			.build();
 	// Misc
 	private static final int MIN_LVL = 11;
 	
@@ -52,7 +49,7 @@ public final class Q00284_MuertosFeather extends Quest {
 		super(284, Q00284_MuertosFeather.class.getSimpleName(), "Muertos Feather");
 		addStartNpc(TREVOR);
 		addTalkId(TREVOR);
-		addKillId(MOB_DROP_CHANCE.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(MUERTOS_FEATHER);
 	}
 	
@@ -96,7 +93,7 @@ public final class Q00284_MuertosFeather extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 1, 3, npc);
 		if (qs != null) {
-			giveItemRandomly(qs.getPlayer(), npc, MUERTOS_FEATHER, 1, 0, MOB_DROP_CHANCE.get(npc.getId()), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00286_FabulousFeathers/Q00286_FabulousFeathers.java b/src/main/java/com/l2jserver/datapack/quests/Q00286_FabulousFeathers/Q00286_FabulousFeathers.java
index 207e7c5a74..7a18c10d7e 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00286_FabulousFeathers/Q00286_FabulousFeathers.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00286_FabulousFeathers/Q00286_FabulousFeathers.java
@@ -18,13 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00286_FabulousFeathers;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
+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;
 
 /**
@@ -35,16 +33,15 @@ public final class Q00286_FabulousFeathers extends Quest {
 	// NPC
 	private static final int ERINU = 32164;
 	// Item
-	private static final ItemHolder COMMANDERS_FEATHER = new ItemHolder(9746, 80);
-	// Monsters
-	private static final Map<Integer, Double> MOB_DROP_CHANCES = new HashMap<>();
-	static {
-		MOB_DROP_CHANCES.put(22251, 0.748); // Shady Muertos Captain
-		MOB_DROP_CHANCES.put(22253, 0.772); // Shady Muertos Warrior
-		MOB_DROP_CHANCES.put(22254, 0.772); // Shady Muertos Archer
-		MOB_DROP_CHANCES.put(22255, 0.796); // Shady Muertos Commander
-		MOB_DROP_CHANCES.put(22256, 0.952); // Shady Muertos Wizard
-	}
+	private static final QuestItemChanceHolder COMMANDERS_FEATHER = new QuestItemChanceHolder(9746, 80L);
+	// Droplists
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22251, COMMANDERS_FEATHER, 74.8) // Shady Muertos Captain
+			.addSingleDrop(22253, COMMANDERS_FEATHER, 77.2) // Shady Muertos Warrior
+			.addSingleDrop(22254, COMMANDERS_FEATHER, 77.2) // Shady Muertos Archer
+			.addSingleDrop(22255, COMMANDERS_FEATHER, 79.6) // Shady Muertos Commander
+			.addSingleDrop(22256, COMMANDERS_FEATHER, 95.2) // Shady Muertos Wizard
+			.build();
 	// Misc
 	private static final int MIN_LVL = 17;
 	
@@ -52,7 +49,7 @@ public final class Q00286_FabulousFeathers extends Quest {
 		super(286, Q00286_FabulousFeathers.class.getSimpleName(), "Fabulous Feathers");
 		addStartNpc(ERINU);
 		addTalkId(ERINU);
-		addKillId(MOB_DROP_CHANCES.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(COMMANDERS_FEATHER.getId());
 	}
 	
@@ -70,8 +67,8 @@ public final class Q00286_FabulousFeathers extends Quest {
 				break;
 			}
 			case "32164-06.html": {
-				if (qs.isCond(2) && hasItem(player, COMMANDERS_FEATHER)) {
-					takeItem(player, COMMANDERS_FEATHER);
+				if (qs.isCond(2) && hasItemsAtLimit(player, COMMANDERS_FEATHER)) {
+					takeItems(player, COMMANDERS_FEATHER.getId(), -1);
 					giveAdena(player, 4160, true);
 					qs.exitQuest(true, true);
 					html = event;
@@ -87,10 +84,8 @@ public final class Q00286_FabulousFeathers extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 1, 3, npc);
-		if (qs != null) {
-			if (giveItemRandomly(qs.getPlayer(), npc, COMMANDERS_FEATHER.getId(), 1, COMMANDERS_FEATHER.getCount(), MOB_DROP_CHANCES.get(npc.getId()), true)) {
-				qs.setCond(2);
-			}
+		if (qs != null && giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			qs.setCond(2);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -102,7 +97,7 @@ public final class Q00286_FabulousFeathers extends Quest {
 		if (qs.isCreated()) {
 			html = ((player.getLevel() >= MIN_LVL) ? "32164-01.htm" : "32164-02.htm");
 		} else if (qs.isStarted()) {
-			html = ((qs.isCond(2) && hasItem(player, COMMANDERS_FEATHER)) ? "32164-04.html" : "32164-05.html");
+			html = ((qs.isCond(2) && hasItemsAtLimit(player, COMMANDERS_FEATHER)) ? "32164-04.html" : "32164-05.html");
 		}
 		return html;
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00290_ThreatRemoval/Q00290_ThreatRemoval.java b/src/main/java/com/l2jserver/datapack/quests/Q00290_ThreatRemoval/Q00290_ThreatRemoval.java
index fc67dbbf48..ec10423aa8 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00290_ThreatRemoval/Q00290_ThreatRemoval.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00290_ThreatRemoval/Q00290_ThreatRemoval.java
@@ -18,16 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00290_ThreatRemoval;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00251_NoSecrets.Q00251_NoSecrets;
-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;
 
@@ -43,29 +38,23 @@ public class Q00290_ThreatRemoval extends Quest {
 	private static final int ENCHANT_ARMOR_S = 960;
 	private static final int FIRE_CRYSTAL = 9552;
 	private static final int SEL_MAHUM_ID_TAG = 15714;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.bulkAddSingleDrop(SEL_MAHUM_ID_TAG, 93.2).withNpcs(22775, 22777, 22778).build() // Sel Mahum Drill Sergeant
+			.bulkAddSingleDrop(SEL_MAHUM_ID_TAG, 36.3).withNpcs(22780, 22782, 22784).build() // Sel Mahum Recruit
+			.addSingleDrop(22776, SEL_MAHUM_ID_TAG, 39.7) // Sel Mahum Training Officer
+			.addSingleDrop(22781, SEL_MAHUM_ID_TAG, 48.3) // Sel Mahum Soldier
+			.addSingleDrop(22783, SEL_MAHUM_ID_TAG, 35.2) // Sel Mahum Soldier
+			.addSingleDrop(22785, SEL_MAHUM_ID_TAG, 16.9) // Sel Mahum Soldier
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 82;
-	
-	private static final Map<Integer, Integer> MOBS_TAG = new HashMap<>();
-	
-	static {
-		MOBS_TAG.put(22775, 932); // Sel Mahum Drill Sergeant
-		MOBS_TAG.put(22776, 397); // Sel Mahum Training Officer
-		MOBS_TAG.put(22777, 932); // Sel Mahum Drill Sergeant
-		MOBS_TAG.put(22778, 932); // Sel Mahum Drill Sergeant
-		MOBS_TAG.put(22780, 363); // Sel Mahum Recruit
-		MOBS_TAG.put(22781, 483); // Sel Mahum Soldier
-		MOBS_TAG.put(22782, 363); // Sel Mahum Recruit
-		MOBS_TAG.put(22783, 352); // Sel Mahum Soldier
-		MOBS_TAG.put(22784, 363); // Sel Mahum Recruit
-		MOBS_TAG.put(22785, 169); // Sel Mahum Soldier
-	}
-	
+
 	public Q00290_ThreatRemoval() {
 		super(290, Q00290_ThreatRemoval.class.getSimpleName(), "Threat Removal");
 		addStartNpc(PINAPS);
 		addTalkId(PINAPS);
-		addKillId(MOBS_TAG.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(SEL_MAHUM_ID_TAG);
 	}
 	
@@ -151,17 +140,9 @@ public class Q00290_ThreatRemoval extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember == null) {
-			return super.onKill(npc, player, isSummon);
-		}
-		
-		final QuestState st = getQuestState(partyMember, false);
-		int npcId = npc.getId();
-		double chance = MOBS_TAG.get(npcId) * rates().getRateQuestDrop();
-		if (getRandom(1000) < chance) {
-			st.rewardItems(SEL_MAHUM_ID_TAG, 1);
-			st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00291_RevengeOfTheRedbonnet/Q00291_RevengeOfTheRedbonnet.java b/src/main/java/com/l2jserver/datapack/quests/Q00291_RevengeOfTheRedbonnet/Q00291_RevengeOfTheRedbonnet.java
index 60cbe80283..934a970c4e 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00291_RevengeOfTheRedbonnet/Q00291_RevengeOfTheRedbonnet.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00291_RevengeOfTheRedbonnet/Q00291_RevengeOfTheRedbonnet.java
@@ -20,7 +20,7 @@ package com.l2jserver.datapack.quests.Q00291_RevengeOfTheRedbonnet;
 
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.QuestItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.util.Util;
@@ -33,7 +33,7 @@ public final class Q00291_RevengeOfTheRedbonnet extends Quest {
 	// NPC
 	private static final int MARYSE_REDBONNET = 30553;
 	// Item
-	private static final ItemHolder BLACK_WOLF_PELT = new ItemHolder(1482, 40);
+	private static final QuestItemChanceHolder BLACK_WOLF_PELT = new QuestItemChanceHolder(1482, 40L);
 	// Monster
 	private static final int BLACK_WOLF = 20317;
 	// Rewards
@@ -66,8 +66,8 @@ public final class Q00291_RevengeOfTheRedbonnet extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getQuestState(killer, false);
-		if ((qs != null) && qs.isCond(1) && Util.checkIfInRange(1500, npc, killer, true)) {
-			if (giveItemRandomly(qs.getPlayer(), npc, BLACK_WOLF_PELT.getId(), 1, BLACK_WOLF_PELT.getCount(), 1.0, true)) {
+		if ((qs != null) && qs.isCond(1) && Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
+			if (giveItemRandomly(qs.getPlayer(), npc, BLACK_WOLF_PELT, true)) {
 				qs.setCond(2);
 			}
 		}
@@ -81,8 +81,8 @@ public final class Q00291_RevengeOfTheRedbonnet extends Quest {
 		if (qs.isCreated()) {
 			html = ((player.getLevel() >= MIN_LVL) ? "30553-02.htm" : "30553-01.htm");
 		} else if (qs.isStarted()) {
-			if (qs.isCond(2) && hasItem(player, BLACK_WOLF_PELT)) {
-				takeItem(player, BLACK_WOLF_PELT);
+			if (qs.isCond(2) && hasItemsAtLimit(player, BLACK_WOLF_PELT)) {
+				takeItems(player, BLACK_WOLF_PELT.getId(), -1);
 				final int chance = getRandom(100);
 				if (chance <= 2) {
 					giveItems(player, GRANDMAS_PEARL, 1);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00292_BrigandsSweep/Q00292_BrigandsSweep.java b/src/main/java/com/l2jserver/datapack/quests/Q00292_BrigandsSweep/Q00292_BrigandsSweep.java
index 69a63113ac..ae45b84832 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00292_BrigandsSweep/Q00292_BrigandsSweep.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00292_BrigandsSweep/Q00292_BrigandsSweep.java
@@ -18,14 +18,13 @@
  */
 package com.l2jserver.datapack.quests.Q00292_BrigandsSweep;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.enums.Race;
 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;
 import com.l2jserver.gameserver.util.Util;
@@ -42,17 +41,16 @@ public final class Q00292_BrigandsSweep extends Quest {
 	private static final int GOBLIN_NECKLACE = 1483;
 	private static final int GOBLIN_PENDANT = 1484;
 	private static final int GOBLIN_LORD_PENDANT = 1485;
-	private static final int SUSPICIOUS_MEMO = 1486;
 	private static final int SUSPICIOUS_CONTRACT = 1487;
-	// Monsters
-	private static final Map<Integer, Integer> MOB_ITEM_DROP = new HashMap<>();
-	static {
-		MOB_ITEM_DROP.put(20322, GOBLIN_NECKLACE); // Goblin Brigand
-		MOB_ITEM_DROP.put(20323, GOBLIN_PENDANT); // Goblin Brigand Leader
-		MOB_ITEM_DROP.put(20324, GOBLIN_NECKLACE); // Goblin Brigand Lieutenant
-		MOB_ITEM_DROP.put(20327, GOBLIN_NECKLACE); // Goblin Snooper
-		MOB_ITEM_DROP.put(20528, GOBLIN_LORD_PENDANT); // Goblin Lord
-	}
+	private static final QuestItemChanceHolder SUSPICIOUS_MEMO = new QuestItemChanceHolder(1486, 3L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20322, GOBLIN_NECKLACE) // Goblin Brigand
+			.addSingleDrop(20323, GOBLIN_PENDANT) // Goblin Brigand Leader
+			.addSingleDrop(20324, GOBLIN_NECKLACE) // Goblin Brigand Lieutenant
+			.addSingleDrop(20327, GOBLIN_NECKLACE) // Goblin Snooper
+			.addSingleDrop(20528, GOBLIN_LORD_PENDANT) // Goblin Lord
+			.build();
 	// Misc
 	private static final int MIN_LVL = 5;
 	
@@ -60,8 +58,8 @@ public final class Q00292_BrigandsSweep extends Quest {
 		super(292, Q00292_BrigandsSweep.class.getSimpleName(), "Brigands Sweep");
 		addStartNpc(SPIRON);
 		addTalkId(SPIRON, BALANKI);
-		addKillId(MOB_ITEM_DROP.keySet());
-		registerQuestItems(GOBLIN_NECKLACE, GOBLIN_PENDANT, GOBLIN_LORD_PENDANT, SUSPICIOUS_MEMO, SUSPICIOUS_CONTRACT);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(GOBLIN_NECKLACE, GOBLIN_PENDANT, GOBLIN_LORD_PENDANT, SUSPICIOUS_MEMO.getId(), SUSPICIOUS_CONTRACT);
 	}
 	
 	@Override
@@ -100,17 +98,17 @@ public final class Q00292_BrigandsSweep 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)) {
+		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
 			final int chance = getRandom(10);
 			if (chance > 5) {
-				giveItemRandomly(killer, npc, MOB_ITEM_DROP.get(npc.getId()), 1, 0, 1.0, true);
+				giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 			} else if (qs.isCond(1) && (chance > 4) && !hasQuestItems(killer, SUSPICIOUS_CONTRACT)) {
-				final long memos = getQuestItemsCount(killer, SUSPICIOUS_MEMO);
+				final long memos = getQuestItemsCount(killer, SUSPICIOUS_MEMO.getId());
 				if (memos < 3) {
-					if (giveItemRandomly(killer, npc, SUSPICIOUS_MEMO, 1, 3, 1.0, false)) {
+					if (giveItemRandomly(qs.getPlayer(), npc, SUSPICIOUS_MEMO, false)) {
 						playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
 						giveItems(killer, SUSPICIOUS_CONTRACT, 1);
-						takeItems(killer, SUSPICIOUS_MEMO, -1);
+						takeItems(killer, SUSPICIOUS_MEMO.getId(), -1);
 						qs.setCond(2, true);
 					} else {
 						playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
@@ -144,10 +142,10 @@ public final class Q00292_BrigandsSweep extends Quest {
 								giveAdena(talker, (necklaces * 12) + (pendants * 36) + (lordPendants * 33) + (sum >= 10 ? 1000 : 0), true);
 								takeItems(talker, -1, GOBLIN_NECKLACE, GOBLIN_PENDANT, GOBLIN_LORD_PENDANT);
 							}
-							if ((sum > 0) && !hasAtLeastOneQuestItem(talker, SUSPICIOUS_MEMO, SUSPICIOUS_CONTRACT)) {
+							if ((sum > 0) && !hasAtLeastOneQuestItem(talker, SUSPICIOUS_MEMO.getId(), SUSPICIOUS_CONTRACT)) {
 								html = "30532-05.html";
 							} else {
-								final long memos = getQuestItemsCount(talker, SUSPICIOUS_MEMO);
+								final long memos = getQuestItemsCount(talker, SUSPICIOUS_MEMO.getId());
 								if ((memos == 0) && hasQuestItems(talker, SUSPICIOUS_CONTRACT)) {
 									giveAdena(talker, 1120, true);
 									takeItems(talker, -1, SUSPICIOUS_CONTRACT); // Retail like, reward is given in 2 pieces if both conditions are meet.
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00294_CovertBusiness/Q00294_CovertBusiness.java b/src/main/java/com/l2jserver/datapack/quests/Q00294_CovertBusiness/Q00294_CovertBusiness.java
index 9055d2bc74..453f9803ac 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00294_CovertBusiness/Q00294_CovertBusiness.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00294_CovertBusiness/Q00294_CovertBusiness.java
@@ -18,15 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00294_CovertBusiness;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import com.l2jserver.gameserver.enums.Race;
 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.util.Util;
 
@@ -38,13 +35,19 @@ public final class Q00294_CovertBusiness extends Quest {
 	// NPC
 	private static final int KEEF = 30534;
 	// Item
-	private static final int BAT_FANG = 1491;
-	// Monsters
-	private static final Map<Integer, List<Integer>> MONSTER_DROP_CHANCE = new HashMap<>();
-	static {
-		MONSTER_DROP_CHANCE.put(20370, Arrays.asList(6, 3, 1, -1));
-		MONSTER_DROP_CHANCE.put(20480, Arrays.asList(5, 2, -1));
-	}
+	private static final QuestItemChanceHolder BAT_FANG = new QuestItemChanceHolder(1491, 100L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addGroupedDropForSingleItem(20370, BAT_FANG, 100.0)
+				.withAmount(4, 10.0)
+				.withAmount(3, 20.0)
+				.withAmount(2, 30.0)
+				.orElse(1)
+			.addGroupedDropForSingleItem(20480, BAT_FANG, 100.0)
+				.withAmount(3, 20.0)
+				.withAmount(2, 30.0)
+				.orElse(1)
+			.build();
 	// Reward
 	private static final int RING_OF_RACCOON = 1508;
 	// Misc
@@ -54,8 +57,8 @@ public final class Q00294_CovertBusiness extends Quest {
 		super(294, Q00294_CovertBusiness.class.getSimpleName(), "Covert Business");
 		addStartNpc(KEEF);
 		addTalkId(KEEF);
-		addKillId(MONSTER_DROP_CHANCE.keySet());
-		registerQuestItems(BAT_FANG);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(BAT_FANG.getId());
 	}
 	
 	@Override
@@ -71,17 +74,9 @@ public final class Q00294_CovertBusiness extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getQuestState(killer, false);
-		if ((qs != null) && qs.isCond(1) && Util.checkIfInRange(1500, npc, killer, true)) {
-			final int chance = getRandom(10);
-			int count = 0;
-			for (int i : MONSTER_DROP_CHANCE.get(npc.getId())) {
-				count++;
-				if (chance > i) {
-					if (giveItemRandomly(killer, npc, BAT_FANG, count, 100, 1.0, true)) {
-						qs.setCond(2);
-					}
-					break;
-				}
+		if ((qs != null) && qs.isCond(1) && Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
+			if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)) {
+				qs.setCond(2);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00295_DreamingOfTheSkies/Q00295_DreamingOfTheSkies.java b/src/main/java/com/l2jserver/datapack/quests/Q00295_DreamingOfTheSkies/Q00295_DreamingOfTheSkies.java
index 8346e4d798..a8c4eb6c9e 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00295_DreamingOfTheSkies/Q00295_DreamingOfTheSkies.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00295_DreamingOfTheSkies/Q00295_DreamingOfTheSkies.java
@@ -20,10 +20,13 @@ package com.l2jserver.datapack.quests.Q00295_DreamingOfTheSkies;
 
 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;
 import com.l2jserver.gameserver.util.Util;
 
+import static com.l2jserver.gameserver.model.quest.QuestDroplist.singleDropItem;
+
 /**
  * Dreaming of the Skies (295)
  * @author xban1x
@@ -34,7 +37,7 @@ public final class Q00295_DreamingOfTheSkies extends Quest {
 	// Monster
 	private static final int MAGICAL_WEAVER = 20153;
 	// Item
-	private static final int FLOATING_STONE = 1492;
+	private static final QuestItemChanceHolder FLOATING_STONE = new QuestItemChanceHolder(1492, 50L);
 	// Reward
 	private static final int RING_OF_FIREFLY = 1509;
 	// Misc
@@ -45,7 +48,7 @@ public final class Q00295_DreamingOfTheSkies extends Quest {
 		addStartNpc(ARIN);
 		addTalkId(ARIN);
 		addKillId(MAGICAL_WEAVER);
-		registerQuestItems(FLOATING_STONE);
+		registerQuestItems(FLOATING_STONE.getId());
 	}
 	
 	@Override
@@ -62,7 +65,7 @@ public final class Q00295_DreamingOfTheSkies extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getQuestState(killer, false);
 		if ((qs != null) && qs.isCond(1) && Util.checkIfInRange(1500, npc, killer, true)) {
-			if (giveItemRandomly(killer, npc, FLOATING_STONE, (getRandom(100) > 25) ? 1 : 2, 50, 1.0, true)) {
+			if (giveItemRandomly(qs.getPlayer(), npc, singleDropItem(FLOATING_STONE, getRandom(100) > 25 ? 1L : 2L), FLOATING_STONE.getLimit(), true)) {
 				qs.setCond(2);
 			}
 		}
@@ -84,7 +87,7 @@ public final class Q00295_DreamingOfTheSkies extends Quest {
 					giveItems(talker, RING_OF_FIREFLY, 1);
 					html = "30536-05.html";
 				}
-				takeItems(talker, FLOATING_STONE, -1);
+				takeItems(talker, FLOATING_STONE.getId(), -1);
 				qs.exitQuest(true, true);
 			} else {
 				html = "30536-04.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00296_TarantulasSpiderSilk/Q00296_TarantulasSpiderSilk.java b/src/main/java/com/l2jserver/datapack/quests/Q00296_TarantulasSpiderSilk/Q00296_TarantulasSpiderSilk.java
index 94e8775351..80aefe089c 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00296_TarantulasSpiderSilk/Q00296_TarantulasSpiderSilk.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00296_TarantulasSpiderSilk/Q00296_TarantulasSpiderSilk.java
@@ -21,7 +21,10 @@ package com.l2jserver.datapack.quests.Q00296_TarantulasSpiderSilk;
 import com.l2jserver.datapack.quests.Q00281_HeadForTheHills.Q00281_HeadForTheHills;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.drops.IDropItem;
+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.util.Util;
 
@@ -34,8 +37,9 @@ public final class Q00296_TarantulasSpiderSilk extends Quest {
 	private static final int TRADER_MION = 30519;
 	private static final int DEFENDER_NATHAN = 30548;
 	// Items
-	private static final int TARANTULA_SPIDER_SILK = 1493;
-	private static final int TARANTULA_SPINNERETTE = 1494;
+	private static final QuestItemChanceHolder TARANTULA_SPIDER_SILK = new QuestItemChanceHolder(1493, 90.909);
+	private static final QuestItemChanceHolder TARANTULA_SPINNERETTE = new QuestItemChanceHolder(1494, 9.091);
+	private static final IDropItem DROP_ITEM = QuestDroplist.groupedDropItem(55.0, TARANTULA_SPIDER_SILK, TARANTULA_SPINNERETTE);
 	// Monsters
 	private static final int[] MONSTERS = new int[] {
 		20394,
@@ -50,7 +54,7 @@ public final class Q00296_TarantulasSpiderSilk extends Quest {
 		addStartNpc(TRADER_MION);
 		addTalkId(TRADER_MION, DEFENDER_NATHAN);
 		addKillId(MONSTERS);
-		registerQuestItems(TARANTULA_SPIDER_SILK, TARANTULA_SPINNERETTE);
+		registerQuestItems(TARANTULA_SPIDER_SILK.getId(), TARANTULA_SPINNERETTE.getId());
 	}
 	
 	@Override
@@ -84,9 +88,9 @@ public final class Q00296_TarantulasSpiderSilk extends Quest {
 			}
 			case "30548-03.html": {
 				if (qs.isStarted()) {
-					if (hasQuestItems(player, TARANTULA_SPINNERETTE)) {
-						giveItems(player, TARANTULA_SPIDER_SILK, (15 + getRandom(9)) * getQuestItemsCount(player, TARANTULA_SPINNERETTE));
-						takeItems(player, TARANTULA_SPINNERETTE, -1);
+					if (hasQuestItems(player, TARANTULA_SPINNERETTE.getId())) {
+						giveItems(player, TARANTULA_SPIDER_SILK, (15 + getRandom(9)) * getQuestItemsCount(player, TARANTULA_SPINNERETTE.getId()));
+						takeItems(player, TARANTULA_SPINNERETTE.getId(), -1);
 						html = event;
 					} else {
 						html = "30548-02.html";
@@ -101,13 +105,8 @@ public final class Q00296_TarantulasSpiderSilk extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getQuestState(killer, false);
-		if ((qs != null) && Util.checkIfInRange(1500, npc, killer, true)) {
-			final int chance = getRandom(100);
-			if (chance > 95) {
-				giveItemRandomly(killer, npc, TARANTULA_SPINNERETTE, 1, 0, 1, true);
-			} else if (chance > 45) {
-				giveItemRandomly(killer, npc, TARANTULA_SPIDER_SILK, 1, 0, 1, true);
-			}
+		if ((qs != null) && Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
+			giveItemRandomly(qs.getPlayer(), npc, DROP_ITEM, 0, true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -120,10 +119,10 @@ public final class Q00296_TarantulasSpiderSilk extends Quest {
 			html = (talker.getLevel() >= MIN_LVL ? "30519-02.htm" : "30519-01.htm");
 		} else if (qs.isStarted()) {
 			if (npc.getId() == TRADER_MION) {
-				final long silk = getQuestItemsCount(talker, TARANTULA_SPIDER_SILK);
+				final long silk = getQuestItemsCount(talker, TARANTULA_SPIDER_SILK.getId());
 				if (silk >= 1) {
 					giveAdena(talker, (silk * 30) + (silk >= 10 ? 2000 : 0), true);
-					takeItems(talker, TARANTULA_SPIDER_SILK, -1);
+					takeItems(talker, TARANTULA_SPIDER_SILK.getId(), -1);
 					Q00281_HeadForTheHills.giveNewbieReward(talker);// TODO: It's using wrong bitmask, need to create a general bitmask for this using EnumIntBitmask class inside Quest class for handling Quest rewards.
 					html = "30519-05.html";
 				} else {
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00298_LizardmensConspiracy/Q00298_LizardmensConspiracy.java b/src/main/java/com/l2jserver/datapack/quests/Q00298_LizardmensConspiracy/Q00298_LizardmensConspiracy.java
index b4f0637706..dad0c03997 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00298_LizardmensConspiracy/Q00298_LizardmensConspiracy.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00298_LizardmensConspiracy/Q00298_LizardmensConspiracy.java
@@ -18,13 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00298_LizardmensConspiracy;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
+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;
 
 /**
@@ -32,31 +30,30 @@ import com.l2jserver.gameserver.model.quest.QuestState;
  * @author xban1x
  */
 public final class Q00298_LizardmensConspiracy extends Quest {
+	// Misc
+	private static final int MIN_LVL = 25;
+	private static final long GEMS_LIMIT = 50L;
 	// NPCs
 	private static final int GUARD_PRAGA = 30333;
 	private static final int MAGISTER_ROHMER = 30344;
 	// Items
 	private static final int PATROLS_REPORT = 7182;
-	private static final int SHINING_GEM = 7183;
-	private static final int SHINING_RED_GEM = 7184;
-	// Monsters
-	private static final Map<Integer, ItemChanceHolder> MONSTERS = new HashMap<>();
-	static {
-		MONSTERS.put(20922, new ItemChanceHolder(SHINING_GEM, 0.49, 1));
-		MONSTERS.put(20924, new ItemChanceHolder(SHINING_GEM, 0.75, 1));
-		MONSTERS.put(20926, new ItemChanceHolder(SHINING_RED_GEM, 0.54, 1));
-		MONSTERS.put(20927, new ItemChanceHolder(SHINING_RED_GEM, 0.54, 1));
-		MONSTERS.put(20922, new ItemChanceHolder(SHINING_GEM, 0.70, 1));
-	}
-	// Misc
-	private static final int MIN_LVL = 25;
-	
+	private static final QuestItemChanceHolder SHINING_GEM = new QuestItemChanceHolder(7183, GEMS_LIMIT);
+	private static final QuestItemChanceHolder SHINING_RED_GEM = new QuestItemChanceHolder(7184, 54.0, GEMS_LIMIT);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20922, SHINING_GEM, 70.0)
+			.addSingleDrop(20924, SHINING_GEM, 75.0)
+			.addSingleDrop(20926, SHINING_RED_GEM)
+			.addSingleDrop(20927, SHINING_RED_GEM)
+			.build();
+
 	public Q00298_LizardmensConspiracy() {
 		super(298, Q00298_LizardmensConspiracy.class.getSimpleName(), "Lizardmen's Conspiracy");
 		addStartNpc(GUARD_PRAGA);
 		addTalkId(GUARD_PRAGA, MAGISTER_ROHMER);
-		addKillId(MONSTERS.keySet());
-		registerQuestItems(PATROLS_REPORT, SHINING_GEM, SHINING_RED_GEM);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(PATROLS_REPORT, SHINING_GEM.getId(), SHINING_RED_GEM.getId());
 	}
 	
 	@Override
@@ -104,11 +101,9 @@ public final class Q00298_LizardmensConspiracy extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 2, 3, npc);
 		if (qs != null) {
-			final ItemChanceHolder item = MONSTERS.get(npc.getId());
-			if (giveItemRandomly(qs.getPlayer(), npc, item.getId(), item.getCount(), 50, item.getChance(), true) //
-				&& (getQuestItemsCount(qs.getPlayer(), SHINING_GEM) >= 50) //
-				&& (getQuestItemsCount(qs.getPlayer(), SHINING_RED_GEM) >= 50)) {
-				qs.setCond(3, true);
+			if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)
+					&& hasItemsAtLimit(qs.getPlayer(), SHINING_GEM, SHINING_RED_GEM)) {
+				qs.setCond(3);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00299_GatherIngredientsForPie/Q00299_GatherIngredientsForPie.java b/src/main/java/com/l2jserver/datapack/quests/Q00299_GatherIngredientsForPie/Q00299_GatherIngredientsForPie.java
index 2c94b2307c..e0d19d867e 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00299_GatherIngredientsForPie/Q00299_GatherIngredientsForPie.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00299_GatherIngredientsForPie/Q00299_GatherIngredientsForPie.java
@@ -18,18 +18,17 @@
  */
 package com.l2jserver.datapack.quests.Q00299_GatherIngredientsForPie;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.QuestItemHolder;
+import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
+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;
 
+import java.util.List;
+
 /**
  * Gather Ingredients for Pie (299)
  * @author xban1x
@@ -39,32 +38,32 @@ public final class Q00299_GatherIngredientsForPie extends Quest {
 	private static final int LARS = 30063;
 	private static final int BRIGHT = 30466;
 	private static final int EMILLY = 30620;
-	// Monsters
-	private static final Map<Integer, Integer> MONSTERS_CHANCES = new HashMap<>(2);
 	// Items
 	private static final int FRUIT_BASKET = 7136;
 	private static final int AVELLAN_SPICE = 7137;
-	private static final int HONEY_POUCH = 7138;
+	private static final QuestItemChanceHolder HONEY_POUCH = new QuestItemChanceHolder(7138, 100L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20934, HONEY_POUCH, 1, 2, 70.0) // Wasp Worker
+			.addSingleDrop(20935, HONEY_POUCH, 1, 2, 77.0) // Wasp Leader
+			.build();
 	// Rewards
-	private static final List<QuestItemHolder> REWARDS = new ArrayList<>(5);
+	private static final List<ItemChanceHolder> REWARDS = List.of(
+			new ItemChanceHolder(57, 400, 2500), // Adena
+			new ItemChanceHolder(1865, 550, 50), // Varnish
+			new ItemChanceHolder(1870, 700, 50), // Coal
+			new ItemChanceHolder(1869, 850, 50), // Iron Ore
+			new ItemChanceHolder(1871, 1000, 50) // Charcoal
+	);
 	// Misc
 	private static final int MIN_LVL = 34;
-	static {
-		MONSTERS_CHANCES.put(20934, 700); // Wasp Worker
-		MONSTERS_CHANCES.put(20935, 770); // Wasp Leader
-		REWARDS.add(new QuestItemHolder(57, 400, 2500)); // Adena
-		REWARDS.add(new QuestItemHolder(1865, 550, 50)); // Varnish
-		REWARDS.add(new QuestItemHolder(1870, 700, 50)); // Coal
-		REWARDS.add(new QuestItemHolder(1869, 850, 50)); // Iron Ore
-		REWARDS.add(new QuestItemHolder(1871, 1000, 50)); // Charcoal
-	}
 	
 	public Q00299_GatherIngredientsForPie() {
 		super(299, Q00299_GatherIngredientsForPie.class.getSimpleName(), "Gather Ingredients for Pie");
 		addStartNpc(EMILLY);
 		addTalkId(LARS, BRIGHT, EMILLY);
-		addKillId(MONSTERS_CHANCES.keySet());
-		registerQuestItems(FRUIT_BASKET, HONEY_POUCH, AVELLAN_SPICE);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(FRUIT_BASKET, HONEY_POUCH.getId(), AVELLAN_SPICE);
 	}
 	
 	@Override
@@ -99,8 +98,8 @@ public final class Q00299_GatherIngredientsForPie extends Quest {
 				break;
 			}
 			case "30620-06.html": {
-				if (qs.isCond(2) && (getQuestItemsCount(player, HONEY_POUCH) >= 100)) {
-					takeItems(player, HONEY_POUCH, -1);
+				if (qs.isCond(2) && hasItemsAtLimit(player, HONEY_POUCH)) {
+					takeItems(player, HONEY_POUCH.getId(), -1);
 					qs.setCond(3, true);
 					html = event;
 				} else {
@@ -122,7 +121,7 @@ public final class Q00299_GatherIngredientsForPie extends Quest {
 				if (qs.isCond(6) && hasQuestItems(player, FRUIT_BASKET)) {
 					takeItems(player, FRUIT_BASKET, -1);
 					final int chance = getRandom(1000);
-					for (QuestItemHolder holder : REWARDS) {
+					for (ItemChanceHolder holder : REWARDS) {
 						if (holder.getChance() > chance) {
 							rewardItems(player, holder);
 							break;
@@ -142,10 +141,8 @@ public final class Q00299_GatherIngredientsForPie extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 1, 3, npc);
-		if ((qs != null) && (getRandom(1000) < MONSTERS_CHANCES.get(npc.getId())) && (getQuestItemsCount(killer, HONEY_POUCH) < 100)) {
-			if (giveItemRandomly(killer, npc, HONEY_POUCH, 1, 2, 100, 1, true)) {
-				qs.setCond(2);
-			}
+		if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			qs.setCond(2);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -194,7 +191,7 @@ public final class Q00299_GatherIngredientsForPie extends Quest {
 								break;
 							}
 							case 2: {
-								if (getQuestItemsCount(talker, HONEY_POUCH) >= 100) {
+								if (hasItemsAtLimit(talker, HONEY_POUCH)) {
 									html = "30620-04.html";
 								}
 								break;
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00303_CollectArrowheads/Q00303_CollectArrowheads.java b/src/main/java/com/l2jserver/datapack/quests/Q00303_CollectArrowheads/Q00303_CollectArrowheads.java
index 9a9839789d..1e2eddd550 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00303_CollectArrowheads/Q00303_CollectArrowheads.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00303_CollectArrowheads/Q00303_CollectArrowheads.java
@@ -20,6 +20,7 @@ package com.l2jserver.datapack.quests.Q00303_CollectArrowheads;
 
 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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -32,10 +33,9 @@ public final class Q00303_CollectArrowheads extends Quest {
 	// NPC
 	private static final int MINIA = 30029;
 	// Item
-	private static final int ORCISH_ARROWHEAD = 963;
+	private static final QuestItemChanceHolder ORCISH_ARROWHEAD = new QuestItemChanceHolder(963, 40.0, 10L);
 	// Misc
 	private static final int MIN_LEVEL = 10;
-	private static final int REQUIRED_ITEM_COUNT = 10;
 	// Monster
 	private static final int TUNATH_ORC_MARKSMAN = 20361;
 	
@@ -44,7 +44,7 @@ public final class Q00303_CollectArrowheads extends Quest {
 		addStartNpc(MINIA);
 		addTalkId(MINIA);
 		addKillId(TUNATH_ORC_MARKSMAN);
-		registerQuestItems(ORCISH_ARROWHEAD);
+		registerQuestItems(ORCISH_ARROWHEAD.getId());
 	}
 	
 	@Override
@@ -58,15 +58,14 @@ public final class Q00303_CollectArrowheads extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember != null) {
-			final QuestState st = getQuestState(partyMember, false);
-			if (st.giveItemRandomly(npc, ORCISH_ARROWHEAD, 1, REQUIRED_ITEM_COUNT, 0.4, true)) {
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		QuestState st = getRandomPartyMemberState(killer, 1, 1, npc);
+		if (st != null) {
+			if (giveItemRandomly(st.getPlayer(), npc, ORCISH_ARROWHEAD, true)) {
 				st.setCond(2);
 			}
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
@@ -81,13 +80,13 @@ public final class Q00303_CollectArrowheads extends Quest {
 			case State.STARTED: {
 				switch (st.getCond()) {
 					case 1: {
-						if (st.getQuestItemsCount(ORCISH_ARROWHEAD) < REQUIRED_ITEM_COUNT) {
+						if (!hasItemsAtLimit(st.getPlayer(), ORCISH_ARROWHEAD)) {
 							htmltext = "30029-05.html";
 						}
 						break;
 					}
 					case 2: {
-						if (st.getQuestItemsCount(ORCISH_ARROWHEAD) >= REQUIRED_ITEM_COUNT) {
+						if (hasItemsAtLimit(st.getPlayer(), ORCISH_ARROWHEAD)) {
 							st.giveAdena(1000, true);
 							st.addExpAndSp(2000, 0);
 							st.exitQuest(true, true);
@@ -101,4 +100,4 @@ public final class Q00303_CollectArrowheads extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00306_CrystalOfFireAndIce/Q00306_CrystalOfFireAndIce.java b/src/main/java/com/l2jserver/datapack/quests/Q00306_CrystalOfFireAndIce/Q00306_CrystalOfFireAndIce.java
index 8a14c98354..03b802904d 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00306_CrystalOfFireAndIce/Q00306_CrystalOfFireAndIce.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00306_CrystalOfFireAndIce/Q00306_CrystalOfFireAndIce.java
@@ -18,13 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00306_CrystalOfFireAndIce;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
 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;
 import com.l2jserver.gameserver.util.Util;
@@ -36,28 +33,28 @@ import com.l2jserver.gameserver.util.Util;
 public final class Q00306_CrystalOfFireAndIce extends Quest {
 	// NPC
 	private static final int KATERINA = 30004;
+	// Monsters
+	private static final int UNDINE_NOBLE = 20115;
 	// Items
 	private static final int FLAME_SHARD = 1020;
 	private static final int ICE_SHARD = 1021;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20109, FLAME_SHARD, 92.5) // Salamander
+			.addSingleDrop(20110, ICE_SHARD, 90.0) // Undine
+			.addSingleDrop(20112, FLAME_SHARD, 90.0) // Salamander Elder
+			.addSingleDrop(20113, ICE_SHARD, 92.5) // Undine Elder
+			.addSingleDrop(20114, FLAME_SHARD, 92.5) // Salamander Noble
+			.addSingleDrop(UNDINE_NOBLE, ICE_SHARD, 95.0) // Undine Noble
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 17;
-	// Monsters
-	private static final int UNDINE_NOBLE = 20115;
-	private static final Map<Integer, ItemHolder> MONSTER_DROPS = new HashMap<>();
-	static {
-		MONSTER_DROPS.put(20109, new ItemHolder(FLAME_SHARD, 925)); // Salamander
-		MONSTER_DROPS.put(20110, new ItemHolder(ICE_SHARD, 900)); // Undine
-		MONSTER_DROPS.put(20112, new ItemHolder(FLAME_SHARD, 900)); // Salamander Elder
-		MONSTER_DROPS.put(20113, new ItemHolder(ICE_SHARD, 925)); // Undine Elder
-		MONSTER_DROPS.put(20114, new ItemHolder(FLAME_SHARD, 925)); // Salamander Noble
-		MONSTER_DROPS.put(UNDINE_NOBLE, new ItemHolder(ICE_SHARD, 950)); // Undine Noble
-	}
-	
+
 	public Q00306_CrystalOfFireAndIce() {
 		super(306, Q00306_CrystalOfFireAndIce.class.getSimpleName(), "Crystals of Fire and Ice");
 		addStartNpc(KATERINA);
 		addTalkId(KATERINA);
-		addKillId(MONSTER_DROPS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(FLAME_SHARD, ICE_SHARD);
 	}
 	
@@ -92,16 +89,15 @@ public final class Q00306_CrystalOfFireAndIce extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs;
-		if (npc.getId() == UNDINE_NOBLE) // Undine Noble gives quest drops only for the killer
-		{
+		if (npc.getId() == UNDINE_NOBLE) { // Undine Noble gives quest drops only for the killer
 			qs = getQuestState(killer, false);
-			if ((qs != null) && qs.isStarted()) {
-				giveKillReward(killer, npc);
+			if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, qs.getPlayer(), false)) {
+				giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 			}
 		} else {
 			qs = getRandomPartyMemberState(killer, -1, 3, npc);
-			if (qs != null) {
-				giveKillReward(qs.getPlayer(), npc);
+			if (qs != null && Util.checkIfInRange(1500, npc, qs.getPlayer(), false)) {
+				giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -131,11 +127,4 @@ public final class Q00306_CrystalOfFireAndIce extends Quest {
 		}
 		return htmltext;
 	}
-	
-	private static void giveKillReward(L2PcInstance player, L2Npc npc) {
-		if (Util.checkIfInRange(1500, npc, player, false)) {
-			final ItemHolder item = MONSTER_DROPS.get(npc.getId());
-			giveItemRandomly(player, npc, item.getId(), 1, 0, 1000.0 / item.getCount(), true);
-		}
-	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00308_ReedFieldMaintenance/Q00308_ReedFieldMaintenance.java b/src/main/java/com/l2jserver/datapack/quests/Q00308_ReedFieldMaintenance/Q00308_ReedFieldMaintenance.java
index 0694b5c13d..9b96c7aa74 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00308_ReedFieldMaintenance/Q00308_ReedFieldMaintenance.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00308_ReedFieldMaintenance/Q00308_ReedFieldMaintenance.java
@@ -18,17 +18,13 @@
  */
 package com.l2jserver.datapack.quests.Q00308_ReedFieldMaintenance;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00238_SuccessFailureOfBusiness.Q00238_SuccessFailureOfBusiness;
 import com.l2jserver.datapack.quests.Q00309_ForAGoodCause.Q00309_ForAGoodCause;
 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.network.serverpackets.RadarControl;
 import com.l2jserver.gameserver.util.Util;
@@ -41,21 +37,18 @@ import com.l2jserver.gameserver.util.Util;
 public class Q00308_ReedFieldMaintenance extends Quest {
 	// NPC
 	private static final int KATENSA = 32646;
-	// Mobs
-	private static final int AWAKENED_MUCROKIAN = 22655;
-	private static final Map<Integer, Integer> MUCROKIAN = new HashMap<>();
-	static {
-		MUCROKIAN.put(22650, 218); // Mucrokian Fanatic
-		MUCROKIAN.put(22651, 258); // Mucrokian Ascetic
-		MUCROKIAN.put(22652, 248); // Mucrokian Savior
-		MUCROKIAN.put(22653, 290); // Mucrokian Preacher
-		MUCROKIAN.put(22654, 220); // Contaminated Mucrokian
-		MUCROKIAN.put(22655, 124); // Awakened Mucrokian
-	}
-	
 	// Items
 	private static final int MUCROKIAN_HIDE = 14871;
 	private static final int AWAKENED_MUCROKIAN_HIDE = 14872;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22650, MUCROKIAN_HIDE, 21.8) // Mucrokian Fanatic
+			.addSingleDrop(22651, MUCROKIAN_HIDE, 25.8) // Mucrokian Ascetic
+			.addSingleDrop(22652, MUCROKIAN_HIDE, 24.8) // Mucrokian Savior
+			.addSingleDrop(22653, MUCROKIAN_HIDE, 29.0) // Mucrokian Preacher
+			.addSingleDrop(22654, MUCROKIAN_HIDE, 22.0) // Contaminated Mucrokian
+			.addSingleDrop(22655, AWAKENED_MUCROKIAN_HIDE, 12.4) // Awakened Mucrokian
+			.build();
 	// Rewards
 	private static final int REC_DYNASTY_EARRINGS_70 = 9985;
 	private static final int REC_DYNASTY_NECKLACE_70 = 9986;
@@ -63,27 +56,11 @@ public class Q00308_ReedFieldMaintenance extends Quest {
 	private static final int REC_DYNASTY_SIGIL_60 = 10115;
 	
 	private static final int[] MOIRAI_RECIPES = {
-		15777,
-		15780,
-		15783,
-		15786,
-		15789,
-		15790,
-		15814,
-		15813,
-		15812
+		15777, 15780, 15783, 15786, 15789, 15790, 15814, 15813, 15812
 	};
 	
 	private static final int[] MOIRAI_PIECES = {
-		15647,
-		15650,
-		15653,
-		15656,
-		15659,
-		15692,
-		15772,
-		15773,
-		15774
+		15647, 15650, 15653, 15656, 15659, 15692, 15772, 15773, 15774
 	};
 	
 	// Misc
@@ -93,7 +70,7 @@ public class Q00308_ReedFieldMaintenance extends Quest {
 		super(308, Q00308_ReedFieldMaintenance.class.getSimpleName(), "Reed Field Maintenance");
 		addStartNpc(KATENSA);
 		addTalkId(KATENSA);
-		addKillId(MUCROKIAN.keySet());
+		addKillId(DROPLIST.getNpcIds());
 	}
 	
 	private boolean canGiveItem(QuestState st, int quanty) {
@@ -190,18 +167,9 @@ public class Q00308_ReedFieldMaintenance extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(killer, 1);
-		if (partyMember != null) {
-			final QuestState st = getQuestState(partyMember, false);
-			double chance = MUCROKIAN.get(npc.getId()) * rates().getRateQuestDrop();
-			if (getRandom(1000) < chance) {
-				if (npc.getId() == AWAKENED_MUCROKIAN) {
-					st.giveItems(AWAKENED_MUCROKIAN_HIDE, 1);
-				} else {
-					st.giveItems(MUCROKIAN_HIDE, 1);
-				}
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
+		QuestState st = getRandomPartyMemberState(killer, 1, 1, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -220,4 +188,4 @@ public class Q00308_ReedFieldMaintenance extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00309_ForAGoodCause/Q00309_ForAGoodCause.java b/src/main/java/com/l2jserver/datapack/quests/Q00309_ForAGoodCause/Q00309_ForAGoodCause.java
index 501a1ca3b7..7d066888ca 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00309_ForAGoodCause/Q00309_ForAGoodCause.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00309_ForAGoodCause/Q00309_ForAGoodCause.java
@@ -18,17 +18,13 @@
  */
 package com.l2jserver.datapack.quests.Q00309_ForAGoodCause;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00239_WontYouJoinUs.Q00239_WontYouJoinUs;
 import com.l2jserver.datapack.quests.Q00308_ReedFieldMaintenance.Q00308_ReedFieldMaintenance;
 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.network.serverpackets.RadarControl;
 import com.l2jserver.gameserver.util.Util;
@@ -41,21 +37,18 @@ import com.l2jserver.gameserver.util.Util;
 public class Q00309_ForAGoodCause extends Quest {
 	// NPC
 	private static final int ATRA = 32647;
-	// Mobs
-	private static final int CORRUPTED_MUCROKIAN = 22654;
-	private static final Map<Integer, Integer> MUCROKIANS = new HashMap<>();
-	static {
-		MUCROKIANS.put(22650, 218); // Mucrokian Fanatic
-		MUCROKIANS.put(22651, 258); // Mucrokian Ascetic
-		MUCROKIANS.put(22652, 248); // Mucrokian Savior
-		MUCROKIANS.put(22653, 290); // Mucrokian Preacher
-		MUCROKIANS.put(22654, 124); // Contaminated Mucrokian
-		MUCROKIANS.put(22655, 220); // Awakened Mucrokian
-	}
-	
 	// Items
 	private static final int MUCROKIAN_HIDE = 14873;
 	private static final int FALLEN_MUCROKIAN_HIDE = 14874;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22650, MUCROKIAN_HIDE, 21.8) // Mucrokian Fanatic
+			.addSingleDrop(22651, MUCROKIAN_HIDE, 25.8) // Mucrokian Ascetic
+			.addSingleDrop(22652, MUCROKIAN_HIDE, 24.8) // Mucrokian Savior
+			.addSingleDrop(22653, MUCROKIAN_HIDE, 29.0) // Mucrokian Preacher
+			.addSingleDrop(22654, FALLEN_MUCROKIAN_HIDE, 2, 12.4) // Contaminated Mucrokian
+			.addSingleDrop(22655, MUCROKIAN_HIDE, 22.0) // Awakened Mucrokian
+			.build();
 	// Rewards
 	private static final int REC_DYNASTY_EARRINGS_70 = 9985;
 	private static final int REC_DYNASTY_NECKLACE_70 = 9986;
@@ -63,27 +56,11 @@ public class Q00309_ForAGoodCause extends Quest {
 	private static final int REC_DYNASTY_SIGIL_60 = 10115;
 	
 	private static final int[] MOIRAI_RECIPES = {
-		15777,
-		15780,
-		15783,
-		15786,
-		15789,
-		15790,
-		15814,
-		15813,
-		15812
+		15777, 15780, 15783, 15786, 15789, 15790, 15814, 15813, 15812
 	};
 	
 	private static final int[] MOIRAI_PIECES = {
-		15647,
-		15650,
-		15653,
-		15656,
-		15659,
-		15692,
-		15772,
-		15773,
-		15774
+		15647, 15650, 15653, 15656, 15659, 15692, 15772, 15773, 15774
 	};
 	
 	// Misc
@@ -93,7 +70,7 @@ public class Q00309_ForAGoodCause extends Quest {
 		super(309, Q00309_ForAGoodCause.class.getSimpleName(), "For A Good Cause");
 		addStartNpc(ATRA);
 		addTalkId(ATRA);
-		addKillId(MUCROKIANS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 	}
 	
 	private boolean canGiveItem(QuestState st, int quanty) {
@@ -192,19 +169,9 @@ public class Q00309_ForAGoodCause extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(killer, 1);
-		if (partyMember != null) {
-			final QuestState st = getQuestState(partyMember, false);
-			double chance = MUCROKIANS.get(npc.getId()) * rates().getRateQuestDrop();
-			if (getRandom(1000) < chance) {
-				if (npc.getId() == CORRUPTED_MUCROKIAN) {
-					st.giveItems(FALLEN_MUCROKIAN_HIDE, 1);
-					st.rewardItems(FALLEN_MUCROKIAN_HIDE, 1);
-				} else {
-					st.giveItems(MUCROKIAN_HIDE, 1);
-				}
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
+		QuestState st = getRandomPartyMemberState(killer, 1, 1, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00311_ExpulsionOfEvilSpirits/Q00311_ExpulsionOfEvilSpirits.java b/src/main/java/com/l2jserver/datapack/quests/Q00311_ExpulsionOfEvilSpirits/Q00311_ExpulsionOfEvilSpirits.java
index bc1efb184a..86e98d7ac1 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00311_ExpulsionOfEvilSpirits/Q00311_ExpulsionOfEvilSpirits.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00311_ExpulsionOfEvilSpirits/Q00311_ExpulsionOfEvilSpirits.java
@@ -18,13 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00311_ExpulsionOfEvilSpirits;
 
-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;
 
 /**
@@ -43,27 +41,26 @@ public final class Q00311_ExpulsionOfEvilSpirits extends Quest {
 	private static final int SOUL_CORE_COUNT = 10;
 	private static final int RAGNA_ORCS_KILLS_COUNT = 100;
 	private static final int RAGNA_ORCS_AMULET_COUNT = 10;
-	// Monsters
-	private static final Map<Integer, Double> MONSTERS = new HashMap<>();
-	static {
-		MONSTERS.put(22691, 0.694); // Ragna Orc
-		MONSTERS.put(22692, 0.716); // Ragna Orc Warrior
-		MONSTERS.put(22693, 0.736); // Ragna Orc Hero
-		MONSTERS.put(22694, 0.712); // Ragna Orc Commander
-		MONSTERS.put(22695, 0.698); // Ragna Orc Healer
-		MONSTERS.put(22696, 0.692); // Ragna Orc Shaman
-		MONSTERS.put(22697, 0.640); // Ragna Orc Seer
-		MONSTERS.put(22698, 0.716); // Ragna Orc Archer
-		MONSTERS.put(22699, 0.752); // Ragna Orc Sniper
-		MONSTERS.put(22701, 0.716); // Varangka's Dre Vanul
-		MONSTERS.put(22702, 0.662); // Varangka's Destroyer
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22691, RAGNA_ORCS_AMULET, 69.4) // Ragna Orc
+			.addSingleDrop(22692, RAGNA_ORCS_AMULET, 71.6) // Ragna Orc Warrior
+			.addSingleDrop(22693, RAGNA_ORCS_AMULET, 73.6) // Ragna Orc Hero
+			.addSingleDrop(22694, RAGNA_ORCS_AMULET, 71.2) // Ragna Orc Commander
+			.addSingleDrop(22695, RAGNA_ORCS_AMULET, 69.8) // Ragna Orc Healer
+			.addSingleDrop(22696, RAGNA_ORCS_AMULET, 69.2) // Ragna Orc Shaman
+			.addSingleDrop(22697, RAGNA_ORCS_AMULET, 64.0) // Ragna Orc Seer
+			.addSingleDrop(22698, RAGNA_ORCS_AMULET, 71.6) // Ragna Orc Archer
+			.addSingleDrop(22699, RAGNA_ORCS_AMULET, 75.2) // Ragna Orc Sniper
+			.addSingleDrop(22701, RAGNA_ORCS_AMULET, 71.6) // Varangka's Dre Vanul
+			.addSingleDrop(22702, RAGNA_ORCS_AMULET, 66.2) // Varangka's Destroyer
+			.build();
 	
 	public Q00311_ExpulsionOfEvilSpirits() {
 		super(311, Q00311_ExpulsionOfEvilSpirits.class.getSimpleName(), "Expulsion of Evil Spirits");
 		addStartNpc(CHAIREN);
 		addTalkId(CHAIREN);
-		addKillId(MONSTERS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(SOUL_CORE_CONTAINING_EVIL_SPIRIT, RAGNA_ORCS_AMULET);
 	}
 	
@@ -126,7 +123,7 @@ public final class Q00311_ExpulsionOfEvilSpirits extends Quest {
 				qs.setMemoStateEx(1, count);
 			}
 			
-			qs.giveItemRandomly(npc, RAGNA_ORCS_AMULET, 1, 0, MONSTERS.get(npc.getId()), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00313_CollectSpores/Q00313_CollectSpores.java b/src/main/java/com/l2jserver/datapack/quests/Q00313_CollectSpores/Q00313_CollectSpores.java
index 44c6400682..560a61d9d4 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00313_CollectSpores/Q00313_CollectSpores.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00313_CollectSpores/Q00313_CollectSpores.java
@@ -20,6 +20,7 @@ package com.l2jserver.datapack.quests.Q00313_CollectSpores;
 
 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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -33,10 +34,9 @@ public final class Q00313_CollectSpores extends Quest {
 	// NPC
 	private static final int HERBIEL = 30150;
 	// Item
-	private static final int SPORE_SAC = 1118;
+	private static final QuestItemChanceHolder SPORE_SAC = new QuestItemChanceHolder(1118, 40.0, 10L);
 	// Misc
 	private static final int MIN_LEVEL = 8;
-	private static final int REQUIRED_SAC_COUNT = 10;
 	// Monster
 	private static final int SPORE_FUNGUS = 20509;
 	
@@ -45,7 +45,7 @@ public final class Q00313_CollectSpores extends Quest {
 		addStartNpc(HERBIEL);
 		addTalkId(HERBIEL);
 		addKillId(SPORE_FUNGUS);
-		registerQuestItems(SPORE_SAC);
+		registerQuestItems(SPORE_SAC.getId());
 	}
 	
 	@Override
@@ -74,8 +74,8 @@ public final class Q00313_CollectSpores extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getQuestState(killer, false);
-		if ((st != null) && st.isCond(1) && Util.checkIfInRange(1500, npc, killer, false)) {
-			if (st.giveItemRandomly(npc, SPORE_SAC, 1, REQUIRED_SAC_COUNT, 0.4, true)) {
+		if ((st != null) && st.isCond(1) && Util.checkIfInRange(1500, npc, st.getPlayer(), false)) {
+			if (giveItemRandomly(st.getPlayer(), npc, SPORE_SAC, true)) {
 				st.setCond(2);
 			}
 		}
@@ -94,13 +94,13 @@ public final class Q00313_CollectSpores extends Quest {
 			case State.STARTED: {
 				switch (st.getCond()) {
 					case 1: {
-						if (st.getQuestItemsCount(SPORE_SAC) < REQUIRED_SAC_COUNT) {
+						if (!hasItemsAtLimit(st.getPlayer(), SPORE_SAC)) {
 							htmltext = "30150-06.html";
 						}
 						break;
 					}
 					case 2: {
-						if (st.getQuestItemsCount(SPORE_SAC) >= REQUIRED_SAC_COUNT) {
+						if (hasItemsAtLimit(st.getPlayer(), SPORE_SAC)) {
 							st.giveAdena(3500, true);
 							st.exitQuest(true, true);
 							htmltext = "30150-07.html";
@@ -113,4 +113,4 @@ public final class Q00313_CollectSpores extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00316_DestroyPlagueCarriers/Q00316_DestroyPlagueCarriers.java b/src/main/java/com/l2jserver/datapack/quests/Q00316_DestroyPlagueCarriers/Q00316_DestroyPlagueCarriers.java
index 8571580a7b..c4185a6a04 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00316_DestroyPlagueCarriers/Q00316_DestroyPlagueCarriers.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00316_DestroyPlagueCarriers/Q00316_DestroyPlagueCarriers.java
@@ -18,14 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00316_DestroyPlagueCarriers;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.enums.Race;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
+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.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
@@ -40,30 +38,30 @@ public final class Q00316_DestroyPlagueCarriers extends Quest {
 	private static final int ELLENIA = 30155;
 	// Items
 	private static final int WERERAT_FANG = 1042;
-	private static final int VAROOL_FOULCLAW_FANG = 1043;
+	private static final QuestItemChanceHolder VAROOL_FOULCLAW_FANG = new QuestItemChanceHolder(1043, 1L);
 	// Misc
 	private static final int MIN_LEVEL = 18;
 	// Monsters
 	private static final int VAROOL_FOULCLAW = 27020;
-	private static final Map<Integer, ItemHolder> MONSTER_DROPS = new HashMap<>();
-	static {
-		MONSTER_DROPS.put(20040, new ItemHolder(WERERAT_FANG, 5)); // Sukar Wererat
-		MONSTER_DROPS.put(20047, new ItemHolder(WERERAT_FANG, 5)); // Sukar Wererat Leader
-		MONSTER_DROPS.put(VAROOL_FOULCLAW, new ItemHolder(VAROOL_FOULCLAW_FANG, 7)); // Varool Foulclaw
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20040, WERERAT_FANG, 50.0) // Sukar Wererat
+			.addSingleDrop(20047, WERERAT_FANG, 50.0) // Sukar Wererat Leader
+			.addSingleDrop(VAROOL_FOULCLAW, VAROOL_FOULCLAW_FANG, 70.0) // Varool Foulclaw
+			.build();
 	
 	public Q00316_DestroyPlagueCarriers() {
 		super(316, Q00316_DestroyPlagueCarriers.class.getSimpleName(), "Destroy Plague Carriers");
 		addStartNpc(ELLENIA);
 		addTalkId(ELLENIA);
 		addAttackId(VAROOL_FOULCLAW);
-		addKillId(MONSTER_DROPS.keySet());
-		registerQuestItems(WERERAT_FANG, VAROOL_FOULCLAW_FANG);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(WERERAT_FANG, VAROOL_FOULCLAW_FANG.getId());
 	}
 	
 	@Override
 	public boolean checkPartyMember(QuestState qs, L2Npc npc) {
-		return ((npc.getId() != VAROOL_FOULCLAW) || !qs.hasQuestItems(VAROOL_FOULCLAW_FANG));
+		return ((npc.getId() != VAROOL_FOULCLAW) || !qs.hasQuestItems(VAROOL_FOULCLAW_FANG.getId()));
 	}
 	
 	@Override
@@ -108,9 +106,7 @@ public final class Q00316_DestroyPlagueCarriers extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			final ItemHolder item = MONSTER_DROPS.get(npc.getId());
-			final int limit = (npc.getId() == VAROOL_FOULCLAW ? 1 : 0);
-			giveItemRandomly(qs.getPlayer(), npc, item.getId(), 1, limit, 10.0 / item.getCount(), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -129,9 +125,9 @@ public final class Q00316_DestroyPlagueCarriers extends Quest {
 			}
 		} else if (qs.isStarted()) {
 			if (hasAtLeastOneQuestItem(player, getRegisteredItemIds())) {
-				final long wererars = getQuestItemsCount(player, WERERAT_FANG);
-				final long foulclaws = getQuestItemsCount(player, VAROOL_FOULCLAW_FANG);
-				giveAdena(player, ((wererars * 30) + (foulclaws * 10000) + ((wererars + foulclaws) >= 10 ? 5000 : 0)), true);
+				final long wererats = getQuestItemsCount(player, WERERAT_FANG);
+				final long foulclaws = getQuestItemsCount(player, VAROOL_FOULCLAW_FANG.getId());
+				giveAdena(player, ((wererats * 30) + (foulclaws * 10000) + ((wererats + foulclaws) >= 10 ? 5000 : 0)), true);
 				takeItems(player, -1, getRegisteredItemIds());
 				htmltext = "30155-07.html";
 			} else {
@@ -140,4 +136,4 @@ public final class Q00316_DestroyPlagueCarriers extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00317_CatchTheWind/Q00317_CatchTheWind.java b/src/main/java/com/l2jserver/datapack/quests/Q00317_CatchTheWind/Q00317_CatchTheWind.java
index f57291b42d..b7327ad7f0 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00317_CatchTheWind/Q00317_CatchTheWind.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00317_CatchTheWind/Q00317_CatchTheWind.java
@@ -20,6 +20,7 @@ package com.l2jserver.datapack.quests.Q00317_CatchTheWind;
 
 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 +32,7 @@ public final class Q00317_CatchTheWind extends Quest {
 	// NPC
 	private static final int RIZRAELL = 30361;
 	// Item
-	private static final int WIND_SHARD = 1078;
+	private static final QuestItemChanceHolder WIND_SHARD = new QuestItemChanceHolder(1078, 50.0);
 	// Misc
 	private static final int MIN_LEVEL = 18;
 	private static final double DROP_CHANCE = 0.5;
@@ -46,7 +47,7 @@ public final class Q00317_CatchTheWind extends Quest {
 		addStartNpc(RIZRAELL);
 		addTalkId(RIZRAELL);
 		addKillId(MONSTERS);
-		registerQuestItems(WIND_SHARD);
+		registerQuestItems(WIND_SHARD.getId());
 	}
 	
 	@Override
@@ -67,10 +68,10 @@ public final class Q00317_CatchTheWind extends Quest {
 			}
 			case "30361-08.html":
 			case "30361-09.html": {
-				final long shardCount = getQuestItemsCount(player, WIND_SHARD);
+				final long shardCount = getQuestItemsCount(player, WIND_SHARD.getId());
 				if (shardCount > 0) {
 					giveAdena(player, ((shardCount * 40) + (shardCount >= 10 ? 2988 : 0)), true);
-					takeItems(player, WIND_SHARD, -1);
+					takeItems(player, WIND_SHARD.getId(), -1);
 				}
 				
 				if (event.equals("30361-08.html")) {
@@ -88,7 +89,7 @@ public final class Q00317_CatchTheWind extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			giveItemRandomly(qs.getPlayer(), npc, WIND_SHARD, 1, 0, DROP_CHANCE, true);
+			giveItemRandomly(qs.getPlayer(), npc, WIND_SHARD, true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -100,8 +101,8 @@ public final class Q00317_CatchTheWind extends Quest {
 		if (qs.isCreated()) {
 			htmltext = ((player.getLevel() >= MIN_LEVEL) ? "30361-03.htm" : "30361-02.htm");
 		} else if (qs.isStarted()) {
-			htmltext = (hasQuestItems(player, WIND_SHARD) ? "30361-07.html" : "30361-05.html");
+			htmltext = (hasQuestItems(player, WIND_SHARD.getId()) ? "30361-07.html" : "30361-05.html");
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00320_BonesTellTheFuture/Q00320_BonesTellTheFuture.java b/src/main/java/com/l2jserver/datapack/quests/Q00320_BonesTellTheFuture/Q00320_BonesTellTheFuture.java
index 3ed76088a4..61a5efb4f8 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00320_BonesTellTheFuture/Q00320_BonesTellTheFuture.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00320_BonesTellTheFuture/Q00320_BonesTellTheFuture.java
@@ -21,6 +21,7 @@ package com.l2jserver.datapack.quests.Q00320_BonesTellTheFuture;
 import com.l2jserver.gameserver.enums.Race;
 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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -33,11 +34,9 @@ public final class Q00320_BonesTellTheFuture extends Quest {
 	// NPC
 	private static final int TETRACH_KAITAR = 30359;
 	// Item
-	private static final int BONE_FRAGMENT = 809;
+	private static final QuestItemChanceHolder BONE_FRAGMENT = new QuestItemChanceHolder(809, 18.0, 10L);
 	// Misc
 	private static final int MIN_LEVEL = 10;
-	private static final int REQUIRED_BONE_COUNT = 10;
-	private static final double DROP_CHANCE = 0.18;
 	// Monsters
 	private static final int[] MONSTERS = {
 		20517, // Skeleton Hunter
@@ -49,7 +48,7 @@ public final class Q00320_BonesTellTheFuture extends Quest {
 		addStartNpc(TETRACH_KAITAR);
 		addTalkId(TETRACH_KAITAR);
 		addKillId(MONSTERS);
-		registerQuestItems(BONE_FRAGMENT);
+		registerQuestItems(BONE_FRAGMENT.getId());
 	}
 	
 	@Override
@@ -65,7 +64,7 @@ public final class Q00320_BonesTellTheFuture extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 1, 3, npc);
-		if ((qs != null) && qs.giveItemRandomly(npc, BONE_FRAGMENT, 1, REQUIRED_BONE_COUNT, DROP_CHANCE, true)) {
+		if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, BONE_FRAGMENT, true)) {
 			qs.setCond(2);
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -81,7 +80,7 @@ public final class Q00320_BonesTellTheFuture extends Quest {
 				break;
 			}
 			case State.STARTED: {
-				if (st.getQuestItemsCount(BONE_FRAGMENT) >= REQUIRED_BONE_COUNT) {
+				if (hasItemsAtLimit(st.getPlayer(), BONE_FRAGMENT)) {
 					htmltext = "30359-06.html";
 					st.giveAdena(8470, true);
 					st.exitQuest(true, true);
@@ -93,4 +92,4 @@ public final class Q00320_BonesTellTheFuture extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00325_GrimCollector/Q00325_GrimCollector.java b/src/main/java/com/l2jserver/datapack/quests/Q00325_GrimCollector/Q00325_GrimCollector.java
index 3b508fbf97..6fefeaa004 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00325_GrimCollector/Q00325_GrimCollector.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00325_GrimCollector/Q00325_GrimCollector.java
@@ -18,15 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00325_GrimCollector;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.QuestItemHolder;
 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;
 import com.l2jserver.gameserver.util.Util;
@@ -51,28 +46,27 @@ public final class Q00325_GrimCollector extends Quest {
 	private static final int ARM_BONE = 1356;
 	private static final int THIGH_BONE = 1357;
 	private static final int COMPLETE_SKELETON = 1358;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addGroupedDrop(20026, 75.0).withDropItem(ZOMBIE_HEAD, 40.0).withDropItem(ZOMBIE_HEART, 26.67).withDropItem(ZOMBIE_LIVER, 33.33).build()
+			.addGroupedDrop(20029, 75.0).withDropItem(ZOMBIE_HEAD, 40.0).withDropItem(ZOMBIE_HEART, 29.33).withDropItem(ZOMBIE_LIVER, 30.67).build()
+			.addGroupedDrop(20035, 79.0).withDropItem(SKULL, 6.33).withDropItem(RIB_BONE, 12.65).withDropItem(SPINE, 17.72).withDropItem(THIGH_BONE, 63.30).build()
+			.addGroupedDrop(20042, 86.0).withDropItem(SKULL, 6.97).withDropItem(RIB_BONE, 15.12).withDropItem(ARM_BONE, 58.15).withDropItem(THIGH_BONE, 19.76).build()
+			.addGroupedDrop(20045, 97.0).withDropItem(SKULL, 9.28).withDropItem(SPINE, 51.55).withDropItem(ARM_BONE, 18.55).withDropItem(THIGH_BONE, 20.62).build()
+			.addGroupedDrop(20051, 100.0).withDropItem(SKULL, 9.0).withDropItem(RIB_BONE, 50.0).withDropItem(SPINE, 20.0).withDropItem(ARM_BONE, 21.0).build()
+			.addGroupedDrop(20457, 80.0).withDropItem(ZOMBIE_HEAD, 50.0).withDropItem(ZOMBIE_HEART, 25.0).withDropItem(ZOMBIE_LIVER, 25.0).build()
+			.addGroupedDrop(20458, 100.0).withDropItem(ZOMBIE_HEAD, 40.0).withDropItem(ZOMBIE_HEART, 30.0).withDropItem(ZOMBIE_LIVER, 30.0).build()
+			.addGroupedDrop(20514, 64.0).withDropItem(SKULL, 9.37).withDropItem(RIB_BONE, 23.43).withDropItem(SPINE, 14.07).withDropItem(ARM_BONE, 1.57).withDropItem(THIGH_BONE, 51.56).build()
+			.addGroupedDrop(20515, 69.0).withDropItem(SKULL, 7.24).withDropItem(RIB_BONE, 21.74).withDropItem(SPINE, 15.94).withDropItem(ARM_BONE, 2.90).withDropItem(THIGH_BONE, 52.18).build()
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 15;
-	// Monsters
-	private static final Map<Integer, List<QuestItemHolder>> MONSTER_DROPS = new HashMap<>();
-	static {
-		MONSTER_DROPS.put(20026, Arrays.asList(new QuestItemHolder(ZOMBIE_HEAD, 30), new QuestItemHolder(ZOMBIE_HEART, 50), new QuestItemHolder(ZOMBIE_LIVER, 75)));
-		MONSTER_DROPS.put(20029, Arrays.asList(new QuestItemHolder(ZOMBIE_HEAD, 30), new QuestItemHolder(ZOMBIE_HEART, 52), new QuestItemHolder(ZOMBIE_LIVER, 75)));
-		MONSTER_DROPS.put(20035, Arrays.asList(new QuestItemHolder(SKULL, 5), new QuestItemHolder(RIB_BONE, 15), new QuestItemHolder(SPINE, 29), new QuestItemHolder(THIGH_BONE, 79)));
-		MONSTER_DROPS.put(20042, Arrays.asList(new QuestItemHolder(SKULL, 6), new QuestItemHolder(RIB_BONE, 19), new QuestItemHolder(ARM_BONE, 69), new QuestItemHolder(THIGH_BONE, 86)));
-		MONSTER_DROPS.put(20045, Arrays.asList(new QuestItemHolder(SKULL, 9), new QuestItemHolder(SPINE, 59), new QuestItemHolder(ARM_BONE, 77), new QuestItemHolder(THIGH_BONE, 97)));
-		MONSTER_DROPS.put(20051, Arrays.asList(new QuestItemHolder(SKULL, 9), new QuestItemHolder(RIB_BONE, 59), new QuestItemHolder(SPINE, 79), new QuestItemHolder(ARM_BONE, 100)));
-		MONSTER_DROPS.put(20457, Arrays.asList(new QuestItemHolder(ZOMBIE_HEAD, 40), new QuestItemHolder(ZOMBIE_HEART, 60), new QuestItemHolder(ZOMBIE_LIVER, 80)));
-		MONSTER_DROPS.put(20458, Arrays.asList(new QuestItemHolder(ZOMBIE_HEAD, 40), new QuestItemHolder(ZOMBIE_HEART, 70), new QuestItemHolder(ZOMBIE_LIVER, 100)));
-		MONSTER_DROPS.put(20514, Arrays.asList(new QuestItemHolder(SKULL, 6), new QuestItemHolder(RIB_BONE, 21), new QuestItemHolder(SPINE, 30), new QuestItemHolder(ARM_BONE, 31), new QuestItemHolder(THIGH_BONE, 64)));
-		MONSTER_DROPS.put(20515, Arrays.asList(new QuestItemHolder(SKULL, 5), new QuestItemHolder(RIB_BONE, 20), new QuestItemHolder(SPINE, 31), new QuestItemHolder(ARM_BONE, 33), new QuestItemHolder(THIGH_BONE, 69)));
-	}
 	
 	public Q00325_GrimCollector() {
 		super(325, Q00325_GrimCollector.class.getSimpleName(), "Grim Collector");
 		addStartNpc(GUARD_CURTIZ);
 		addTalkId(GUARD_CURTIZ, VARSAK, SAMED);
-		addKillId(MONSTER_DROPS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(ANATOMY_DIAGRAM, ZOMBIE_HEAD, ZOMBIE_HEART, ZOMBIE_LIVER, SKULL, RIB_BONE, SPINE, ARM_BONE, THIGH_BONE, COMPLETE_SKELETON);
 	}
 	
@@ -173,14 +167,9 @@ public final class Q00325_GrimCollector extends Quest {
 		if (!Util.checkIfInRange(1500, killer, npc, true) || !qs.hasQuestItems(ANATOMY_DIAGRAM)) {
 			return super.onKill(npc, killer, isSummon);
 		}
-		
-		final int rnd = getRandom(100);
-		for (QuestItemHolder drop : MONSTER_DROPS.get(npc.getId())) {
-			if (rnd < drop.getChance()) {
-				qs.giveItemRandomly(npc, drop.getId(), 1, 0, 1.0, true);
-				break;
-			}
-		}
+
+		giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
+
 		return super.onKill(npc, killer, isSummon);
 	}
 	
@@ -227,4 +216,4 @@ public final class Q00325_GrimCollector extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00329_CuriosityOfADwarf/Q00329_CuriosityOfADwarf.java b/src/main/java/com/l2jserver/datapack/quests/Q00329_CuriosityOfADwarf/Q00329_CuriosityOfADwarf.java
index 28a6d5ec34..2309b1d6f9 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00329_CuriosityOfADwarf/Q00329_CuriosityOfADwarf.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00329_CuriosityOfADwarf/Q00329_CuriosityOfADwarf.java
@@ -18,15 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00329_CuriosityOfADwarf;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
 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;
 import com.l2jserver.gameserver.util.Util;
@@ -43,18 +38,23 @@ public final class Q00329_CuriosityOfADwarf extends Quest {
 	private static final int BROKEN_HEARTSTONE = 1365;
 	// Misc
 	private static final int MIN_LEVEL = 33;
-	// Monsters
-	private static final Map<Integer, List<ItemHolder>> MONSTER_DROPS = new HashMap<>();
-	static {
-		MONSTER_DROPS.put(20083, Arrays.asList(new ItemHolder(GOLEM_HEARTSTONE, 3), new ItemHolder(BROKEN_HEARTSTONE, 54))); // Granitic Golem
-		MONSTER_DROPS.put(20085, Arrays.asList(new ItemHolder(GOLEM_HEARTSTONE, 3), new ItemHolder(BROKEN_HEARTSTONE, 58))); // Puncher
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addGroupedDrop(20083, 54.0) // Granitic Golem
+				.withDropItem(GOLEM_HEARTSTONE, 5.56)
+				.withDropItem(BROKEN_HEARTSTONE, 94.44)
+				.build()
+			.addGroupedDrop(20085, 58.0) // Puncher
+				.withDropItem(GOLEM_HEARTSTONE, 5.17)
+				.withDropItem(BROKEN_HEARTSTONE, 94.83)
+				.build()
+			.build();
 	
 	public Q00329_CuriosityOfADwarf() {
 		super(329, Q00329_CuriosityOfADwarf.class.getSimpleName(), "Curiosity Of A Dwarf");
 		addStartNpc(TRADER_ROLENTO);
 		addTalkId(TRADER_ROLENTO);
-		addKillId(MONSTER_DROPS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(GOLEM_HEARTSTONE, BROKEN_HEARTSTONE);
 	}
 	
@@ -91,13 +91,7 @@ public final class Q00329_CuriosityOfADwarf extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getQuestState(killer, false);
 		if ((st != null) && Util.checkIfInRange(1500, npc, killer, true)) {
-			final int rnd = getRandom(100);
-			for (ItemHolder drop : MONSTER_DROPS.get(npc.getId())) {
-				if (rnd < drop.getCount()) {
-					st.giveItemRandomly(npc, drop.getId(), 1, 0, 1.0, true);
-					break;
-				}
-			}
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -126,4 +120,4 @@ public final class Q00329_CuriosityOfADwarf extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00335_TheSongOfTheHunter/Q00335_TheSongOfTheHunter.java b/src/main/java/com/l2jserver/datapack/quests/Q00335_TheSongOfTheHunter/Q00335_TheSongOfTheHunter.java
index 395c09322e..afb76f76a7 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00335_TheSongOfTheHunter/Q00335_TheSongOfTheHunter.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00335_TheSongOfTheHunter/Q00335_TheSongOfTheHunter.java
@@ -18,10 +18,6 @@
  */
 package com.l2jserver.datapack.quests.Q00335_TheSongOfTheHunter;
 
-import java.util.Arrays;
-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;
@@ -32,6 +28,10 @@ import com.l2jserver.gameserver.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
 import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
 
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * The Song of the Hunter (335)
  * @author Zoey76
@@ -1079,14 +1079,14 @@ public class Q00335_TheSongOfTheHunter extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final QuestState qs = getRandomPartyMemberState(player, -1, 3, npc);
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
 			for (int i = DROPLIST.length - 1; i >= 0; i--) {
 				final int[] droplist = DROPLIST[i];
 				if (npc.getId() == droplist[0]) {
 					if (hasQuestItems(qs.getPlayer(), droplist[1]) && giveItemRandomly(qs.getPlayer(), npc, droplist[2], droplist[3], droplist[4], droplist[5] / 100d, true)) {
-						playSound(player, Sound.ITEMSOUND_QUEST_MIDDLE);
+						playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
 					}
 				}
 			}
@@ -1225,41 +1225,31 @@ public class Q00335_TheSongOfTheHunter extends Quest {
 				}
 				case GREMLIN_FILCHER: {
 					if (hasQuestItems(qs.getPlayer(), SECOND_CIRCLE_REQUEST_7C) && (getQuestItemsCount(qs.getPlayer(), TEMPEST_SHARD) < 40)) {
-						if (giveItemRandomly(qs.getPlayer(), npc, TEMPEST_SHARD, 5, 40, 1.0, true)) {
-							playSound(player, Sound.ITEMSOUND_QUEST_MIDDLE);
-						}
+						giveItemRandomly(qs.getPlayer(), npc, TEMPEST_SHARD, 5, 40, 1.0, true);
 						
 						npc.broadcastPacket(new CreatureSay(npc.getObjectId(), Say2.NPC_ALL, npc.getName(), NpcStringId.PRETTY_GOOD));
 					}
 					
 					if (hasQuestItems(qs.getPlayer(), SECOND_CIRCLE_REQUEST_8C) && (getQuestItemsCount(qs.getPlayer(), TSUNAMI_SHARD) < 40)) {
-						if (giveItemRandomly(qs.getPlayer(), npc, TSUNAMI_SHARD, 5, 40, 1.0, true)) {
-							playSound(player, Sound.ITEMSOUND_QUEST_MIDDLE);
-						}
+						giveItemRandomly(qs.getPlayer(), npc, TSUNAMI_SHARD, 5, 40, 1.0, true);
 						
 						npc.broadcastPacket(new CreatureSay(npc.getObjectId(), Say2.NPC_ALL, npc.getName(), NpcStringId.PRETTY_GOOD));
 					}
 					
 					if (hasQuestItems(qs.getPlayer(), SECOND_CIRCLE_REQUEST_10C) && (getQuestItemsCount(qs.getPlayer(), HAMADRYAD_SHARD) < 40)) {
-						if (giveItemRandomly(qs.getPlayer(), npc, HAMADRYAD_SHARD, 5, 40, 1.0, true)) {
-							playSound(player, Sound.ITEMSOUND_QUEST_MIDDLE);
-						}
+						giveItemRandomly(qs.getPlayer(), npc, HAMADRYAD_SHARD, 5, 40, 1.0, true);
 						
 						npc.broadcastPacket(new CreatureSay(npc.getObjectId(), Say2.NPC_ALL, npc.getName(), NpcStringId.PRETTY_GOOD));
 					}
 					
 					if (hasQuestItems(qs.getPlayer(), SECOND_CIRCLE_REQUEST_3B) && (getQuestItemsCount(qs.getPlayer(), NARCISSUSS_SOULSTONE) < 40)) {
-						if (giveItemRandomly(qs.getPlayer(), npc, NARCISSUSS_SOULSTONE, 5, 40, 1.0, true)) {
-							playSound(player, Sound.ITEMSOUND_QUEST_MIDDLE);
-						}
+						giveItemRandomly(qs.getPlayer(), npc, NARCISSUSS_SOULSTONE, 5, 40, 1.0, true);
 						
 						npc.broadcastPacket(new CreatureSay(npc.getObjectId(), Say2.NPC_ALL, npc.getName(), NpcStringId.PRETTY_GOOD));
 					}
 					
 					if (hasQuestItems(qs.getPlayer(), SECOND_CIRCLE_REQUEST_5C) && (getQuestItemsCount(qs.getPlayer(), COIN_OF_OLD_EMPIRE) < 20)) {
-						if (giveItemRandomly(qs.getPlayer(), npc, COIN_OF_OLD_EMPIRE, 3, 20, 1.0, true)) {
-							playSound(player, Sound.ITEMSOUND_QUEST_MIDDLE);
-						}
+						giveItemRandomly(qs.getPlayer(), npc, COIN_OF_OLD_EMPIRE, 3, 20, 1.0, true);
 						
 						npc.broadcastPacket(new CreatureSay(npc.getObjectId(), Say2.NPC_ALL, npc.getName(), NpcStringId.PRETTY_GOOD));
 					}
@@ -1299,7 +1289,7 @@ public class Q00335_TheSongOfTheHunter extends Quest {
 				}
 			}
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	private String reward(L2PcInstance player, QuestState qs, int[][] rewards) {
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00336_CoinsOfMagic/Q00336_CoinsOfMagic.java b/src/main/java/com/l2jserver/datapack/quests/Q00336_CoinsOfMagic/Q00336_CoinsOfMagic.java
index ecce1174ee..7f1000735b 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00336_CoinsOfMagic/Q00336_CoinsOfMagic.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00336_CoinsOfMagic/Q00336_CoinsOfMagic.java
@@ -18,16 +18,17 @@
  */
 package com.l2jserver.datapack.quests.Q00336_CoinsOfMagic;
 
-import java.util.ArrayList;
-import java.util.List;
-
 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.util.Util;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Coin Of Magic (336)
  * @author Zealar
@@ -45,39 +46,6 @@ public final class Q00336_CoinsOfMagic extends Quest {
 	private static final int MAGISTER_PAGE = 30696;
 	private static final int UNION_PRESIDENT_BERNARD = 30702;
 	private static final int HEAD_BLACKSMITH_FERRIS = 30847;
-	// Items
-	private static final int Q_BLOOD_MEDUSA = 3472;
-	private static final int Q_BLOOD_WEREWOLF = 3473;
-	private static final int Q_BLOOD_BASILISK = 3474;
-	private static final int Q_BLOOD_DREVANUL = 3475;
-	private static final int Q_BLOOD_SUCCUBUS = 3476;
-	private static final int Q_BLOOD_DRAGON = 3477;
-	private static final int Q_BERETHS_BLOOD_DRAGON = 3478;
-	private static final int Q_MANAKS_BLOOD_WEREWOLF = 3479;
-	private static final int Q_NIAS_BLOOD_MEDUSA = 3480;
-	private static final int Q_GOLD_DRAGON = 3481;
-	private static final int Q_GOLD_WYVERN = 3482;
-	private static final int Q_GOLD_KNIGHT = 3483;
-	private static final int Q_GOLD_GIANT = 3484;
-	private static final int Q_GOLD_DRAKE = 3485;
-	private static final int Q_GOLD_WYRM = 3486;
-	private static final int Q_BERETHS_GOLD_DRAGON = 3487;
-	private static final int Q_MANAKS_GOLD_GIANT = 3488;
-	private static final int Q_NIAS_GOLD_WYVERN = 3489;
-	private static final int Q_SILVER_UNICORN = 3490;
-	private static final int Q_SILVER_FAIRY = 3491;
-	private static final int Q_SILVER_DRYAD = 3492;
-	private static final int Q_SILVER_DRAGON = 3493;
-	private static final int Q_SILVER_GOLEM = 3494;
-	private static final int Q_SILVER_UNDINE = 3495;
-	private static final int Q_BERETHS_SILVER_DRAGON = 3496;
-	private static final int Q_MANAKS_SILVER_DRYAD = 3497;
-	private static final int Q_NIAS_SILVER_FAIRY = 3498;
-	private static final int Q_COIN_DIAGRAM = 3811;
-	private static final int Q_KALDIS_GOLD_DRAGON = 3812;
-	private static final int Q_CC_MEMBERSHIP_1 = 3813;
-	private static final int Q_CC_MEMBERSHIP_2 = 3814;
-	private static final int Q_CC_MEMBERSHIP_3 = 3815;
 	// Monsters
 	private static final int HEADLESS_KNIGHT = 20146;
 	private static final int OEL_MAHUM = 20161;
@@ -130,6 +98,80 @@ public final class Q00336_CoinsOfMagic extends Quest {
 	private static final int BRILLIANT_VENGEANCE_1 = 21658;
 	private static final int BRILLIANT_ANGUISH = 21539;
 	private static final int BRILLIANT_ANGUISH_1 = 21540;
+	// Items
+	private static final int Q_BLOOD_MEDUSA = 3472;
+	private static final int Q_BLOOD_WEREWOLF = 3473;
+	private static final int Q_BLOOD_BASILISK = 3474;
+	private static final int Q_BLOOD_DREVANUL = 3475;
+	private static final int Q_BLOOD_SUCCUBUS = 3476;
+	private static final int Q_BLOOD_DRAGON = 3477;
+	private static final int Q_BERETHS_BLOOD_DRAGON = 3478;
+	private static final int Q_MANAKS_BLOOD_WEREWOLF = 3479;
+	private static final int Q_NIAS_BLOOD_MEDUSA = 3480;
+	private static final int Q_GOLD_DRAGON = 3481;
+	private static final int Q_GOLD_WYVERN = 3482;
+	private static final int Q_GOLD_KNIGHT = 3483;
+	private static final int Q_GOLD_GIANT = 3484;
+	private static final int Q_GOLD_DRAKE = 3485;
+	private static final int Q_GOLD_WYRM = 3486;
+	private static final int Q_BERETHS_GOLD_DRAGON = 3487;
+	private static final int Q_MANAKS_GOLD_GIANT = 3488;
+	private static final int Q_NIAS_GOLD_WYVERN = 3489;
+	private static final int Q_SILVER_UNICORN = 3490;
+	private static final int Q_SILVER_FAIRY = 3491;
+	private static final int Q_SILVER_DRYAD = 3492;
+	private static final int Q_SILVER_DRAGON = 3493;
+	private static final int Q_SILVER_GOLEM = 3494;
+	private static final int Q_SILVER_UNDINE = 3495;
+	private static final int Q_BERETHS_SILVER_DRAGON = 3496;
+	private static final int Q_MANAKS_SILVER_DRYAD = 3497;
+	private static final int Q_NIAS_SILVER_FAIRY = 3498;
+	private static final int Q_COIN_DIAGRAM = 3811;
+	private static final int Q_KALDIS_GOLD_DRAGON = 3812;
+	private static final int Q_CC_MEMBERSHIP_1 = 3813;
+	private static final int Q_CC_MEMBERSHIP_2 = 3814;
+	private static final int Q_CC_MEMBERSHIP_3 = 3815;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			// Gold Wyvern
+			.addSingleDrop(SHACKLE, Q_GOLD_WYVERN, 7.0)
+			.addSingleDrop(SHACKLE_HOLD, Q_GOLD_WYVERN, 7.0)
+			.addSingleDrop(HEADLESS_KNIGHT, Q_GOLD_WYVERN, 8.0)
+			.addSingleDrop(TIMAK_ORC, Q_GOLD_WYVERN, 8.0)
+			.addSingleDrop(HEADLESS_KNIGHT_HOLD, Q_GOLD_WYVERN, 8.5)
+			.bulkAddSingleDrop(Q_GOLD_WYVERN, 10.0)
+				.withNpcs(ROYAL_CAVE_SERVANT, MALRUK_SUCCUBUS_TUREN, ROYAL_CAVE_SERVANT_HOLD, KUKABURO_B, ANTELOPE, ANTELOPE_A, ANTELOPE_B, H_MALRUK_SUCCUBUS_TUREN).build()
+			.bulkAddSingleDrop(Q_GOLD_WYVERN, 11.0)
+				.withNpcs(BUFFALO, BUFFALO_A, BUFFALO_B, KUKABURO, KUKABURO_A).build()
+			.addSingleDrop(DOOM_SERVANT, Q_GOLD_WYVERN, 14.0)
+			.addSingleDrop(DOOM_KNIGHT, Q_GOLD_WYVERN, 21.0)
+			// Silver Unicorn
+			.addSingleDrop(VANOR_SILENOS_SHAMAN, Q_SILVER_UNICORN, 7.0)
+			.bulkAddSingleDrop(Q_SILVER_UNICORN, 8.0)
+				.withNpcs(BLOODY_GHOST, TARLK_BUGBEAR_BOSS, OEL_MAHUM).build()
+			.addSingleDrop(OEL_MAHUM_WARRIOR, Q_SILVER_UNICORN, 9.0)
+			.addSingleDrop(HUNGRY_CORPSE, Q_SILVER_UNICORN, 10.0)
+			.addSingleDrop(BYFOOT, Q_SILVER_UNICORN, 11.0)
+			.addSingleDrop(BYFOOT_SIGEL, Q_SILVER_UNICORN, 12.0)
+			.bulkAddSingleDrop(Q_SILVER_UNICORN, 15.0)
+				.withNpcs(DARK_GUARD, BRILLIANT_CLAW, BRILLIANT_CLAW_1).build()
+			.addSingleDrop(OEL_MAHUM_WITCH_DOCTOR, Q_SILVER_UNICORN, 20.0)
+			.addSingleDrop(BRILLIANT_ANGUISH, Q_SILVER_UNICORN, 21.0)
+			.addSingleDrop(BRILLIANT_ANGUISH_1, Q_SILVER_UNICORN, 21.0)
+			// Blood Medusa
+			.addSingleDrop(LAKIN, Q_BLOOD_MEDUSA, 6.0)
+			.addSingleDrop(HATAR_HANISHEE, Q_BLOOD_MEDUSA, 7.0)
+			.addSingleDrop(PUNISHMENT_OF_UNDEAD, Q_BLOOD_MEDUSA, 8.0)
+			.bulkAddSingleDrop(Q_BLOOD_MEDUSA, 9.0)
+				.withNpcs(FLOAT_OF_GRAVE, BANDERSNATCH_A, BANDERSNATCH_B).build()
+			.addSingleDrop(BANDERSNATCH, Q_BLOOD_MEDUSA, 10.0)
+			.addSingleDrop(NIHIL_INVADER, Q_BLOOD_MEDUSA, 11.0)
+			.addSingleDrop(TIMAK_ORC_SHAMAN, Q_BLOOD_MEDUSA, 13.0)
+			.addSingleDrop(TIMAK_ORC_ARCHER, Q_BLOOD_MEDUSA, 14.0)
+			.addSingleDrop(TIMAK_ORC_SOLDIER, Q_BLOOD_MEDUSA, 14.0)
+			.bulkAddSingleDrop(Q_BLOOD_MEDUSA, 16.0)
+				.withNpcs(DOOM_ARCHER, BRILLIANT_WISDOM, BRILLIANT_VENGEANCE, BRILLIANT_VENGEANCE_1).build()
+			.build();
 	// Rewards
 	private static final int DEMON_STAFF = 206;
 	private static final int DARK_SCREAMER = 233;
@@ -893,200 +935,20 @@ public final class Q00336_CoinsOfMagic extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
-		
 		switch (npc.getId()) {
-			case HARIT_LIZARDMAN_SHAMAN:
-			case HARIT_LIZARDM_MATRIARCH: {
+			case HARIT_LIZARDMAN_SHAMAN, HARIT_LIZARDM_MATRIARCH -> {
 				QuestState qs = getRandomPlayerFromPartyCoin(killer, npc, 2);
-				if (qs != null) {
-					if (getRandom(1000) < 63) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_KALDIS_GOLD_DRAGON, 1, 0, 1, true);
-						qs.setCond(3);
-						qs.showQuestionMark(336);
-					}
+				if (qs != null && giveItemRandomly(qs.getPlayer(), npc, Q_KALDIS_GOLD_DRAGON, true)) {
+					qs.setCond(3);
+					qs.showQuestionMark(336);
 				}
 				return super.onKill(npc, killer, isSummon);
 			}
 		}
+
 		final QuestState qs = getRandomPlayerFromParty(killer, npc, 3);
 		if (qs != null) {
-			switch (npc.getId()) {
-				case SHACKLE:
-				case SHACKLE_HOLD: {
-					if (getRandom(1000) < 70) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_GOLD_WYVERN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case HEADLESS_KNIGHT:
-				case TIMAK_ORC: {
-					if (getRandom(1000) < 80) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_GOLD_WYVERN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case HEADLESS_KNIGHT_HOLD: {
-					if (getRandom(1000) < 85) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_GOLD_WYVERN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case ROYAL_CAVE_SERVANT:
-				case MALRUK_SUCCUBUS_TUREN:
-				case ROYAL_CAVE_SERVANT_HOLD:
-				case KUKABURO_B:
-				case ANTELOPE:
-				case ANTELOPE_A:
-				case ANTELOPE_B:
-				case H_MALRUK_SUCCUBUS_TUREN: {
-					if (getRandom(1000) < 100) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_GOLD_WYVERN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case BUFFALO:
-				case BUFFALO_A:
-				case BUFFALO_B:
-				case KUKABURO:
-				case KUKABURO_A: {
-					if (getRandom(1000) < 110) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_GOLD_WYVERN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case DOOM_SERVANT: {
-					if (getRandom(1000) < 140) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_GOLD_WYVERN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case DOOM_KNIGHT: {
-					if (getRandom(1000) < 210) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_GOLD_WYVERN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case VANOR_SILENOS_SHAMAN: {
-					if (getRandom(1000) < 70) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_SILVER_UNICORN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case BLOODY_GHOST:
-				case TARLK_BUGBEAR_BOSS:
-				case OEL_MAHUM: {
-					if (getRandom(1000) < 80) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_SILVER_UNICORN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case OEL_MAHUM_WARRIOR: {
-					if (getRandom(1000) < 90) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_SILVER_UNICORN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case HUNGRY_CORPSE: {
-					if (getRandom(1000) < 100) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_SILVER_UNICORN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case BYFOOT: {
-					if (getRandom(1000) < 110) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_SILVER_UNICORN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case BYFOOT_SIGEL: {
-					if (getRandom(1000) < 120) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_SILVER_UNICORN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case DARK_GUARD:
-				case BRILLIANT_CLAW:
-				case BRILLIANT_CLAW_1: {
-					if (getRandom(1000) < 150) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_SILVER_UNICORN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case OEL_MAHUM_WITCH_DOCTOR: {
-					if (getRandom(1000) < 200) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_SILVER_UNICORN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case BRILLIANT_ANGUISH:
-				case BRILLIANT_ANGUISH_1: {
-					if (getRandom(1000) < 210) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_SILVER_UNICORN, 1, 0, 1, true);
-					}
-					break;
-				}
-				case LAKIN: {
-					if (getRandom(1000) < 60) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_BLOOD_MEDUSA, 1, 0, 1, true);
-					}
-					break;
-				}
-				case HATAR_HANISHEE: {
-					if (getRandom(1000) < 70) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_BLOOD_MEDUSA, 1, 0, 1, true);
-					}
-					break;
-				}
-				case PUNISHMENT_OF_UNDEAD: {
-					if (getRandom(1000) < 80) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_BLOOD_MEDUSA, 1, 0, 1, true);
-					}
-					break;
-				}
-				case FLOAT_OF_GRAVE:
-				case BANDERSNATCH_A:
-				case BANDERSNATCH_B: {
-					if (getRandom(1000) < 90) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_BLOOD_MEDUSA, 1, 0, 1, true);
-					}
-					break;
-				}
-				case BANDERSNATCH: {
-					if (getRandom(1000) < 100) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_BLOOD_MEDUSA, 1, 0, 1, true);
-					}
-					break;
-				}
-				case NIHIL_INVADER: {
-					if (getRandom(1000) < 110) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_BLOOD_MEDUSA, 1, 0, 1, true);
-					}
-					break;
-				}
-				case TIMAK_ORC_SHAMAN: {
-					if (getRandom(1000) < 130) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_BLOOD_MEDUSA, 1, 0, 1, true);
-					}
-					break;
-				}
-				case TIMAK_ORC_ARCHER:
-				case TIMAK_ORC_SOLDIER: {
-					if (getRandom(1000) < 140) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_BLOOD_MEDUSA, 1, 0, 1, true);
-					}
-					break;
-				}
-				case DOOM_ARCHER:
-				case BRILLIANT_WISDOM:
-				case BRILLIANT_VENGEANCE:
-				case BRILLIANT_VENGEANCE_1: {
-					if (getRandom(1000) < 160) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_BLOOD_MEDUSA, 1, 0, 1, true);
-					}
-					break;
-				}
-			}
-			
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00340_SubjugationOfLizardmen/Q00340_SubjugationOfLizardmen.java b/src/main/java/com/l2jserver/datapack/quests/Q00340_SubjugationOfLizardmen/Q00340_SubjugationOfLizardmen.java
index 9e67f62dbe..1b2c6b88ad 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00340_SubjugationOfLizardmen/Q00340_SubjugationOfLizardmen.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00340_SubjugationOfLizardmen/Q00340_SubjugationOfLizardmen.java
@@ -21,7 +21,9 @@ package com.l2jserver.datapack.quests.Q00340_SubjugationOfLizardmen;
 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.util.Util;
 
@@ -35,11 +37,6 @@ public final class Q00340_SubjugationOfLizardmen extends Quest {
 	private static final int PRIEST_ADONIUS = 30375;
 	private static final int GUARD_WEISZ = 30385;
 	private static final int CHEST_OF_BIFRONS = 30989;
-	// Items
-	private static final int TRADE_CARGO = 4255;
-	private static final int AGNESS_HOLY_SYMBOL = 4256;
-	private static final int AGNESS_ROSARY = 4257;
-	private static final int SINISTER_TOTEM = 4258;
 	// Monster
 	private static final int FELIM_LIZARDMAN = 20008;
 	private static final int FELIM_LIZARDMAN_SCOUT = 20010;
@@ -47,6 +44,17 @@ public final class Q00340_SubjugationOfLizardmen extends Quest {
 	private static final int LANGK_LIZARDMAN_WARRIOR = 20024;
 	private static final int LANGK_LIZARDMAN_SCOUT = 20027;
 	private static final int LANGK_LIZARDMAN = 20030;
+	// Items
+	private static final int AGNESS_HOLY_SYMBOL = 4256;
+	private static final int AGNESS_ROSARY = 4257;
+	private static final int SINISTER_TOTEM = 4258;
+	private static final QuestItemChanceHolder TRADE_CARGO = new QuestItemChanceHolder(4255, 30L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(FELIM_LIZARDMAN, TRADE_CARGO, 63.0)
+			.addSingleDrop(FELIM_LIZARDMAN_SCOUT, TRADE_CARGO, 63.0)
+			.addSingleDrop(FELIM_LIZARDMAN_WARRIOR, TRADE_CARGO, 68.0)
+			.build();
 	// Raid Boss
 	private static final int SERPENT_DEMON_BIFRONS = 25146;
 	// Misc
@@ -57,7 +65,7 @@ public final class Q00340_SubjugationOfLizardmen extends Quest {
 		addStartNpc(GUARD_WEISZ);
 		addTalkId(GUARD_WEISZ, HIGH_PRIESTESS_LEVIAN, PRIEST_ADONIUS, CHEST_OF_BIFRONS);
 		addKillId(FELIM_LIZARDMAN, FELIM_LIZARDMAN_SCOUT, FELIM_LIZARDMAN_WARRIOR, LANGK_LIZARDMAN_WARRIOR, LANGK_LIZARDMAN_SCOUT, LANGK_LIZARDMAN, SERPENT_DEMON_BIFRONS);
-		registerQuestItems(TRADE_CARGO, AGNESS_HOLY_SYMBOL, AGNESS_ROSARY, SINISTER_TOTEM);
+		registerQuestItems(TRADE_CARGO.getId(), AGNESS_HOLY_SYMBOL, AGNESS_ROSARY, SINISTER_TOTEM);
 	}
 	
 	@Override
@@ -83,25 +91,25 @@ public final class Q00340_SubjugationOfLizardmen extends Quest {
 				break;
 			}
 			case "30385-07.html": {
-				takeItems(player, TRADE_CARGO, -1);
+				takeItems(player, TRADE_CARGO.getId(), -1);
 				qs.setMemoState(2);
 				qs.setCond(2, true);
 				htmltext = event;
 				break;
 			}
 			case "30385-09.html": {
-				if (getQuestItemsCount(player, TRADE_CARGO) >= 30) {
+				if (hasItemsAtLimit(player, TRADE_CARGO)) {
 					giveAdena(player, 4090, true);
-					takeItems(player, TRADE_CARGO, -1);
+					takeItems(player, TRADE_CARGO.getId(), -1);
 					qs.setMemoState(1);
 					htmltext = event;
 				}
 				break;
 			}
 			case "30385-10.html": {
-				if (getQuestItemsCount(player, TRADE_CARGO) >= 30) {
+				if (hasItemsAtLimit(player, TRADE_CARGO)) {
 					giveAdena(player, 4090, true);
-					takeItems(player, TRADE_CARGO, -1);
+					takeItems(player, TRADE_CARGO.getId(), -1);
 					qs.exitQuest(false, true);
 					htmltext = event;
 				}
@@ -139,20 +147,12 @@ public final class Q00340_SubjugationOfLizardmen extends Quest {
 		final QuestState qs = getQuestState(killer, false);
 		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, killer, true)) {
 			switch (npc.getId()) {
-				case FELIM_LIZARDMAN:
-				case FELIM_LIZARDMAN_SCOUT: {
+				case FELIM_LIZARDMAN, FELIM_LIZARDMAN_SCOUT, FELIM_LIZARDMAN_WARRIOR -> {
 					if (qs.isMemoState(1)) {
-						giveItemRandomly(killer, npc, TRADE_CARGO, 1, 30, 0.63, true);
+						giveItemRandomly(killer, npc, DROPLIST.get(npc), true);
 					}
-					break;
 				}
-				case FELIM_LIZARDMAN_WARRIOR: {
-					if (qs.isMemoState(1)) {
-						giveItemRandomly(killer, npc, TRADE_CARGO, 1, 30, 0.68, true);
-					}
-					break;
-				}
-				case LANGK_LIZARDMAN_WARRIOR: {
+				case LANGK_LIZARDMAN_WARRIOR -> {
 					if (qs.isMemoState(3)) {
 						if (!hasQuestItems(killer, AGNESS_HOLY_SYMBOL) && (getRandom(100) <= 19)) {
 							giveItems(killer, AGNESS_HOLY_SYMBOL, 1);
@@ -162,10 +162,8 @@ public final class Q00340_SubjugationOfLizardmen extends Quest {
 							playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
 						}
 					}
-					break;
 				}
-				case LANGK_LIZARDMAN_SCOUT:
-				case LANGK_LIZARDMAN: {
+				case LANGK_LIZARDMAN_SCOUT, LANGK_LIZARDMAN -> {
 					if (qs.isMemoState(3)) {
 						if (!hasQuestItems(killer, AGNESS_HOLY_SYMBOL) && (getRandom(100) <= 18)) {
 							giveItems(killer, AGNESS_HOLY_SYMBOL, 1);
@@ -175,12 +173,8 @@ public final class Q00340_SubjugationOfLizardmen extends Quest {
 							playSound(killer, Sound.ITEMSOUND_QUEST_ITEMGET);
 						}
 					}
-					break;
-				}
-				case SERPENT_DEMON_BIFRONS: {
-					addSpawn(CHEST_OF_BIFRONS, npc, true, 30000);
-					break;
 				}
+				case SERPENT_DEMON_BIFRONS -> addSpawn(CHEST_OF_BIFRONS, npc, true, 30000);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -199,7 +193,7 @@ public final class Q00340_SubjugationOfLizardmen extends Quest {
 			switch (npc.getId()) {
 				case GUARD_WEISZ: {
 					if (memoState == 1) {
-						if (getQuestItemsCount(player, TRADE_CARGO) < 30) {
+						if (!hasItemsAtLimit(player, TRADE_CARGO)) {
 							htmltext = "30385-05.html";
 						} else {
 							htmltext = "30385-06.html";
@@ -264,4 +258,4 @@ public final class Q00340_SubjugationOfLizardmen extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00344_1000YearsTheEndOfLamentation/Q00344_1000YearsTheEndOfLamentation.java b/src/main/java/com/l2jserver/datapack/quests/Q00344_1000YearsTheEndOfLamentation/Q00344_1000YearsTheEndOfLamentation.java
index f75b071c85..e0a4098bca 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00344_1000YearsTheEndOfLamentation/Q00344_1000YearsTheEndOfLamentation.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00344_1000YearsTheEndOfLamentation/Q00344_1000YearsTheEndOfLamentation.java
@@ -18,13 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00344_1000YearsTheEndOfLamentation;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestDroplist;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
 /**
@@ -44,20 +42,19 @@ public final class Q00344_1000YearsTheEndOfLamentation extends Quest {
 	private static final ItemHolder OLD_HILT = new ItemHolder(4271, 1);
 	private static final ItemHolder TOTEM_NECKLACE = new ItemHolder(4272, 1);
 	private static final ItemHolder CRUCIFIX = new ItemHolder(4273, 1);
-	// Monsters
-	private static final Map<Integer, Double> MONSTER_CHANCES = new HashMap<>();
-	{
-		MONSTER_CHANCES.put(20236, 0.58); // Cave Servant
-		MONSTER_CHANCES.put(20238, 0.75); // Cave Servant Warrior
-		MONSTER_CHANCES.put(20237, 0.78); // Cave Servant Archer
-		MONSTER_CHANCES.put(20239, 0.79); // Cave Servant Captain
-		MONSTER_CHANCES.put(20240, 0.85); // Royal Cave Servant
-		MONSTER_CHANCES.put(20272, 0.58); // Cave Servant
-		MONSTER_CHANCES.put(20273, 0.78); // Cave Servant Archer
-		MONSTER_CHANCES.put(20274, 0.75); // Cave Servant Warrior
-		MONSTER_CHANCES.put(20275, 0.79); // Cave Servant Captain
-		MONSTER_CHANCES.put(20276, 0.85); // Royal Cave Servant
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20236, ARTICLES, 58.0) // Cave Servant
+			.addSingleDrop(20238, ARTICLES, 75.0) // Cave Servant Warrior
+			.addSingleDrop(20237, ARTICLES, 78.0) // Cave Servant Archer
+			.addSingleDrop(20239, ARTICLES, 79.0) // Cave Servant Captain
+			.addSingleDrop(20240, ARTICLES, 85.0) // Royal Cave Servant
+			.addSingleDrop(20272, ARTICLES, 58.0) // Cave Servant
+			.addSingleDrop(20273, ARTICLES, 78.0) // Cave Servant Archer
+			.addSingleDrop(20274, ARTICLES, 75.0) // Cave Servant Warrior
+			.addSingleDrop(20275, ARTICLES, 79.0) // Cave Servant Captain
+			.addSingleDrop(20276, ARTICLES, 85.0) // Royal Cave Servant
+			.build();
 	// Rewards
 	private static final ItemHolder ORIHARUKON_ORE = new ItemHolder(1874, 25);
 	private static final ItemHolder VARNISH_OF_PURITY = new ItemHolder(1887, 10);
@@ -78,7 +75,7 @@ public final class Q00344_1000YearsTheEndOfLamentation extends Quest {
 		super(344, Q00344_1000YearsTheEndOfLamentation.class.getSimpleName(), "1000 years, the End of Lamentation");
 		addStartNpc(GILMORE);
 		addTalkId(KAIEN, GARVARENTZ, GILMORE, RODEMAI, ORVEN);
-		addKillId(MONSTER_CHANCES.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(ARTICLES, OLD_KEY.getId(), OLD_HILT.getId(), TOTEM_NECKLACE.getId(), CRUCIFIX.getId());
 	}
 	
@@ -287,7 +284,7 @@ public final class Q00344_1000YearsTheEndOfLamentation extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 1, 3, npc);
 		if (qs != null) {
-			giveItemRandomly(qs.getPlayer(), npc, ARTICLES, 1, 0, MONSTER_CHANCES.get(npc.getId()), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00347_GoGetTheCalculator/Q00347_GoGetTheCalculator.java b/src/main/java/com/l2jserver/datapack/quests/Q00347_GoGetTheCalculator/Q00347_GoGetTheCalculator.java
index 74fdff7c9d..1bff9b0e92 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00347_GoGetTheCalculator/Q00347_GoGetTheCalculator.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00347_GoGetTheCalculator/Q00347_GoGetTheCalculator.java
@@ -20,6 +20,7 @@ package com.l2jserver.datapack.quests.Q00347_GoGetTheCalculator;
 
 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.itemcontainer.Inventory;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
@@ -37,7 +38,7 @@ public final class Q00347_GoGetTheCalculator extends Quest {
 	private static final int BALANKI = 30533;
 	// Items
 	private static final int STOLEN_CALCULATOR = 4285;
-	private static final int GEMSTONE = 4286;
+	private static final QuestItemChanceHolder GEMSTONE = new QuestItemChanceHolder(4286, 40.0, 10L);
 	// Monster
 	private static final int GEMSTONE_BEAST = 20540;
 	// Reward
@@ -51,7 +52,7 @@ public final class Q00347_GoGetTheCalculator extends Quest {
 		addStartNpc(BRUNON);
 		addTalkId(BRUNON, SILVERA, SPIRON, BALANKI);
 		addKillId(GEMSTONE_BEAST);
-		registerQuestItems(STOLEN_CALCULATOR, GEMSTONE);
+		registerQuestItems(STOLEN_CALCULATOR, GEMSTONE.getId());
 	}
 	
 	@Override
@@ -189,7 +190,7 @@ public final class Q00347_GoGetTheCalculator extends Quest {
 								break;
 							}
 							case 5: {
-								takeItems(talker, GEMSTONE, -1);
+								takeItems(talker, GEMSTONE.getId(), -1);
 								giveItems(talker, STOLEN_CALCULATOR, 1);
 								qs.setCond(6, true);
 								htmltext = "30527-03.html";
@@ -217,7 +218,7 @@ public final class Q00347_GoGetTheCalculator extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 4, 3, npc);
 		if (qs != null) {
-			if (giveItemRandomly(qs.getPlayer(), npc, GEMSTONE, 1, 10, 0.4, true)) {
+			if (giveItemRandomly(qs.getPlayer(), npc, GEMSTONE, true)) {
 				qs.setCond(5);
 			}
 		}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00351_BlackSwan/Q00351_BlackSwan.java b/src/main/java/com/l2jserver/datapack/quests/Q00351_BlackSwan/Q00351_BlackSwan.java
index 5611b1cf87..b8d620e0c0 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00351_BlackSwan/Q00351_BlackSwan.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00351_BlackSwan/Q00351_BlackSwan.java
@@ -18,15 +18,14 @@
  */
 package com.l2jserver.datapack.quests.Q00351_BlackSwan;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00345_MethodToRaiseTheDead.Q00345_MethodToRaiseTheDead;
 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.util.Util;
+
+import static com.l2jserver.gameserver.model.quest.QuestDroplist.singleDropItem;
 
 /**
  * Black Swan (351)
@@ -37,26 +36,26 @@ public final class Q00351_BlackSwan extends Quest {
 	private static final int ROMAN = 30897;
 	private static final int GOSTA = 30916;
 	private static final int IASON_HEINE = 30969;
+	// Monsters
+	private static final int TASABA_LIZARDMAN1 = 20784;
+	private static final int TASABA_LIZARDMAN_SHAMAN1 = 20785;
+	private static final int TASABA_LIZARDMAN2 = 21639;
+	private static final int TASABA_LIZARDMAN_SHAMAN2 = 21640;
 	// Items
 	private static final int ORDER_OF_GOSTA = 4296;
 	private static final int LIZARD_FANG = 4297;
 	private static final int BARREL_OF_LEAGUE = 4298;
 	private static final int BILL_OF_IASON_HEINE = 4407;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(TASABA_LIZARDMAN1, BARREL_OF_LEAGUE, 4.0)
+			.addSingleDrop(TASABA_LIZARDMAN_SHAMAN1, BARREL_OF_LEAGUE, 3.0)
+			.addSingleDrop(TASABA_LIZARDMAN2, BARREL_OF_LEAGUE, 4.0)
+			.addSingleDrop(TASABA_LIZARDMAN_SHAMAN2, BARREL_OF_LEAGUE, 3.0)
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 32;
-	// Monsters
-	private static final int TASABA_LIZARDMAN1 = 20784;
-	private static final int TASABA_LIZARDMAN_SHAMAN1 = 20785;
-	private static final int TASABA_LIZARDMAN2 = 21639;
-	private static final int TASABA_LIZARDMAN_SHAMAN2 = 21640;
-	private static final Map<Integer, Integer> MONSTER_DROP_CHANCES = new HashMap<>();
-	static {
-		MONSTER_DROP_CHANCES.put(TASABA_LIZARDMAN1, 4);
-		MONSTER_DROP_CHANCES.put(TASABA_LIZARDMAN_SHAMAN1, 3);
-		MONSTER_DROP_CHANCES.put(TASABA_LIZARDMAN2, 4);
-		MONSTER_DROP_CHANCES.put(TASABA_LIZARDMAN_SHAMAN2, 3);
-	}
-	
+
 	public Q00351_BlackSwan() {
 		super(351, Q00351_BlackSwan.class.getSimpleName(), "Black Swan");
 		addStartNpc(GOSTA, ROMAN);
@@ -129,25 +128,25 @@ public final class Q00351_BlackSwan extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		
-		if ((qs == null) || !Util.checkIfInRange(1500, npc, killer, true)) {
+		if (qs == null) {
 			return null;
 		}
 		
 		final int random = getRandom(20);
 		if (random < 10) {
-			giveItemRandomly(qs.getPlayer(), npc, LIZARD_FANG, 1, 0, 1.0, true);
+			giveItemRandomly(qs.getPlayer(), npc, LIZARD_FANG, true);
 			
 			if (getRandom(20) == 0) {
-				giveItemRandomly(qs.getPlayer(), npc, BARREL_OF_LEAGUE, 1, 0, 1.0, false);
+				giveItemRandomly(qs.getPlayer(), npc, BARREL_OF_LEAGUE, false);
 			}
 		} else if (random < 15) {
-			giveItemRandomly(qs.getPlayer(), npc, LIZARD_FANG, 2, 0, 1.0, true);
+			giveItemRandomly(qs.getPlayer(), npc, singleDropItem(LIZARD_FANG, 2L), 0, true);
 			
 			if (getRandom(20) == 0) {
-				giveItemRandomly(qs.getPlayer(), npc, BARREL_OF_LEAGUE, 1, 0, 1.0, false);
+				giveItemRandomly(qs.getPlayer(), npc, BARREL_OF_LEAGUE, false);
 			}
-		} else if (getRandom(100) < MONSTER_DROP_CHANCES.get(npc.getId())) {
-			giveItemRandomly(qs.getPlayer(), npc, BARREL_OF_LEAGUE, 1, 0, 1.0, true);
+		} else {
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		
 		return super.onKill(npc, killer, isSummon);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00352_HelpRoodRaiseANewPet/Q00352_HelpRoodRaiseANewPet.java b/src/main/java/com/l2jserver/datapack/quests/Q00352_HelpRoodRaiseANewPet/Q00352_HelpRoodRaiseANewPet.java
index 1547159300..2dfa207a4e 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00352_HelpRoodRaiseANewPet/Q00352_HelpRoodRaiseANewPet.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00352_HelpRoodRaiseANewPet/Q00352_HelpRoodRaiseANewPet.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00352_HelpRoodRaiseANewPet;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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.util.Util;
 
@@ -32,44 +30,31 @@ import com.l2jserver.gameserver.util.Util;
  * @author Adry_85
  */
 public final class Q00352_HelpRoodRaiseANewPet extends Quest {
-	private static final class DropInfo {
-		public final int _firstChance;
-		public final int _secondChance;
-		
-		public DropInfo(int firstChance, int secondChance) {
-			_firstChance = firstChance;
-			_secondChance = secondChance;
-		}
-		
-		public int getFirstChance() {
-			return _firstChance;
-		}
-		
-		public int getSecondChance() {
-			return _secondChance;
-		}
-	}
-	
 	// NPC
 	private static final int ROOD = 31067;
 	// Items
 	private static final int LIENRIK_EGG1 = 5860;
 	private static final int LIENRIK_EGG2 = 5861;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addGroupedDrop(20786, 48.0) // lienrik
+				.withDropItem(LIENRIK_EGG1, 95.83)
+				.withDropItem(LIENRIK_EGG2, 4.17).build()
+			.addGroupedDrop(21644, 48.0) // lienrik_a
+				.withDropItem(LIENRIK_EGG1, 95.83)
+				.withDropItem(LIENRIK_EGG2, 4.17).build()
+			.addGroupedDrop(21645, 71.0) // lienrik_lad_a
+				.withDropItem(LIENRIK_EGG1, 97.18)
+				.withDropItem(LIENRIK_EGG2, 2.82).build()
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 39;
 	
-	private static final Map<Integer, DropInfo> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20786, new DropInfo(46, 48)); // lienrik
-		MOBS.put(21644, new DropInfo(46, 48)); // lienrik_a
-		MOBS.put(21645, new DropInfo(69, 71)); // lienrik_lad_a
-	}
-	
 	public Q00352_HelpRoodRaiseANewPet() {
 		super(352, Q00352_HelpRoodRaiseANewPet.class.getSimpleName(), "Help Rood Raise A New Pet!");
 		addStartNpc(ROOD);
 		addTalkId(ROOD);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(LIENRIK_EGG1, LIENRIK_EGG2);
 	}
 	
@@ -111,15 +96,9 @@ public final class Q00352_HelpRoodRaiseANewPet extends Quest {
 		if ((qs == null) || !Util.checkIfInRange(1500, npc, killer, true)) {
 			return null;
 		}
-		
-		final DropInfo info = MOBS.get(npc.getId());
-		final int random = getRandom(100);
-		
-		if (random < info.getFirstChance()) {
-			qs.giveItemRandomly(npc, LIENRIK_EGG1, 1, 0, 1.0, true);
-		} else if (random < info.getSecondChance()) {
-			qs.giveItemRandomly(npc, LIENRIK_EGG2, 1, 0, 1.0, true);
-		}
+
+		giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
+
 		return super.onKill(npc, killer, isSummon);
 	}
 	
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00354_ConquestOfAlligatorIsland/Q00354_ConquestOfAlligatorIsland.java b/src/main/java/com/l2jserver/datapack/quests/Q00354_ConquestOfAlligatorIsland/Q00354_ConquestOfAlligatorIsland.java
index 6f601a75d3..764a213911 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00354_ConquestOfAlligatorIsland/Q00354_ConquestOfAlligatorIsland.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00354_ConquestOfAlligatorIsland/Q00354_ConquestOfAlligatorIsland.java
@@ -18,12 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00354_ConquestOfAlligatorIsland;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -35,29 +34,26 @@ public final class Q00354_ConquestOfAlligatorIsland extends Quest {
 	private static final int KLUCK = 30895;
 	// Items
 	private static final int ALLIGATOR_TOOTH = 5863;
-	private static final int MYSTERIOUS_MAP_PIECE = 5864;
 	private static final int PIRATES_TREASURE_MAP = 5915;
+	private static final QuestItemChanceHolder MYSTERIOUS_MAP_PIECE = new QuestItemChanceHolder(5864, 10.0);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20804, ALLIGATOR_TOOTH, 84.0) // crokian_lad
+			.addSingleDrop(20805, ALLIGATOR_TOOTH, 91.0) // dailaon_lad
+			.addSingleDrop(20806, ALLIGATOR_TOOTH, 88.0) // crokian_lad_warrior
+			.addSingleDrop(20807, ALLIGATOR_TOOTH, 92.0) // farhite_lad
+			.addSingleDrop(22208, ALLIGATOR_TOOTH, 114.0) // nos_lad
+			.addSingleDrop(20991, ALLIGATOR_TOOTH, 169.0) // tribe_of_swamp
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 38;
-	// Mobs
-	private static final Map<Integer, Double> MOB1 = new HashMap<>();
-	private static final Map<Integer, Integer> MOB2 = new HashMap<>();
-	static {
-		MOB1.put(20804, 0.84); // crokian_lad
-		MOB1.put(20805, 0.91); // dailaon_lad
-		MOB1.put(20806, 0.88); // crokian_lad_warrior
-		MOB1.put(20807, 0.92); // farhite_lad
-		MOB2.put(22208, 14); // nos_lad
-		MOB2.put(20991, 69); // tribe_of_swamp
-	}
 	
 	public Q00354_ConquestOfAlligatorIsland() {
 		super(354, Q00354_ConquestOfAlligatorIsland.class.getSimpleName(), "Conquest of Alligator Island");
 		addStartNpc(KLUCK);
 		addTalkId(KLUCK);
-		addKillId(MOB1.keySet());
-		addKillId(MOB2.keySet());
-		registerQuestItems(ALLIGATOR_TOOTH, MYSTERIOUS_MAP_PIECE);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(ALLIGATOR_TOOTH, MYSTERIOUS_MAP_PIECE.getId());
 	}
 	
 	@Override
@@ -101,10 +97,10 @@ public final class Q00354_ConquestOfAlligatorIsland extends Quest {
 				break;
 			}
 			case "REWARD": {
-				final long count = st.getQuestItemsCount(MYSTERIOUS_MAP_PIECE);
+				final long count = st.getQuestItemsCount(MYSTERIOUS_MAP_PIECE.getId());
 				if (count >= 10) {
 					st.giveItems(PIRATES_TREASURE_MAP, 1);
-					st.takeItems(MYSTERIOUS_MAP_PIECE, 10);
+					st.takeItems(MYSTERIOUS_MAP_PIECE.getId(), 10);
 					htmltext = "30895-13.html";
 				} else if (count > 0) {
 					htmltext = "30895-12.html";
@@ -116,20 +112,13 @@ public final class Q00354_ConquestOfAlligatorIsland extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final QuestState st = getRandomPartyMemberState(player, -1, 3, npc);
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		final QuestState st = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (st != null) {
-			int npcId = npc.getId();
-			if (MOB1.containsKey(npcId)) {
-				st.giveItemRandomly(npc, ALLIGATOR_TOOTH, 1, 0, MOB1.get(npcId), true);
-			} else {
-				final int itemCount = ((getRandom(100) < MOB2.get(npcId)) ? 2 : 1);
-				st.giveItemRandomly(npc, ALLIGATOR_TOOTH, itemCount, 0, 1.0, true);
-			}
-			
-			st.giveItemRandomly(npc, MYSTERIOUS_MAP_PIECE, 1, 0, 0.1, false);
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
+			giveItemRandomly(st.getPlayer(), npc, MYSTERIOUS_MAP_PIECE, false);
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
@@ -139,7 +128,7 @@ public final class Q00354_ConquestOfAlligatorIsland extends Quest {
 		if (st.isCreated()) {
 			htmltext = ((player.getLevel() >= MIN_LEVEL) ? "30895-01.htm" : "30895-03.html");
 		} else if (st.isStarted()) {
-			htmltext = (st.hasQuestItems(MYSTERIOUS_MAP_PIECE) ? "30895-11.html" : "30895-04.html");
+			htmltext = (st.hasQuestItems(MYSTERIOUS_MAP_PIECE.getId()) ? "30895-11.html" : "30895-04.html");
 		}
 		return htmltext;
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00355_FamilyHonor/Q00355_FamilyHonor.java b/src/main/java/com/l2jserver/datapack/quests/Q00355_FamilyHonor/Q00355_FamilyHonor.java
index 902c31bd8f..f234521067 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00355_FamilyHonor/Q00355_FamilyHonor.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00355_FamilyHonor/Q00355_FamilyHonor.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00355_FamilyHonor;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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.util.Util;
 
@@ -60,22 +58,33 @@ public final class Q00355_FamilyHonor extends Quest {
 	private static final int ANCIENT_STATUE_ORIGINAL = 4352;
 	private static final int ANCIENT_STATUE_REPLICA = 4353;
 	private static final int ANCIENT_STATUE_FORGERY = 4354;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addGroupedDrop(20767, 68.4) // timak_orc_troop_leader
+				.withDropItem(GALFREDO_ROMERS_BUST, 81.87)
+				.withDropItem(SCULPTOR_BERONA, 18.13)
+				.build()
+			.addGroupedDrop(20768, 65.0) // timak_orc_troop_shaman
+				.withDropItem(GALFREDO_ROMERS_BUST, 81.54)
+				.withDropItem(SCULPTOR_BERONA, 18.46)
+				.build()
+			.addGroupedDrop(20769, 51.6) // timak_orc_troop_warrior
+				.withDropItem(GALFREDO_ROMERS_BUST, 81.4)
+				.withDropItem(SCULPTOR_BERONA, 18.6)
+				.build()
+			.addGroupedDrop(20770, 56.0) // timak_orc_troop_archer
+				.withDropItem(GALFREDO_ROMERS_BUST, 78.57)
+				.withDropItem(SCULPTOR_BERONA, 21.43)
+				.build()
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 36;
 	
-	private static final Map<Integer, DropInfo> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20767, new DropInfo(560, 684)); // timak_orc_troop_leader
-		MOBS.put(20768, new DropInfo(530, 650)); // timak_orc_troop_shaman
-		MOBS.put(20769, new DropInfo(420, 516)); // timak_orc_troop_warrior
-		MOBS.put(20770, new DropInfo(440, 560)); // timak_orc_troop_archer
-	}
-	
 	public Q00355_FamilyHonor() {
 		super(355, Q00355_FamilyHonor.class.getSimpleName(), "Family Honor");
 		addStartNpc(GALIBREDO);
 		addTalkId(GALIBREDO, PATRIN);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(GALFREDO_ROMERS_BUST);
 	}
 	
@@ -162,18 +171,12 @@ public final class Q00355_FamilyHonor extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getQuestState(killer, false);
 		
-		if ((qs == null) || !Util.checkIfInRange(1500, npc, killer, true)) {
+		if ((qs == null) || !Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
 			return null;
 		}
-		
-		final DropInfo info = MOBS.get(npc.getId());
-		final int random = getRandom(1000);
-		
-		if (random < info.getFirstChance()) {
-			qs.giveItemRandomly(npc, GALFREDO_ROMERS_BUST, 1, 0, 1.0, true);
-		} else if (random < info.getSecondChance()) {
-			qs.giveItemRandomly(npc, SCULPTOR_BERONA, 1, 0, 1.0, true);
-		}
+
+		giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
+
 		return super.onKill(npc, killer, isSummon);
 	}
 	
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00356_DigUpTheSeaOfSpores/Q00356_DigUpTheSeaOfSpores.java b/src/main/java/com/l2jserver/datapack/quests/Q00356_DigUpTheSeaOfSpores/Q00356_DigUpTheSeaOfSpores.java
index f2e14a72fd..73b7981931 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00356_DigUpTheSeaOfSpores/Q00356_DigUpTheSeaOfSpores.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00356_DigUpTheSeaOfSpores/Q00356_DigUpTheSeaOfSpores.java
@@ -18,12 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00356_DigUpTheSeaOfSpores;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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.util.Util;
 
@@ -34,26 +33,26 @@ import com.l2jserver.gameserver.util.Util;
 public final class Q00356_DigUpTheSeaOfSpores extends Quest {
 	// NPC
 	private static final int GAUEN = 30717;
-	// Items
-	private static final int CARNIVORE_SPORE = 5865;
-	private static final int HERBIVOROUS_SPORE = 5866;
-	// Misc
-	private static final int MIN_LEVEL = 43;
 	// Monsters
 	private static final int ROTTING_TREE = 20558;
 	private static final int SPORE_ZOMBIE = 20562;
-	private static final Map<Integer, Double> MONSTER_DROP_CHANCES = new HashMap<>();
-	static {
-		MONSTER_DROP_CHANCES.put(ROTTING_TREE, 0.73);
-		MONSTER_DROP_CHANCES.put(SPORE_ZOMBIE, 0.94);
-	}
+	// Items
+	private static final QuestItemChanceHolder CARNIVORE_SPORE = new QuestItemChanceHolder(5865, 50L);
+	private static final QuestItemChanceHolder HERBIVOROUS_SPORE = new QuestItemChanceHolder(5866, 50L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(ROTTING_TREE, HERBIVOROUS_SPORE, 73.0)
+			.addSingleDrop(SPORE_ZOMBIE, CARNIVORE_SPORE, 94.0)
+			.build();
+	// Misc
+	private static final int MIN_LEVEL = 43;
 	
 	public Q00356_DigUpTheSeaOfSpores() {
 		super(356, Q00356_DigUpTheSeaOfSpores.class.getSimpleName(), "Dig Up the Sea of Spores!");
 		addStartNpc(GAUEN);
 		addTalkId(GAUEN);
 		addKillId(ROTTING_TREE, SPORE_ZOMBIE);
-		registerQuestItems(HERBIVOROUS_SPORE, CARNIVORE_SPORE);
+		registerQuestItems(HERBIVOROUS_SPORE.getId(), CARNIVORE_SPORE.getId());
 	}
 	
 	@Override
@@ -80,8 +79,8 @@ public final class Q00356_DigUpTheSeaOfSpores extends Quest {
 			}
 			case "30717-09.html": {
 				addExpAndSp(player, 31850, 0);
-				takeItems(player, CARNIVORE_SPORE, -1);
-				takeItems(player, HERBIVOROUS_SPORE, -1);
+				takeItems(player, CARNIVORE_SPORE.getId(), -1);
+				takeItems(player, HERBIVOROUS_SPORE.getId(), -1);
 				htmltext = event;
 				break;
 			}
@@ -98,7 +97,7 @@ public final class Q00356_DigUpTheSeaOfSpores extends Quest {
 			}
 			case "FINISH": {
 				final int value = getRandom(100);
-				int adena = 0;
+				int adena;
 				if (value < 20) {
 					adena = 44000;
 					htmltext = "30717-15.html";
@@ -124,12 +123,9 @@ public final class Q00356_DigUpTheSeaOfSpores extends Quest {
 		if ((qs == null) || !Util.checkIfInRange(1500, npc, killer, true)) {
 			return null;
 		}
-		
-		final int dropItem = ((npc.getId() == ROTTING_TREE) ? HERBIVOROUS_SPORE : CARNIVORE_SPORE);
-		final int otherItem = ((dropItem == HERBIVOROUS_SPORE) ? CARNIVORE_SPORE : HERBIVOROUS_SPORE);
-		
-		if (giveItemRandomly(qs.getPlayer(), npc, dropItem, 1, 50, MONSTER_DROP_CHANCES.get(npc.getId()), true)) {
-			if (getQuestItemsCount(killer, otherItem) >= 50) {
+
+		if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			if (hasItemsAtLimit(killer, CARNIVORE_SPORE, HERBIVOROUS_SPORE)) {
 				qs.setCond(3);
 			} else {
 				qs.setCond(2);
@@ -145,8 +141,8 @@ public final class Q00356_DigUpTheSeaOfSpores extends Quest {
 		if (qs.isCreated()) {
 			htmltext = (player.getLevel() >= MIN_LEVEL) ? "30717-01.htm" : "30717-06.htm";
 		} else if (qs.isStarted()) {
-			final boolean hasAllHerbSpores = (getQuestItemsCount(player, HERBIVOROUS_SPORE) >= 50);
-			final boolean hasAllCarnSpores = (getQuestItemsCount(player, CARNIVORE_SPORE) >= 50);
+			final boolean hasAllHerbSpores = hasItemsAtLimit(player, HERBIVOROUS_SPORE);
+			final boolean hasAllCarnSpores = hasItemsAtLimit(player, CARNIVORE_SPORE);
 			
 			if (hasAllHerbSpores && hasAllCarnSpores) {
 				htmltext = "30717-13.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00357_WarehouseKeepersAmbition/Q00357_WarehouseKeepersAmbition.java b/src/main/java/com/l2jserver/datapack/quests/Q00357_WarehouseKeepersAmbition/Q00357_WarehouseKeepersAmbition.java
index f50c0a1a40..0eb09ccab8 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00357_WarehouseKeepersAmbition/Q00357_WarehouseKeepersAmbition.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00357_WarehouseKeepersAmbition/Q00357_WarehouseKeepersAmbition.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00357_WarehouseKeepersAmbition;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -35,14 +33,13 @@ public final class Q00357_WarehouseKeepersAmbition extends Quest {
 	private static final int SILVA = 30686;
 	// Item
 	private static final int JADE_CRYSTAL = 5867;
-	// Monsters
-	private final Map<Integer, Double> DROP_DATA = new HashMap<>();
-	{
-		DROP_DATA.put(20594, 0.577); // Forest Runner
-		DROP_DATA.put(20595, 0.6); // Fline Elder
-		DROP_DATA.put(20596, 0.638); // Liele Elder
-		DROP_DATA.put(20597, 0.062); // Valley Treant Elder
-	}
+	// Droplist
+	private final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20594, JADE_CRYSTAL, 57.7) // Forest Runner
+			.addSingleDrop(20595, JADE_CRYSTAL, 60.0) // Fline Elder
+			.addSingleDrop(20596, JADE_CRYSTAL, 63.8) // Liele Elder
+			.addSingleDrop(20597, JADE_CRYSTAL, 62.0) // Valley Treant Elder
+			.build();
 	// Misc
 	private static final int MIN_LVL = 47;
 	
@@ -50,7 +47,7 @@ public final class Q00357_WarehouseKeepersAmbition extends Quest {
 		super(357, Q00357_WarehouseKeepersAmbition.class.getSimpleName(), "Warehouse Keeper's Ambition");
 		addStartNpc(SILVA);
 		addTalkId(SILVA);
-		addKillId(DROP_DATA.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(JADE_CRYSTAL);
 	}
 	
@@ -121,7 +118,7 @@ public final class Q00357_WarehouseKeepersAmbition extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			giveItemRandomly(qs.getPlayer(), npc, JADE_CRYSTAL, 1, 0, DROP_DATA.get(npc.getId()), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00358_IllegitimateChildOfTheGoddess/Q00358_IllegitimateChildOfTheGoddess.java b/src/main/java/com/l2jserver/datapack/quests/Q00358_IllegitimateChildOfTheGoddess/Q00358_IllegitimateChildOfTheGoddess.java
index 5c735e7494..c1bdc2d0d5 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00358_IllegitimateChildOfTheGoddess/Q00358_IllegitimateChildOfTheGoddess.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00358_IllegitimateChildOfTheGoddess/Q00358_IllegitimateChildOfTheGoddess.java
@@ -18,12 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00358_IllegitimateChildOfTheGoddess;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -34,10 +33,14 @@ public final class Q00358_IllegitimateChildOfTheGoddess extends Quest {
 	// NPC
 	private static final int OLTRAN = 30862;
 	// Item
-	private static final int SNAKE_SCALE = 5868;
+	private static final QuestItemChanceHolder SNAKE_SCALE = new QuestItemChanceHolder(5868, 108L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20672, SNAKE_SCALE, 71.0) // trives
+			.addSingleDrop(20673, SNAKE_SCALE, 74.0) // falibati
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 63;
-	private static final int SNAKE_SCALE_COUNT = 108;
 	// Rewards
 	private static final int[] REWARDS = new int[] {
 		5364, // Recipe: Sealed Dark Crystal Shield(60%)
@@ -49,19 +52,13 @@ public final class Q00358_IllegitimateChildOfTheGoddess extends Quest {
 		6337, // Recipe: Sealed Majestic Earring(70%)
 		6339, // Recipe: Sealed Majestic Ring(70%)
 	};
-	// Mobs
-	private static final Map<Integer, Double> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20672, 0.71); // trives
-		MOBS.put(20673, 0.74); // falibati
-	}
-	
+
 	public Q00358_IllegitimateChildOfTheGoddess() {
 		super(358, Q00358_IllegitimateChildOfTheGoddess.class.getSimpleName(), "Illegitimate Child of the Goddess");
 		addStartNpc(OLTRAN);
 		addTalkId(OLTRAN);
-		addKillId(MOBS.keySet());
-		registerQuestItems(SNAKE_SCALE);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(SNAKE_SCALE.getId());
 	}
 	
 	@Override
@@ -88,12 +85,12 @@ public final class Q00358_IllegitimateChildOfTheGoddess extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final QuestState st = getRandomPartyMemberState(player, 1, 3, npc);
-		if ((st != null) && st.giveItemRandomly(npc, SNAKE_SCALE, 1, SNAKE_SCALE_COUNT, MOBS.get(npc.getId()), true)) {
-			st.setCond(2, true);
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		final QuestState st = getRandomPartyMemberState(killer, 1, 3, npc);
+		if ((st != null) && giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			st.setCond(2);
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
@@ -103,7 +100,7 @@ public final class Q00358_IllegitimateChildOfTheGoddess extends Quest {
 		if (st.isCreated()) {
 			htmltext = ((player.getLevel() >= MIN_LEVEL) ? "30862-01.htm" : "30862-05.html");
 		} else if (st.isStarted()) {
-			if (getQuestItemsCount(player, SNAKE_SCALE) < SNAKE_SCALE_COUNT) {
+			if (!hasItemsAtLimit(player, SNAKE_SCALE)) {
 				htmltext = "30862-06.html";
 			} else {
 				rewardItems(player, REWARDS[getRandom(REWARDS.length)], 1);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00359_ForASleeplessDeadman/Q00359_ForASleeplessDeadman.java b/src/main/java/com/l2jserver/datapack/quests/Q00359_ForASleeplessDeadman/Q00359_ForASleeplessDeadman.java
index 949910f768..f4401e7f21 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00359_ForASleeplessDeadman/Q00359_ForASleeplessDeadman.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00359_ForASleeplessDeadman/Q00359_ForASleeplessDeadman.java
@@ -18,12 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00359_ForASleeplessDeadman;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -34,10 +33,15 @@ public final class Q00359_ForASleeplessDeadman extends Quest {
 	// NPC
 	private static final int ORVEN = 30857;
 	// Item
-	private static final int REMAINS_OF_ADEN_RESIDENTS = 5869;
+	private static final QuestItemChanceHolder REMAINS_OF_ADEN_RESIDENTS = new QuestItemChanceHolder(5869, 60L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21006, REMAINS_OF_ADEN_RESIDENTS, 36.5) // doom_servant
+			.addSingleDrop(21007, REMAINS_OF_ADEN_RESIDENTS, 39.2) // doom_guard
+			.addSingleDrop(21008, REMAINS_OF_ADEN_RESIDENTS, 50.3) // doom_archer
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 60;
-	private static final int REMAINS_COUNT = 60;
 	// Rewards
 	private static final int[] REWARDS = new int[] {
 		5494, // Sealed Dark Crystal Shield Fragment
@@ -49,20 +53,13 @@ public final class Q00359_ForASleeplessDeadman extends Quest {
 		6345, // Sealed Phoenix Ring Gemstone
 		6346, // Sealed Majestic Ring Gemstone
 	};
-	// Mobs
-	private static final Map<Integer, Double> MOBS = new HashMap<>();
-	static {
-		MOBS.put(21006, 0.365); // doom_servant
-		MOBS.put(21007, 0.392); // doom_guard
-		MOBS.put(21008, 0.503); // doom_archer
-	}
-	
+
 	public Q00359_ForASleeplessDeadman() {
 		super(359, Q00359_ForASleeplessDeadman.class.getSimpleName(), "For a Sleepless Deadman");
 		addStartNpc(ORVEN);
 		addTalkId(ORVEN);
-		addKillId(MOBS.keySet());
-		registerQuestItems(REMAINS_OF_ADEN_RESIDENTS);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(REMAINS_OF_ADEN_RESIDENTS.getId());
 	}
 	
 	@Override
@@ -97,12 +94,12 @@ public final class Q00359_ForASleeplessDeadman extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final QuestState st = getRandomPartyMemberState(player, 1, 3, npc);
-		if ((st != null) && st.giveItemRandomly(npc, REMAINS_OF_ADEN_RESIDENTS, 1, REMAINS_COUNT, MOBS.get(npc.getId()), true)) {
-			st.setCond(2, true);
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		final QuestState st = getRandomPartyMemberState(killer, 1, 3, npc);
+		if ((st != null) && giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			st.setCond(2);
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
@@ -113,10 +110,10 @@ public final class Q00359_ForASleeplessDeadman extends Quest {
 			htmltext = ((player.getLevel() >= MIN_LEVEL) ? "30857-01.htm" : "30857-06.html");
 		} else if (st.isStarted()) {
 			if (st.isMemoState(1)) {
-				if (getQuestItemsCount(player, REMAINS_OF_ADEN_RESIDENTS) < REMAINS_COUNT) {
+				if (!hasItemsAtLimit(player, REMAINS_OF_ADEN_RESIDENTS)) {
 					htmltext = "30857-07.html";
 				} else {
-					takeItems(player, REMAINS_OF_ADEN_RESIDENTS, -1);
+					takeItems(player, REMAINS_OF_ADEN_RESIDENTS.getId(), -1);
 					st.setMemoState(2);
 					st.setCond(3, true);
 					htmltext = "30857-08.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00365_DevilsLegacy/Q00365_DevilsLegacy.java b/src/main/java/com/l2jserver/datapack/quests/Q00365_DevilsLegacy/Q00365_DevilsLegacy.java
index 699cf06fb2..66017920cb 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00365_DevilsLegacy/Q00365_DevilsLegacy.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00365_DevilsLegacy/Q00365_DevilsLegacy.java
@@ -18,14 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00365_DevilsLegacy;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestDroplist;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
 /**
@@ -38,6 +36,13 @@ public final class Q00365_DevilsLegacy extends Quest {
 	private static final int RANDOLF = 30095;
 	// Item
 	private static final int PIRATES_TREASURE_CHEST = 5873;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20836, PIRATES_TREASURE_CHEST, 47.0) // pirates_zombie
+			.addSingleDrop(20845, PIRATES_TREASURE_CHEST, 40.0) // pirates_zombie_captain
+			.addSingleDrop(21629, PIRATES_TREASURE_CHEST, 40.0) // pirates_zombie_captain_1
+			.addSingleDrop(21630, PIRATES_TREASURE_CHEST, 40.0) // pirates_zombie_captain_2
+			.build();
 	// Rewards
 	private static final int ENCHANT_WEAPON_C = 951;
 	private static final int ENCHANT_ARMOR_C = 952;
@@ -54,20 +59,12 @@ public final class Q00365_DevilsLegacy extends Quest {
 	private static final int MIN_LEVEL = 39;
 	// Skill
 	private static final SkillHolder POISON = new SkillHolder(4035, 2);
-	// Mobs
-	private static final Map<Integer, Double> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20836, 0.47); // pirates_zombie
-		MOBS.put(20845, 0.40); // pirates_zombie_captain
-		MOBS.put(21629, 0.40); // pirates_zombie_captain_1
-		MOBS.put(21630, 0.40); // pirates_zombie_captain_2
-	}
-	
+
 	public Q00365_DevilsLegacy() {
 		super(365, Q00365_DevilsLegacy.class.getSimpleName(), "Devil's Legacy");
 		addStartNpc(RANDOLF);
 		addTalkId(RANDOLF, COLLOB);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(PIRATES_TREASURE_CHEST);
 	}
 	
@@ -155,12 +152,12 @@ public final class Q00365_DevilsLegacy extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final QuestState qs = getRandomPartyMemberState(player, -1, 3, npc);
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			giveItemRandomly(qs.getPlayer(), npc, PIRATES_TREASURE_CHEST, 1, 0, MOBS.get(npc.getId()), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00366_SilverHairedShaman/Q00366_SilverHairedShaman.java b/src/main/java/com/l2jserver/datapack/quests/Q00366_SilverHairedShaman/Q00366_SilverHairedShaman.java
index e140a39b7c..e9c04e3a52 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00366_SilverHairedShaman/Q00366_SilverHairedShaman.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00366_SilverHairedShaman/Q00366_SilverHairedShaman.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00366_SilverHairedShaman;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -35,21 +33,20 @@ public final class Q00366_SilverHairedShaman extends Quest {
 	private static final int DIETER = 30111;
 	// Item
 	private static final int SAIRONS_SILVER_HAIR = 5874;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20986, SAIRONS_SILVER_HAIR, 80.0) // saitnn
+			.addSingleDrop(20987, SAIRONS_SILVER_HAIR, 73.0) // saitnn_doll
+			.addSingleDrop(20988, SAIRONS_SILVER_HAIR, 80.0) // saitnn_puppet
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 48;
-	// Mobs
-	private static final Map<Integer, Integer> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20986, 80); // saitnn
-		MOBS.put(20987, 73); // saitnn_doll
-		MOBS.put(20988, 80); // saitnn_puppet
-	}
-	
+
 	public Q00366_SilverHairedShaman() {
 		super(366, Q00366_SilverHairedShaman.class.getSimpleName(), "Silver Haired Shaman");
 		addStartNpc(DIETER);
 		addTalkId(DIETER);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(SAIRONS_SILVER_HAIR);
 	}
 	
@@ -87,14 +84,12 @@ public final class Q00366_SilverHairedShaman extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		if (getRandom(100) < MOBS.get(npc.getId())) {
-			L2PcInstance luckyPlayer = getRandomPartyMember(player, npc);
-			if (luckyPlayer != null) {
-				giveItemRandomly(luckyPlayer, npc, SAIRONS_SILVER_HAIR, 1, 0, 1.0, true);
-			}
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		L2PcInstance luckyPlayer = getRandomPartyMember(killer, npc);
+		if (luckyPlayer != null) {
+			giveItemRandomly(luckyPlayer, npc, DROPLIST.get(npc), true);
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00368_TrespassingIntoTheHolyGround/Q00368_TrespassingIntoTheHolyGround.java b/src/main/java/com/l2jserver/datapack/quests/Q00368_TrespassingIntoTheHolyGround/Q00368_TrespassingIntoTheHolyGround.java
index a658c32732..f2f05d38b3 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00368_TrespassingIntoTheHolyGround/Q00368_TrespassingIntoTheHolyGround.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00368_TrespassingIntoTheHolyGround/Q00368_TrespassingIntoTheHolyGround.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00368_TrespassingIntoTheHolyGround;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -35,22 +33,21 @@ public final class Q00368_TrespassingIntoTheHolyGround extends Quest {
 	private static final int RESTINA = 30926;
 	// Item
 	private static final int BLADE_STAKATO_FANG = 5881;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20794, BLADE_STAKATO_FANG, 60.0) // blade_stakato
+			.addSingleDrop(20795, BLADE_STAKATO_FANG, 57.0) // blade_stakato_worker
+			.addSingleDrop(20796, BLADE_STAKATO_FANG, 61.0) // blade_stakato_soldier
+			.addSingleDrop(20797, BLADE_STAKATO_FANG, 93.0) // blade_stakato_drone
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 36;
-	// Mobs
-	private static final Map<Integer, Double> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20794, 0.60); // blade_stakato
-		MOBS.put(20795, 0.57); // blade_stakato_worker
-		MOBS.put(20796, 0.61); // blade_stakato_soldier
-		MOBS.put(20797, 0.93); // blade_stakato_drone
-	}
-	
+
 	public Q00368_TrespassingIntoTheHolyGround() {
 		super(368, Q00368_TrespassingIntoTheHolyGround.class.getSimpleName(), "Trespassing into the Holy Ground");
 		addStartNpc(RESTINA);
 		addTalkId(RESTINA);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(BLADE_STAKATO_FANG);
 	}
 	
@@ -82,25 +79,18 @@ public final class Q00368_TrespassingIntoTheHolyGround extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final int i;
 		switch (npc.getId()) {
-			case 20795:
-			case 20797: {
-				i = 1;
-				break;
-			}
-			default: {
-				i = 3;
-				break;
-			}
+			case 20795, 20797 -> i = 1;
+			default -> i = 3;
 		}
 		
-		final QuestState st = getRandomPartyMemberState(player, -1, i, npc);
+		final QuestState st = getRandomPartyMemberState(killer, -1, i, npc);
 		if (st != null) {
-			st.giveItemRandomly(npc, BLADE_STAKATO_FANG, 1, 0, MOBS.get(npc.getId()), true);
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00369_CollectorOfJewels/Q00369_CollectorOfJewels.java b/src/main/java/com/l2jserver/datapack/quests/Q00369_CollectorOfJewels/Q00369_CollectorOfJewels.java
index c6382e121d..c5de42eb7b 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00369_CollectorOfJewels/Q00369_CollectorOfJewels.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00369_CollectorOfJewels/Q00369_CollectorOfJewels.java
@@ -18,13 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00369_CollectorOfJewels;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.QuestItemHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestDroplist;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
 /**
@@ -37,24 +34,25 @@ public final class Q00369_CollectorOfJewels extends Quest {
 	// Items
 	private static final int FLARE_SHARD = 5882;
 	private static final int FREEZING_SHARD = 5883;
+	// Mobs
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20609, FLARE_SHARD, 75.0) // salamander_lakin
+			.addSingleDrop(20612, FLARE_SHARD, 91.0) // salamander_rowin
+			.addSingleDrop(20749, FLARE_SHARD, 2L) // death_fire
+			.addSingleDrop(20616, FREEZING_SHARD, 81.0) // undine_lakin
+			.addSingleDrop(20619, FREEZING_SHARD, 87.0) // undine_rowin
+			.addSingleDrop(20747, FREEZING_SHARD, 2L) // roxide
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 25;
-	// Mobs
-	private static final Map<Integer, QuestItemHolder> MOBS_DROP_CHANCES = new HashMap<>();
-	static {
-		MOBS_DROP_CHANCES.put(20609, new QuestItemHolder(FLARE_SHARD, 75, 1)); // salamander_lakin
-		MOBS_DROP_CHANCES.put(20612, new QuestItemHolder(FLARE_SHARD, 91, 1)); // salamander_rowin
-		MOBS_DROP_CHANCES.put(20749, new QuestItemHolder(FLARE_SHARD, 100, 2)); // death_fire
-		MOBS_DROP_CHANCES.put(20616, new QuestItemHolder(FREEZING_SHARD, 81, 1)); // undine_lakin
-		MOBS_DROP_CHANCES.put(20619, new QuestItemHolder(FREEZING_SHARD, 87, 1)); // undine_rowin
-		MOBS_DROP_CHANCES.put(20747, new QuestItemHolder(FREEZING_SHARD, 100, 2)); // roxide
-	}
-	
+	private static final int FIRST_STEP_LIMIT = 50;
+	private static final int SECOND_STEP_LIMIT = 200;
+
 	public Q00369_CollectorOfJewels() {
 		super(369, Q00369_CollectorOfJewels.class.getSimpleName(), "Collector of Jewels");
 		addStartNpc(NELL);
 		addTalkId(NELL);
-		addKillId(MOBS_DROP_CHANCES.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(FLARE_SHARD, FREEZING_SHARD);
 	}
 	
@@ -101,21 +99,16 @@ public final class Q00369_CollectorOfJewels extends Quest {
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final QuestItemHolder item = MOBS_DROP_CHANCES.get(npc.getId());
-		if (getRandom(100) < item.getChance()) {
-			L2PcInstance luckyPlayer = getRandomPartyMember(player, npc);
-			if (luckyPlayer != null) {
-				final QuestState st = getQuestState(luckyPlayer, false);
-				final int itemCount = (st.isMemoState(1) ? 50 : 200);
-				final int cond = (st.isMemoState(1) ? 2 : 4);
-				if (giveItemRandomly(luckyPlayer, npc, item.getId(), item.getCount(), itemCount, 1.0, true) //
-					&& (getQuestItemsCount(luckyPlayer, FLARE_SHARD, FREEZING_SHARD) >= (itemCount * 2))) {
-					st.setCond(cond);
-				}
-			}
+	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
+		L2PcInstance luckyPlayer = getRandomPartyMember(killer, npc);
+		final QuestState st = getQuestState(luckyPlayer, false);
+
+		final int itemLimit = (st.isMemoState(1) ? FIRST_STEP_LIMIT : SECOND_STEP_LIMIT);
+		if (giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc).drop(), itemLimit, true)
+			&& (getQuestItemsCount(luckyPlayer, FLARE_SHARD, FREEZING_SHARD) >= (itemLimit * 2))) {
+			st.setCond((st.isMemoState(1) ? 2 : 4));
 		}
-		return super.onKill(npc, player, isSummon);
+		return super.onKill(npc, killer, isSummon);
 	}
 	
 	@Override
@@ -127,7 +120,7 @@ public final class Q00369_CollectorOfJewels extends Quest {
 		} else if (st.isStarted()) {
 			switch (st.getMemoState()) {
 				case 1: {
-					if (getQuestItemsCount(player, FLARE_SHARD, FREEZING_SHARD) >= 100) {
+					if (getQuestItemsCount(player, FLARE_SHARD, FREEZING_SHARD) >= FIRST_STEP_LIMIT * 2) {
 						giveAdena(player, 31810, true);
 						takeItems(player, -1, FLARE_SHARD, FREEZING_SHARD);
 						st.setMemoState(2);
@@ -142,7 +135,7 @@ public final class Q00369_CollectorOfJewels extends Quest {
 					break;
 				}
 				case 3: {
-					if (getQuestItemsCount(player, FLARE_SHARD, FREEZING_SHARD) >= 400) {
+					if (getQuestItemsCount(player, FLARE_SHARD, FREEZING_SHARD) >= SECOND_STEP_LIMIT * 2) {
 						giveAdena(player, 84415, true);
 						takeItems(player, -1, FLARE_SHARD, FREEZING_SHARD);
 						st.exitQuest(true, true);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00370_AnElderSowsSeeds/Q00370_AnElderSowsSeeds.java b/src/main/java/com/l2jserver/datapack/quests/Q00370_AnElderSowsSeeds/Q00370_AnElderSowsSeeds.java
index 4d483f2729..4f7dd2f37d 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00370_AnElderSowsSeeds/Q00370_AnElderSowsSeeds.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00370_AnElderSowsSeeds/Q00370_AnElderSowsSeeds.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00370_AnElderSowsSeeds;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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.util.Util;
 
@@ -40,25 +38,22 @@ public final class Q00370_AnElderSowsSeeds extends Quest {
 	private static final int CHAPTER_OF_WATER = 5918;
 	private static final int CHAPTER_OF_WIND = 5919;
 	private static final int CHAPTER_OF_EARTH = 5920;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20082, SPELLBOOK_PAGE, 9.0) // ant_recruit
+			.addSingleDrop(20086, SPELLBOOK_PAGE, 9.0) // ant_guard
+			.addSingleDrop(20090, SPELLBOOK_PAGE, 22.0) // noble_ant_leader
+			.addSingleDrop(20084, SPELLBOOK_PAGE, 10.1) // ant_patrol
+			.addSingleDrop(20089, SPELLBOOK_PAGE, 10.0) // noble_ant
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 28;
-	// Mobs
-	private static final Map<Integer, Integer> MOBS1 = new HashMap<>();
-	private static final Map<Integer, Double> MOBS2 = new HashMap<>();
-	static {
-		MOBS1.put(20082, 9); // ant_recruit
-		MOBS1.put(20086, 9); // ant_guard
-		MOBS1.put(20090, 22); // noble_ant_leader
-		MOBS2.put(20084, 0.101); // ant_patrol
-		MOBS2.put(20089, 0.100); // noble_ant
-	}
 	
 	public Q00370_AnElderSowsSeeds() {
 		super(370, Q00370_AnElderSowsSeeds.class.getSimpleName(), "An Elder Sows Seeds");
 		addStartNpc(CASIAN);
 		addTalkId(CASIAN);
-		addKillId(MOBS1.keySet());
-		addKillId(MOBS2.keySet());
+		addKillId(DROPLIST.getNpcIds());
 	}
 	
 	@Override
@@ -113,19 +108,9 @@ public final class Q00370_AnElderSowsSeeds extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		int npcId = npc.getId();
-		if (MOBS1.containsKey(npcId)) {
-			if (getRandom(100) < MOBS1.get(npcId)) {
-				L2PcInstance luckyPlayer = getRandomPartyMember(player, npc);
-				if (luckyPlayer != null) {
-					giveItemRandomly(luckyPlayer, npc, SPELLBOOK_PAGE, 1, 0, 1.0, true);
-				}
-			}
-		} else {
-			final QuestState st = getRandomPartyMemberState(player, -1, 3, npc);
-			if (st != null) {
-				giveItemRandomly(st.getPlayer(), npc, SPELLBOOK_PAGE, 1, 0, MOBS2.get(npcId), true);
-			}
+		final QuestState st = getRandomPartyMemberState(player, -1, 3, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00371_ShrieksOfGhosts/Q00371_ShrieksOfGhosts.java b/src/main/java/com/l2jserver/datapack/quests/Q00371_ShrieksOfGhosts/Q00371_ShrieksOfGhosts.java
index 79da021664..aa1979e8c5 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00371_ShrieksOfGhosts/Q00371_ShrieksOfGhosts.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00371_ShrieksOfGhosts/Q00371_ShrieksOfGhosts.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00371_ShrieksOfGhosts;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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.util.Util;
 
@@ -32,24 +30,6 @@ import com.l2jserver.gameserver.util.Util;
  * @author Adry_85
  */
 public final class Q00371_ShrieksOfGhosts extends Quest {
-	private static final class DropInfo {
-		public final int _firstChance;
-		public final int _secondChance;
-		
-		public DropInfo(int firstChance, int secondChance) {
-			_firstChance = firstChance;
-			_secondChance = secondChance;
-		}
-		
-		public int getFirstChance() {
-			return _firstChance;
-		}
-		
-		public int getSecondChance() {
-			return _secondChance;
-		}
-	}
-	
 	// NPCs
 	private static final int REVA = 30867;
 	private static final int PATRIN = 30929;
@@ -60,21 +40,30 @@ public final class Q00371_ShrieksOfGhosts extends Quest {
 	private static final int ANCIENT_PORCELAIN_HIGH_QUALITY = 6004;
 	private static final int ANCIENT_PORCELAIN_LOW_QUALITY = 6005;
 	private static final int ANCIENT_PORCELAIN_LOWEST_QUALITY = 6006;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addGroupedDrop(20818, 40.0) // hallates_warrior
+				.withDropItem(ANCIENT_ASH_URN, 87.5)
+				.withDropItem(ANCIENT_PORCELAIN, 12.5)
+				.build()
+			.addGroupedDrop(20820, 67.3) // hallates_knight
+				.withDropItem(ANCIENT_ASH_URN, 86.63)
+				.withDropItem(ANCIENT_PORCELAIN, 13.37)
+				.build()
+			.addGroupedDrop(20824, 53.8) // hallates_commander
+				.withDropItem(ANCIENT_ASH_URN, 85.13)
+				.withDropItem(ANCIENT_PORCELAIN, 14.87)
+				.build()
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 59;
-	
-	private static final Map<Integer, DropInfo> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20818, new DropInfo(350, 400)); // hallates_warrior
-		MOBS.put(20820, new DropInfo(583, 673)); // hallates_knight
-		MOBS.put(20824, new DropInfo(458, 538)); // hallates_commander
-	}
-	
+
+
 	public Q00371_ShrieksOfGhosts() {
 		super(371, Q00371_ShrieksOfGhosts.class.getSimpleName(), "Shrieks of Ghosts");
 		addStartNpc(REVA);
 		addTalkId(REVA, PATRIN);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(ANCIENT_ASH_URN);
 	}
 	
@@ -155,18 +144,12 @@ public final class Q00371_ShrieksOfGhosts extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getQuestState(killer, false);
 		
-		if ((qs == null) || !Util.checkIfInRange(1500, npc, killer, true)) {
+		if ((qs == null) || !Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
 			return null;
 		}
-		
-		final DropInfo info = MOBS.get(npc.getId());
-		final int random = getRandom(1000);
-		
-		if (random < info.getFirstChance()) {
-			qs.giveItemRandomly(npc, ANCIENT_ASH_URN, 1, 0, 1.0, true);
-		} else if (random < info.getSecondChance()) {
-			qs.giveItemRandomly(npc, ANCIENT_PORCELAIN, 1, 0, 1.0, true);
-		}
+
+		giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
+
 		return super.onKill(npc, killer, isSummon);
 	}
 	
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00372_LegacyOfInsolence/Q00372_LegacyOfInsolence.java b/src/main/java/com/l2jserver/datapack/quests/Q00372_LegacyOfInsolence/Q00372_LegacyOfInsolence.java
index 6c323d1f0c..9e48f5dd4a 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00372_LegacyOfInsolence/Q00372_LegacyOfInsolence.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00372_LegacyOfInsolence/Q00372_LegacyOfInsolence.java
@@ -18,17 +18,17 @@
  */
 package com.l2jserver.datapack.quests.Q00372_LegacyOfInsolence;
 
-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.QuestItemHolder;
+import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
 import com.l2jserver.gameserver.util.Util;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Legacy Of Insolence (372)
  * @author ivantotov
@@ -102,15 +102,15 @@ public final class Q00372_LegacyOfInsolence extends Quest {
 	private static final int SEALED_MAJESTIC_CIRCLET_DESIGN = 5528;
 	// Monsters
 	private static final int HALLATES_INSPECTOR = 20825;
-	private static final Map<Integer, QuestItemHolder> MONSTER_REWARDS = new HashMap<>();
+	private static final Map<Integer, ItemChanceHolder> MONSTER_REWARDS = new HashMap<>();
 	
 	static {
-		MONSTER_REWARDS.put(20817, new QuestItemHolder(ANCIENT_RED_PAPYRUS, 302, 1));
-		MONSTER_REWARDS.put(20821, new QuestItemHolder(ANCIENT_RED_PAPYRUS, 410, 1));
-		MONSTER_REWARDS.put(HALLATES_INSPECTOR, new QuestItemHolder(ANCIENT_RED_PAPYRUS, 1, 447));
-		MONSTER_REWARDS.put(20829, new QuestItemHolder(ANCIENT_BLUE_PAPYRUS, 451, 1));
-		MONSTER_REWARDS.put(21062, new QuestItemHolder(ANCIENT_WHITE_PAPYRUS, 290, 1));
-		MONSTER_REWARDS.put(21069, new QuestItemHolder(ANCIENT_BLACK_PAPYRUS, 280, 1));
+		MONSTER_REWARDS.put(20817, new ItemChanceHolder(ANCIENT_RED_PAPYRUS, 302, 1));
+		MONSTER_REWARDS.put(20821, new ItemChanceHolder(ANCIENT_RED_PAPYRUS, 410, 1));
+		MONSTER_REWARDS.put(HALLATES_INSPECTOR, new ItemChanceHolder(ANCIENT_RED_PAPYRUS, 1, 447));
+		MONSTER_REWARDS.put(20829, new ItemChanceHolder(ANCIENT_BLUE_PAPYRUS, 451, 1));
+		MONSTER_REWARDS.put(21062, new ItemChanceHolder(ANCIENT_WHITE_PAPYRUS, 290, 1));
+		MONSTER_REWARDS.put(21069, new ItemChanceHolder(ANCIENT_BLACK_PAPYRUS, 280, 1));
 	}
 	
 	// Misc
@@ -361,7 +361,7 @@ public final class Q00372_LegacyOfInsolence extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
-		final QuestItemHolder item = MONSTER_REWARDS.get(npc.getId());
+		final ItemChanceHolder item = MONSTER_REWARDS.get(npc.getId());
 		if (npc.getId() == HALLATES_INSPECTOR) {
 			if (getRandom(1000) < item.getChance()) {
 				final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00373_SupplierOfReagents/Q00373_SupplierOfReagents.java b/src/main/java/com/l2jserver/datapack/quests/Q00373_SupplierOfReagents/Q00373_SupplierOfReagents.java
index 4f8bbfddb5..7344744a04 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00373_SupplierOfReagents/Q00373_SupplierOfReagents.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00373_SupplierOfReagents/Q00373_SupplierOfReagents.java
@@ -18,16 +18,18 @@
  */
 package com.l2jserver.datapack.quests.Q00373_SupplierOfReagents;
 
-import java.util.HashMap;
-
 import com.l2jserver.datapack.quests.Q00235_MimirsElixir.Q00235_MimirsElixir;
 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.ItemHolder;
+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 java.util.HashMap;
+
 /**
  * Supplier of Reagents (373)
  * @author Joxit
@@ -53,7 +55,7 @@ public final class Q00373_SupplierOfReagents extends Quest {
 	private static final int LAVA_STONE = 6012;
 	private static final int MOONSTONE_SHARD = 6013;
 	private static final int ROTTEN_BONE = 6014;
-	private static final int DEMONS_BLOOD = 6015;
+	private static final QuestItemChanceHolder DEMONS_BLOOD = new QuestItemChanceHolder(6015, 3L, 0L);
 	private static final int INFERNIUM_ORE = 6016;
 	private static final int BLOOD_ROOT = 6017;
 	private static final int VOLCANIC_ASH = 6018;
@@ -76,6 +78,26 @@ public final class Q00373_SupplierOfReagents extends Quest {
 	private static final int PURE_SILVER = 6320;
 	private static final int MIXING_MANUAL = 6317;
 	private static final int WESLEYS_MIXING_STONE = 5904;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addGroupedDrop(HALLATE_GUARDIAN, 87.6)
+				.withDropItem(DEMONS_BLOOD, 87.44)
+				.withDropItem(MOONSTONE_SHARD, 12.56).build()
+			.addGroupedDrop(HALLATE_MAID, 65)
+				.withDropItem(REAGENT_POUNCH1, 69.23)
+				.withDropItem(VOLCANIC_ASH, 30.77).build()
+			.addSingleDrop(HAMES_ORC_SHAMAN, REAGENT_POUNCH3, 61.6)
+			.addGroupedDrop(LAVA_WYRM, 98.9)
+				.withDropItem(WYRM_BLOOD, 67.34)
+				.withDropItem(LAVA_STONE, 32.66).build()
+			.addGroupedDrop(CRENDION, 100.0)
+				.withDropItem(ROTTEN_BONE, 61.8)
+				.withDropItem(QUICKSILVER, 38.2).build()
+			.addSingleDrop(PLATINUM_GUARDIAN_SHAMAN, REAGENT_BOX, 44.4)
+			.addGroupedDrop(PLATINUM_TRIBE_SHAMAN, 100.0)
+				.withDropItem(REAGENT_POUNCH2, 65.8)
+				.withDropItem(QUICKSILVER, 2, 34.2).build()
+			.build();
 	// Misc
 	private static final int MIN_LVL = 57;
 	private static final HashMap<String, Integer> HTML_TO_MEMO_STATE = new HashMap<>(20);
@@ -102,7 +124,7 @@ public final class Q00373_SupplierOfReagents extends Quest {
 		MEMO_STATE_TO_ITEM.put(12, new ItemHolder(LAVA_STONE, 10));
 		MEMO_STATE_TO_ITEM.put(13, new ItemHolder(MOONSTONE_SHARD, 10));
 		MEMO_STATE_TO_ITEM.put(14, new ItemHolder(ROTTEN_BONE, 10));
-		MEMO_STATE_TO_ITEM.put(15, new ItemHolder(DEMONS_BLOOD, 10));
+		MEMO_STATE_TO_ITEM.put(15, new ItemHolder(DEMONS_BLOOD.getId(), 10));
 		MEMO_STATE_TO_ITEM.put(16, new ItemHolder(INFERNIUM_ORE, 10));
 		MEMO_STATE_TO_ITEM.put(17, new ItemHolder(DRACOPLASM, 10));
 		MEMO_STATE_TO_ITEM.put(18, new ItemHolder(MAGMA_DUST, 10));
@@ -296,63 +318,7 @@ public final class Q00373_SupplierOfReagents extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			switch (npc.getId()) {
-				case HALLATE_GUARDIAN: {
-					final int chance = getRandom(1000);
-					if (chance < 766) {
-						giveItemRandomly(qs.getPlayer(), npc, DEMONS_BLOOD, 3, 0, 1, true);
-					} else if (chance < 876) {
-						giveItemRandomly(qs.getPlayer(), npc, MOONSTONE_SHARD, 1, 0, 1, true);
-					}
-					break;
-				}
-				case HALLATE_MAID: {
-					final int chance = getRandom(100);
-					if (chance < 45) {
-						giveItemRandomly(qs.getPlayer(), npc, REAGENT_POUNCH1, 1, 0, 1, true);
-					} else if (chance < 65) {
-						giveItemRandomly(qs.getPlayer(), npc, VOLCANIC_ASH, 1, 0, 1, true);
-					}
-					break;
-				}
-				case HAMES_ORC_SHAMAN: {
-					if (getRandom(1000) < 616) {
-						giveItemRandomly(qs.getPlayer(), npc, REAGENT_POUNCH3, 1, 0, 1, true);
-					}
-					break;
-				}
-				case LAVA_WYRM: {
-					final int chance = getRandom(1000);
-					if (chance < 666) {
-						giveItemRandomly(qs.getPlayer(), npc, WYRM_BLOOD, 1, 0, 1, true);
-					} else if (chance < 989) {
-						giveItemRandomly(qs.getPlayer(), npc, LAVA_STONE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case CRENDION: {
-					if (getRandom(1000) < 618) {
-						giveItemRandomly(qs.getPlayer(), npc, ROTTEN_BONE, 1, 0, 1, true);
-					} else {
-						giveItemRandomly(qs.getPlayer(), npc, QUICKSILVER, 1, 0, 1, true);
-					}
-					break;
-				}
-				case PLATINUM_GUARDIAN_SHAMAN: {
-					if (getRandom(1000) < 444) {
-						giveItemRandomly(qs.getPlayer(), npc, REAGENT_BOX, 1, 0, 1, true);
-					}
-					break;
-				}
-				case PLATINUM_TRIBE_SHAMAN: {
-					if (getRandom(1000) < 658) {
-						giveItemRandomly(qs.getPlayer(), npc, REAGENT_POUNCH2, 1, 0, 1, true);
-					} else {
-						giveItemRandomly(qs.getPlayer(), npc, QUICKSILVER, 2, 0, 1, true);
-					}
-					break;
-				}
-			}
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00376_ExplorationOfTheGiantsCavePart1/Q00376_ExplorationOfTheGiantsCavePart1.java b/src/main/java/com/l2jserver/datapack/quests/Q00376_ExplorationOfTheGiantsCavePart1/Q00376_ExplorationOfTheGiantsCavePart1.java
index 3817ef626a..3730850e4d 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00376_ExplorationOfTheGiantsCavePart1/Q00376_ExplorationOfTheGiantsCavePart1.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00376_ExplorationOfTheGiantsCavePart1/Q00376_ExplorationOfTheGiantsCavePart1.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00376_ExplorationOfTheGiantsCavePart1;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -41,24 +39,23 @@ public class Q00376_ExplorationOfTheGiantsCavePart1 extends Quest {
 	private static final int BOOK3 = 14838;
 	private static final int BOOK4 = 14839;
 	private static final int BOOK5 = 14840;
-	// Mobs
-	private static final Map<Integer, Double> MOBS = new HashMap<>();
-	static {
-		MOBS.put(22670, 0.314); // const_lord
-		MOBS.put(22671, 0.302); // const_gaurdian
-		MOBS.put(22672, 0.300); // const_seer
-		MOBS.put(22673, 0.258); // hirokai
-		MOBS.put(22674, 0.248); // imagro
-		MOBS.put(22675, 0.264); // palite
-		MOBS.put(22676, 0.258); // hamrit
-		MOBS.put(22677, 0.266); // kranout
-	}
-	
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22670, ANCIENT_PARCHMENT, 31.4) // const_lord
+			.addSingleDrop(22671, ANCIENT_PARCHMENT, 30.2) // const_gaurdian
+			.addSingleDrop(22672, ANCIENT_PARCHMENT, 30.0) // const_seer
+			.addSingleDrop(22673, ANCIENT_PARCHMENT, 25.8) // hirokai
+			.addSingleDrop(22674, ANCIENT_PARCHMENT, 24.8) // imagro
+			.addSingleDrop(22675, ANCIENT_PARCHMENT, 26.4) // palite
+			.addSingleDrop(22676, ANCIENT_PARCHMENT, 25.8) // hamrit
+			.addSingleDrop(22677, ANCIENT_PARCHMENT, 26.6) // kranout
+			.build();
+
 	public Q00376_ExplorationOfTheGiantsCavePart1() {
 		super(376, Q00376_ExplorationOfTheGiantsCavePart1.class.getSimpleName(), "Exploration of the Giants' Cave - Part 1");
 		addStartNpc(SOBLING);
 		addTalkId(SOBLING);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(ANCIENT_PARCHMENT);
 	}
 	
@@ -94,7 +91,7 @@ public class Q00376_ExplorationOfTheGiantsCavePart1 extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(player, -1, 3, npc);
 		if (qs != null) {
-			giveItemRandomly(qs.getPlayer(), npc, ANCIENT_PARCHMENT, 1, 0, MOBS.get(npc.getId()), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00377_ExplorationOfTheGiantsCavePart2/Q00377_ExplorationOfTheGiantsCavePart2.java b/src/main/java/com/l2jserver/datapack/quests/Q00377_ExplorationOfTheGiantsCavePart2/Q00377_ExplorationOfTheGiantsCavePart2.java
index ee598800b5..a3ee405249 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00377_ExplorationOfTheGiantsCavePart2/Q00377_ExplorationOfTheGiantsCavePart2.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00377_ExplorationOfTheGiantsCavePart2/Q00377_ExplorationOfTheGiantsCavePart2.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00377_ExplorationOfTheGiantsCavePart2;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -41,28 +39,25 @@ public class Q00377_ExplorationOfTheGiantsCavePart2 extends Quest {
 	private static final int BOOK3 = 14844;
 	private static final int BOOK4 = 14845;
 	private static final int BOOK5 = 14846;
-	// Mobs
-	private static final Map<Integer, Integer> MOBS1 = new HashMap<>();
-	private static final Map<Integer, Double> MOBS2 = new HashMap<>();
-	static {
-		MOBS1.put(22660, 366); // lesser_giant_re
-		MOBS1.put(22661, 424); // lesser_giant_soldier_re
-		MOBS1.put(22662, 304); // lesser_giant_shooter_re
-		MOBS1.put(22663, 304); // lesser_giant_scout_re
-		MOBS1.put(22664, 354); // lesser_giant_mage_re
-		MOBS1.put(22665, 324); // lesser_giant_elder_re
-		MOBS2.put(22666, 0.276); // barif_re
-		MOBS2.put(22667, 0.284); // barif_pet_re
-		MOBS2.put(22668, 0.240); // gamlin_re
-		MOBS2.put(22669, 0.240); // leogul_re
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22660, TITAN_ANCIENT_BOOK, 236.6) // lesser_giant_re
+			.addSingleDrop(22661, TITAN_ANCIENT_BOOK, 242.4) // lesser_giant_soldier_re
+			.addSingleDrop(22662, TITAN_ANCIENT_BOOK, 230.4) // lesser_giant_shooter_re
+			.addSingleDrop(22663, TITAN_ANCIENT_BOOK, 230.4) // lesser_giant_scout_re
+			.addSingleDrop(22664, TITAN_ANCIENT_BOOK, 235.4) // lesser_giant_mage_re
+			.addSingleDrop(22665, TITAN_ANCIENT_BOOK, 232.4) // lesser_giant_elder_re
+			.addSingleDrop(22666, TITAN_ANCIENT_BOOK, 27.6) // barif_re
+			.addSingleDrop(22667, TITAN_ANCIENT_BOOK, 28.4) // barif_pet_re
+			.addSingleDrop(22668, TITAN_ANCIENT_BOOK, 24.0) // gamlin_re
+			.addSingleDrop(22669, TITAN_ANCIENT_BOOK, 24.0) // leogul_re
+			.build();
 	
 	public Q00377_ExplorationOfTheGiantsCavePart2() {
 		super(377, Q00377_ExplorationOfTheGiantsCavePart2.class.getSimpleName(), "Exploration of the Giants' Cave - Part 2");
 		addStartNpc(SOBLING);
 		addTalkId(SOBLING);
-		addKillId(MOBS1.keySet());
-		addKillId(MOBS2.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(TITAN_ANCIENT_BOOK);
 	}
 	
@@ -98,13 +93,7 @@ public class Q00377_ExplorationOfTheGiantsCavePart2 extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(player, -1, 3, npc);
 		if (qs != null) {
-			int npcId = npc.getId();
-			if (MOBS1.containsKey(npcId)) {
-				final int itemCount = ((getRandom(1000) < MOBS1.get(npcId)) ? 3 : 2);
-				giveItemRandomly(qs.getPlayer(), npc, TITAN_ANCIENT_BOOK, itemCount, 0, 1.0, true);
-			} else {
-				giveItemRandomly(qs.getPlayer(), npc, TITAN_ANCIENT_BOOK, 1, 0, MOBS2.get(npcId), true);
-			}
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00379_FantasyWine/Q00379_FantasyWine.java b/src/main/java/com/l2jserver/datapack/quests/Q00379_FantasyWine/Q00379_FantasyWine.java
index 79f1296029..b523895253 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00379_FantasyWine/Q00379_FantasyWine.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00379_FantasyWine/Q00379_FantasyWine.java
@@ -20,8 +20,9 @@ package com.l2jserver.datapack.quests.Q00379_FantasyWine;
 
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
+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.util.Util;
 
@@ -32,15 +33,20 @@ import com.l2jserver.gameserver.util.Util;
 public final class Q00379_FantasyWine extends Quest {
 	// NPC
 	private static final int HARLAN = 30074;
+	// Monsters
+	private static final int ENKU_ORC_CHAMPION = 20291;
+	private static final int ENKU_ORC_SHAMAN = 20292;
 	// Items
-	private static final ItemHolder LEAF_OF_EUCALYPTUS = new ItemHolder(5893, 80);
-	private static final ItemHolder STONE_OF_CHILL = new ItemHolder(5894, 100);
 	private static final int OLD_WINE_15_YEAR = 5956;
 	private static final int OLD_WINE_30_YEAR = 5957;
 	private static final int OLD_WINE_60_YEAR = 5958;
-	// Monsters
-	private static final int ENKU_ORC_CHAMPION = 20291;
-	private static final int ENKU_ORC_SHAMAN = 20292;
+	private static final QuestItemChanceHolder LEAF_OF_EUCALYPTUS = new QuestItemChanceHolder(5893, 80L);
+	private static final QuestItemChanceHolder STONE_OF_CHILL = new QuestItemChanceHolder(5894, 100L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(ENKU_ORC_CHAMPION, LEAF_OF_EUCALYPTUS)
+			.addSingleDrop(ENKU_ORC_SHAMAN, STONE_OF_CHILL)
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 20;
 	
@@ -73,7 +79,7 @@ public final class Q00379_FantasyWine extends Quest {
 				break;
 			}
 			case "30074-11.html": {
-				if (hasAllItems(player, true, LEAF_OF_EUCALYPTUS, STONE_OF_CHILL)) {
+				if (hasItemsAtLimit(player, LEAF_OF_EUCALYPTUS, STONE_OF_CHILL)) {
 					final int random = getRandom(10);
 					final int item;
 					
@@ -89,7 +95,7 @@ public final class Q00379_FantasyWine extends Quest {
 					}
 					
 					giveItems(player, item, 1);
-					takeAllItems(player, LEAF_OF_EUCALYPTUS, STONE_OF_CHILL);
+					takeItems(player, -1, LEAF_OF_EUCALYPTUS.getId(), STONE_OF_CHILL.getId());
 					qs.exitQuest(true, true);
 				}
 				break;
@@ -102,15 +108,14 @@ public final class Q00379_FantasyWine extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getQuestState(killer, false);
 		
-		if ((qs == null) || !Util.checkIfInRange(1500, npc, killer, true)) {
+		if ((qs == null) || !Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
 			return null;
 		}
-		
-		final ItemHolder dropItem = ((npc.getId() == ENKU_ORC_CHAMPION) ? LEAF_OF_EUCALYPTUS : STONE_OF_CHILL);
-		
-		if (giveItemRandomly(killer, npc, dropItem.getId(), 1, dropItem.getCount(), 1.0, true) && hasAllItems(killer, true, LEAF_OF_EUCALYPTUS, STONE_OF_CHILL)) {
+
+		if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true) && hasItemsAtLimit(killer, LEAF_OF_EUCALYPTUS, STONE_OF_CHILL)) {
 			qs.setCond(2);
 		}
+
 		return super.onKill(npc, killer, isSummon);
 	}
 	
@@ -121,8 +126,8 @@ public final class Q00379_FantasyWine extends Quest {
 		if (qs.isCreated()) {
 			htmltext = (player.getLevel() >= MIN_LEVEL) ? "30074-01.htm" : "30074-06.html";
 		} else if (qs.isStarted()) {
-			final boolean hasLeafOfEucalyptus = hasItem(player, LEAF_OF_EUCALYPTUS);
-			final boolean hasStoneOfChill = hasItem(player, STONE_OF_CHILL);
+			final boolean hasLeafOfEucalyptus = hasItemsAtLimit(player, LEAF_OF_EUCALYPTUS);
+			final boolean hasStoneOfChill = hasItemsAtLimit(player, STONE_OF_CHILL);
 			
 			if (!hasLeafOfEucalyptus && !hasStoneOfChill) {
 				htmltext = "30074-07.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00380_BringOutTheFlavorOfIngredients/Q00380_BringOutTheFlavorOfIngredients.java b/src/main/java/com/l2jserver/datapack/quests/Q00380_BringOutTheFlavorOfIngredients/Q00380_BringOutTheFlavorOfIngredients.java
index e9af45b1f9..36e97d6191 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00380_BringOutTheFlavorOfIngredients/Q00380_BringOutTheFlavorOfIngredients.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00380_BringOutTheFlavorOfIngredients/Q00380_BringOutTheFlavorOfIngredients.java
@@ -18,18 +18,16 @@
  */
 package com.l2jserver.datapack.quests.Q00380_BringOutTheFlavorOfIngredients;
 
-import static com.l2jserver.gameserver.enums.audio.Sound.ITEMSOUND_QUEST_ITEMGET;
-
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
+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;
 
+import static com.l2jserver.gameserver.enums.audio.Sound.ITEMSOUND_QUEST_ITEMGET;
+
 /**
  * Bring Out the Flavor of Ingredients! (380)
  * @author Pandragon
@@ -39,16 +37,15 @@ public final class Q00380_BringOutTheFlavorOfIngredients extends Quest {
 	private static final int ROLLAND = 30069;
 	// Items
 	private static final int ANTIDOTE = 1831;
-	private static final int RITRON_FRUIT = 5895;
-	private static final int MOON_FLOWER = 5896;
-	private static final int LEECH_FLUIDS = 5897;
-	// Monsters
-	private static final Map<Integer, ItemChanceHolder> MONSTER_CHANCES = new HashMap<>();
-	{
-		MONSTER_CHANCES.put(20205, new ItemChanceHolder(RITRON_FRUIT, 0.1, 4)); // Dire Wolf
-		MONSTER_CHANCES.put(20206, new ItemChanceHolder(MOON_FLOWER, 0.5, 20)); // Kadif Werewolf
-		MONSTER_CHANCES.put(20225, new ItemChanceHolder(LEECH_FLUIDS, 0.5, 10)); // Giant Mist Leech
-	}
+	private static final QuestItemChanceHolder RITRON_FRUIT = new QuestItemChanceHolder(5895, 10.0, 4L);
+	private static final QuestItemChanceHolder MOON_FLOWER = new QuestItemChanceHolder(5896, 50.0, 20L);
+	private static final QuestItemChanceHolder LEECH_FLUIDS = new QuestItemChanceHolder(5897, 50.0, 10L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20205, RITRON_FRUIT) // Dire Wolf
+			.addSingleDrop(20206, MOON_FLOWER) // Kadif Werewolf
+			.addSingleDrop(20225, LEECH_FLUIDS) // Giant Mist Leech
+			.build();
 	// Rewards
 	private static final int RITRON_RECIPE = 5959;
 	private static final int RITRON_DESSERT = 5960;
@@ -59,8 +56,8 @@ public final class Q00380_BringOutTheFlavorOfIngredients extends Quest {
 		super(380, Q00380_BringOutTheFlavorOfIngredients.class.getSimpleName(), "Bring Out the Flavor of Ingredients!");
 		addStartNpc(ROLLAND);
 		addTalkId(ROLLAND);
-		addKillId(MONSTER_CHANCES.keySet());
-		registerQuestItems(RITRON_FRUIT, MOON_FLOWER, LEECH_FLUIDS);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(RITRON_FRUIT.getId(), MOON_FLOWER.getId(), LEECH_FLUIDS.getId());
 	}
 	
 	@Override
@@ -110,9 +107,9 @@ public final class Q00380_BringOutTheFlavorOfIngredients extends Quest {
 					case 2:
 					case 3:
 					case 4: {
-						if ((getQuestItemsCount(talker, ANTIDOTE) >= 2) && (getQuestItemsCount(talker, RITRON_FRUIT) >= 4) && (getQuestItemsCount(talker, MOON_FLOWER) >= 20) && (getQuestItemsCount(talker, LEECH_FLUIDS) >= 10)) {
+						if ((getQuestItemsCount(talker, ANTIDOTE) >= 2) && hasItemsAtLimit(talker, RITRON_FRUIT, MOON_FLOWER, LEECH_FLUIDS)) {
 							takeItems(talker, ANTIDOTE, 2);
-							takeItems(talker, -1, RITRON_FRUIT, MOON_FLOWER, LEECH_FLUIDS);
+							takeItems(talker, -1, RITRON_FRUIT.getId(), MOON_FLOWER.getId(), LEECH_FLUIDS.getId());
 							qs.setCond(5, true);
 							htmltext = "30069-08.html";
 						} else {
@@ -165,9 +162,8 @@ public final class Q00380_BringOutTheFlavorOfIngredients extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if ((qs != null) && (qs.getCond() < 4)) {
-			final ItemChanceHolder item = MONSTER_CHANCES.get(npc.getId());
-			if (giveItemRandomly(qs.getPlayer(), npc, item.getId(), 1, item.getCount(), item.getChance(), false)) {
-				if ((getQuestItemsCount(killer, RITRON_FRUIT) >= 3) && (getQuestItemsCount(killer, MOON_FLOWER) >= 20) && (getQuestItemsCount(killer, LEECH_FLUIDS) >= 10)) {
+			if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), false)) {
+				if (hasItemsAtLimit(killer, RITRON_FRUIT, MOON_FLOWER, LEECH_FLUIDS)) {
 					qs.setCond(qs.getCond() + 1, true);
 				} else {
 					playSound(killer, ITEMSOUND_QUEST_ITEMGET);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00381_LetsBecomeARoyalMember/Q00381_LetsBecomeARoyalMember.java b/src/main/java/com/l2jserver/datapack/quests/Q00381_LetsBecomeARoyalMember/Q00381_LetsBecomeARoyalMember.java
index bcacc1b71e..9b1d3644e1 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00381_LetsBecomeARoyalMember/Q00381_LetsBecomeARoyalMember.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00381_LetsBecomeARoyalMember/Q00381_LetsBecomeARoyalMember.java
@@ -21,6 +21,7 @@ package com.l2jserver.datapack.quests.Q00381_LetsBecomeARoyalMember;
 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;
 import com.l2jserver.gameserver.util.Util;
@@ -35,9 +36,9 @@ public final class Q00381_LetsBecomeARoyalMember extends Quest {
 	private static final int SORINT = 30232;
 	// Items
 	private static final int COLLECTOR_MEMBERSHIP_1 = 3813;
-	private static final int KAILS_COIN = 5899;
-	private static final int FOUR_LEAF_COIN = 7569;
 	private static final int COIN_ALBUM = 5900;
+	private static final int FOUR_LEAF_COIN = 7569;
+	private static final QuestItemChanceHolder KAILS_COIN = new QuestItemChanceHolder(5899, 5.0, 1L);
 	// Monsters
 	private static final int ANCIENT_GARGOYLE = 21018;
 	private static final int FALLEN_CHIEF_VERGUS = 27316;
@@ -51,7 +52,7 @@ public final class Q00381_LetsBecomeARoyalMember extends Quest {
 		addStartNpc(SORINT);
 		addTalkId(SORINT, SANDRA);
 		addKillId(ANCIENT_GARGOYLE, FALLEN_CHIEF_VERGUS);
-		registerQuestItems(KAILS_COIN, FOUR_LEAF_COIN);
+		registerQuestItems(KAILS_COIN.getId(), FOUR_LEAF_COIN);
 	}
 	
 	@Override
@@ -97,10 +98,10 @@ public final class Q00381_LetsBecomeARoyalMember extends Quest {
 					// TODO this quest is not visible in quest list if neither of these IF blocks are true
 				} else if (qs.isStarted()) {
 					final boolean hasAlbum = hasQuestItems(talker, COIN_ALBUM);
-					final boolean hasCoin = hasQuestItems(talker, KAILS_COIN);
+					final boolean hasCoin = hasQuestItems(talker, KAILS_COIN.getId());
 					
 					if (hasAlbum && hasCoin) {
-						takeItems(talker, 1, KAILS_COIN, COIN_ALBUM);
+						takeItems(talker, 1, KAILS_COIN.getId(), COIN_ALBUM);
 						giveItems(talker, ROYAL_MEMBERSHIP, 1);
 						qs.exitQuest(false, true);
 						htmltext = "30232-06.html";
@@ -141,9 +142,9 @@ public final class Q00381_LetsBecomeARoyalMember 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)) {
+		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
 			if (npc.getId() == ANCIENT_GARGOYLE) {
-				giveItemRandomly(killer, npc, KAILS_COIN, 1, 1, 0.05, true);
+				giveItemRandomly(killer, npc, KAILS_COIN, true);
 			} else if (qs.isMemoState(2) && !hasQuestItems(killer, FOUR_LEAF_COIN)) {
 				giveItems(killer, FOUR_LEAF_COIN, 1);
 				playSound(killer, Sound.ITEMSOUND_QUEST_MIDDLE);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00382_KailsMagicCoin/Q00382_KailsMagicCoin.java b/src/main/java/com/l2jserver/datapack/quests/Q00382_KailsMagicCoin/Q00382_KailsMagicCoin.java
index 2556e38118..75bbc07e5e 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00382_KailsMagicCoin/Q00382_KailsMagicCoin.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00382_KailsMagicCoin/Q00382_KailsMagicCoin.java
@@ -18,13 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00382_KailsMagicCoin;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
 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.util.Util;
 
@@ -45,14 +42,16 @@ public final class Q00382_KailsMagicCoin extends Quest {
 	private static final int KAILS_SILVER_BASILISK = 5961;
 	private static final int KAILS_GOLD_GOLEM = 5962;
 	private static final int KAILS_BLOOD_DRAGON = 5963;
-	// Drops
-	private static final double ORC_CAPTAIN_DROP_CHANCE = 0.069;
-	private static final Map<Integer, ItemChanceHolder> MONSTER_DROPS = new HashMap<>();
-	static {
-		MONSTER_DROPS.put(FALLEN_ORC, new ItemChanceHolder(KAILS_SILVER_BASILISK, 0.073));
-		MONSTER_DROPS.put(FALLEN_ORC_ARCHER, new ItemChanceHolder(KAILS_GOLD_GOLEM, 0.075));
-		MONSTER_DROPS.put(FALLEN_ORC_SHAMAN, new ItemChanceHolder(KAILS_BLOOD_DRAGON, 0.073));
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addGroupedDrop(FALLEN_ORC_CAPTAIN, 6.9)
+				.withDropItem(KAILS_SILVER_BASILISK, 33.333)
+				.withDropItem(KAILS_GOLD_GOLEM, 33.333)
+				.withDropItem(KAILS_BLOOD_DRAGON, 33.334).build()
+			.addSingleDrop(FALLEN_ORC, KAILS_SILVER_BASILISK, 7.3)
+			.addSingleDrop(FALLEN_ORC_ARCHER, KAILS_GOLD_GOLEM, 7.5)
+			.addSingleDrop(FALLEN_ORC_SHAMAN, KAILS_BLOOD_DRAGON, 7.3)
+			.build();
 	// Misc
 	private static final int MIN_LVL = 55;
 	
@@ -105,13 +104,8 @@ public final class Q00382_KailsMagicCoin extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getQuestState(killer, false);
-		if ((qs != null) && hasQuestItems(killer, ROYAL_MEMBERSHIP) && Util.checkIfInRange(1500, npc, killer, true)) {
-			if (npc.getId() == FALLEN_ORC_CAPTAIN) {
-				giveItemRandomly(killer, KAILS_SILVER_BASILISK + getRandom(3), 1, 0, ORC_CAPTAIN_DROP_CHANCE, true);
-			} else {
-				final ItemChanceHolder ih = MONSTER_DROPS.get(npc.getId());
-				giveItemRandomly(killer, ih.getId(), 1, 0, ih.getChance(), true);
-			}
+		if ((qs != null) && hasQuestItems(qs.getPlayer(), ROYAL_MEMBERSHIP) && Util.checkIfInRange(1500, npc, qs.getPlayer(), true)) {
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00384_WarehouseKeepersPastime/Q00384_WarehouseKeepersPastime.java b/src/main/java/com/l2jserver/datapack/quests/Q00384_WarehouseKeepersPastime/Q00384_WarehouseKeepersPastime.java
index 2b02820d8a..d1d4a90d7f 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00384_WarehouseKeepersPastime/Q00384_WarehouseKeepersPastime.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00384_WarehouseKeepersPastime/Q00384_WarehouseKeepersPastime.java
@@ -18,17 +18,15 @@
  */
 package com.l2jserver.datapack.quests.Q00384_WarehouseKeepersPastime;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 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.util.Util;
+
+import java.util.Arrays;
+import java.util.Collections;
 
 /**
  * Warehouse Keeper's Pastime (384)
@@ -39,7 +37,6 @@ public final class Q00384_WarehouseKeepersPastime extends Quest {
 	// NPCs
 	private static final int CLIFF = 30182;
 	private static final int WAREHOUSE_CHIEF_BAXT = 30685;
-	
 	// Monsters
 	private static final int DUST_WIND = 20242;
 	private static final int INNERSEN = 20950;
@@ -69,6 +66,35 @@ public final class Q00384_WarehouseKeepersPastime extends Quest {
 	private static final int THUNDER_WYRM = 20243;
 	// Items
 	private static final int Q_IRONGATE_MEDAL = 5964;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(HUNTER_GARGOYLE, Q_IRONGATE_MEDAL, 32.8)
+			.addSingleDrop(DUST_WIND, Q_IRONGATE_MEDAL, 35.0)
+			.addSingleDrop(THUNDER_WYRM, Q_IRONGATE_MEDAL, 31.2)
+			.addSingleDrop(DUST_WIND_HOLD, Q_IRONGATE_MEDAL, 35.0)
+			.addSingleDrop(THUNDER_WYRM_HOLD, Q_IRONGATE_MEDAL, 31.2)
+			.addSingleDrop(HUNTER_GARGOYLE_HOLD, Q_IRONGATE_MEDAL, 32.8)
+			.addSingleDrop(GIANT_MONSTEREYE, Q_IRONGATE_MEDAL, 17.6)
+			.addSingleDrop(ROT_GOLEM, Q_IRONGATE_MEDAL, 22.6)
+			.addSingleDrop(WEIRD_DRAKE, Q_IRONGATE_MEDAL, 21.8)
+			.addSingleDrop(CARINKAIN, Q_IRONGATE_MEDAL, 21.6)
+			.addSingleDrop(GRAVE_GUARD, Q_IRONGATE_MEDAL, 31.2)
+			.addSingleDrop(TULBEN, Q_IRONGATE_MEDAL, 52.2)
+			.addSingleDrop(DRAGON_BEARER_CHIEF, Q_IRONGATE_MEDAL, 38.0)
+			.addSingleDrop(DRAGON_BEARER_WARRIOR, Q_IRONGATE_MEDAL, 39.0)
+			.addSingleDrop(DRAGON_BEARER_ARCHER, Q_IRONGATE_MEDAL, 37.2)
+			.addSingleDrop(CONGERER_LORD, Q_IRONGATE_MEDAL, 80.2)
+			.addSingleDrop(CONGERER, Q_IRONGATE_MEDAL, 84.4)
+			.addSingleDrop(NIGHTMARE_GUIDE, Q_IRONGATE_MEDAL, 11.8)
+			.addSingleDrop(NIGHTMARE_KEEPER, Q_IRONGATE_MEDAL, 17.0)
+			.addSingleDrop(NIGHTMARE_LORD, Q_IRONGATE_MEDAL, 14.4)
+			.addSingleDrop(CADEINE, Q_IRONGATE_MEDAL, 16.2)
+			.addSingleDrop(SANHIDRO, Q_IRONGATE_MEDAL,  25.0)
+			.addSingleDrop(CONNABI, Q_IRONGATE_MEDAL, 27.2)
+			.addSingleDrop(BARTAL, Q_IRONGATE_MEDAL, 27.0)
+			.addSingleDrop(LUMINUN, Q_IRONGATE_MEDAL, 32.0)
+			.addSingleDrop(INNERSEN, Q_IRONGATE_MEDAL, 34.6)
+			.build();
 	// Reward
 	private static final int MOONSTONE_EARING = 852;
 	private static final int DRAKE_LEATHER_BOOTS = 2437;
@@ -413,10 +439,7 @@ public final class Q00384_WarehouseKeepersPastime extends Quest {
 			}
 		}
 	}
-	
-	/**
-	 * @param qs
-	 */
+
 	private void createBingoBoard(QuestState qs) {
 		//@formatter:off
 		Integer[] arr = {1,2,3,4,5,6,7,8,9};
@@ -425,11 +448,7 @@ public final class Q00384_WarehouseKeepersPastime extends Quest {
 		qs.set("numbers", Arrays.asList(arr).toString().replaceAll("[^\\d ]", ""));
 		qs.set("selected", "? ? ? ? ? ? ? ? ?");
 	}
-	
-	/**
-	 * @param qs
-	 * @return
-	 */
+
 	private int getMatchedBingoLineCount(QuestState qs) {
 		String[] q = qs.get("selected").split(" ");
 		int found = 0;
@@ -462,11 +481,7 @@ public final class Q00384_WarehouseKeepersPastime extends Quest {
 		}
 		return found;
 	}
-	
-	/**
-	 * @param qs
-	 * @param num
-	 */
+
 	private void selectBingoNumber(QuestState qs, int num) {
 		String[] numbers = qs.get("numbers").split(" ");
 		int pos = 0;
@@ -483,35 +498,21 @@ public final class Q00384_WarehouseKeepersPastime extends Quest {
 				continue;
 			}
 		}
-		String result = selected[0];
+		StringBuilder result = new StringBuilder(selected[0]);
 		for (int i = 1; i < selected.length; i++) {
-			result += " " + selected[i];
+			result.append(" ").append(selected[i]);
 		}
-		qs.set("selected", result);
+		qs.set("selected", result.toString());
 	}
-	
-	/**
-	 * @param qs
-	 * @param num
-	 * @return
-	 */
+
 	private boolean isSelectedBingoNumber(QuestState qs, int num) {
 		return qs.get("selected").contains(num + "");
 	}
-	
-	/**
-	 * @param qs
-	 * @param num
-	 * @return
-	 */
+
 	private int getNumberFromBingoBoard(QuestState qs, int num) {
 		return Integer.parseInt(qs.get("numbers").split(" ")[num]);
 	}
-	
-	/**
-	 * @param qs
-	 * @return
-	 */
+
 	private int getBingoSelectCount(QuestState qs) {
 		String current = qs.get("selected");
 		return current.replaceAll("\\D", "").length();
@@ -519,163 +520,10 @@ public final class Q00384_WarehouseKeepersPastime extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
-		final QuestState qs = getRandomPlayerFromParty(killer, npc);
+		final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
 		if (qs != null) {
-			switch (npc.getId()) {
-				case HUNTER_GARGOYLE:
-					if (getRandom(1000) < 328) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case DUST_WIND:
-					if (getRandom(100) < 35) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case THUNDER_WYRM:
-					if (getRandom(1000) < 312) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case DUST_WIND_HOLD:
-					if (getRandom(100) < 35) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case THUNDER_WYRM_HOLD:
-					if (getRandom(1000) < 312) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case HUNTER_GARGOYLE_HOLD:
-					if (getRandom(1000) < 328) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case GIANT_MONSTEREYE:
-					if (getRandom(1000) < 176) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case ROT_GOLEM:
-					if (getRandom(1000) < 226) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case WEIRD_DRAKE:
-					if (getRandom(1000) < 218) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case CARINKAIN:
-					if (getRandom(1000) < 216) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case GRAVE_GUARD:
-					if (getRandom(1000) < 312) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case TULBEN:
-					if (getRandom(1000) < 522) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case DRAGON_BEARER_CHIEF:
-					if (getRandom(100) < 38) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case DRAGON_BEARER_WARRIOR:
-					if (getRandom(100) < 39) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case DRAGON_BEARER_ARCHER:
-					if (getRandom(1000) < 372) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case CONGERER_LORD:
-					if (getRandom(1000) < 802) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case CONGERER:
-					if (getRandom(1000) < 844) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case NIGHTMARE_GUIDE:
-					if (getRandom(1000) < 118) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case NIGHTMARE_KEEPER:
-					if (getRandom(100) < 17) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case NIGHTMARE_LORD:
-					if (getRandom(1000) < 144) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case CADEINE:
-					if (getRandom(1000) < 162) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case SANHIDRO:
-					if (getRandom(100) < 25) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case CONNABI:
-					if (getRandom(1000) < 272) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case BARTAL:
-					if (getRandom(100) < 27) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case LUMINUN:
-					if (getRandom(100) < 32) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-				case INNERSEN:
-					if (getRandom(1000) < 346) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_IRONGATE_MEDAL, 1, 0, 1, true);
-					}
-					break;
-			}
-			
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
-	
-	private QuestState getRandomPlayerFromParty(L2PcInstance player, L2Npc npc) {
-		QuestState qs = getQuestState(player, false);
-		final List<QuestState> candidates = new ArrayList<>();
-		
-		if ((qs != null) && qs.isStarted()) {
-			candidates.add(qs);
-			candidates.add(qs);
-		}
-		
-		if (player.isInParty()) {
-			player.getParty().getMembers().stream().forEach(pm -> {
-				
-				QuestState qss = getQuestState(pm, false);
-				if ((qss != null) && qss.isStarted() && Util.checkIfInRange(1500, npc, pm, true)) {
-					candidates.add(qss);
-				}
-			});
-		}
-		return candidates.isEmpty() ? null : candidates.get(getRandom(candidates.size()));
-	}
 }
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00385_YokeOfThePast/Q00385_YokeOfThePast.java b/src/main/java/com/l2jserver/datapack/quests/Q00385_YokeOfThePast/Q00385_YokeOfThePast.java
index 7c27a20e51..1845767b26 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00385_YokeOfThePast/Q00385_YokeOfThePast.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00385_YokeOfThePast/Q00385_YokeOfThePast.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00385_YokeOfThePast;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
@@ -34,8 +32,7 @@ import com.l2jserver.gameserver.model.quest.State;
 public final class Q00385_YokeOfThePast extends Quest {
 	// NPCs
 	// @formatter:off
-	private static final int[] ZIGGURATS =
-	{
+	private static final int[] ZIGGURATS = {
 		31095, 31096, 31097, 31098, 31099, 31100, 31101,
 		31102, 31103, 31104, 31105, 31106, 31107, 31108,
 		31109, 31110, 31114, 31115, 31116, 31117, 31118,
@@ -44,55 +41,54 @@ public final class Q00385_YokeOfThePast extends Quest {
 	// @formatter:on
 	// Item
 	private static final int SCROLL_OF_ANCIENT_MAGIC = 5902;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21144, SCROLL_OF_ANCIENT_MAGIC, 30.6) // Catacomb Shadow
+			.addSingleDrop(21156, SCROLL_OF_ANCIENT_MAGIC, 99.4) // Purgatory Shadow
+			.addSingleDrop(21208, SCROLL_OF_ANCIENT_MAGIC, 14.6) // Hallowed Watchman
+			.addSingleDrop(21209, SCROLL_OF_ANCIENT_MAGIC, 16.6) // Hallowed Seer
+			.addSingleDrop(21210, SCROLL_OF_ANCIENT_MAGIC, 20.2) // Vault Guardian
+			.addSingleDrop(21211, SCROLL_OF_ANCIENT_MAGIC, 21.2) // Vault Seer
+			.addSingleDrop(21213, SCROLL_OF_ANCIENT_MAGIC, 27.4) // Hallowed Monk
+			.addSingleDrop(21214, SCROLL_OF_ANCIENT_MAGIC, 34.2) // Vault Sentinel
+			.addSingleDrop(21215, SCROLL_OF_ANCIENT_MAGIC, 36.0) // Vault Monk
+			.addSingleDrop(21217, SCROLL_OF_ANCIENT_MAGIC, 46.0) // Hallowed Priest
+			.addSingleDrop(21218, SCROLL_OF_ANCIENT_MAGIC, 55.8) // Vault Overlord
+			.addSingleDrop(21219, SCROLL_OF_ANCIENT_MAGIC, 57.8) // Vault Priest
+			.addSingleDrop(21221, SCROLL_OF_ANCIENT_MAGIC, 71.0) // Sepulcher Inquisitor
+			.addSingleDrop(21222, SCROLL_OF_ANCIENT_MAGIC, 84.2) // Sepulcher Archon
+			.addSingleDrop(21223, SCROLL_OF_ANCIENT_MAGIC, 86.2) // Sepulcher Inquisitor
+			.addSingleDrop(21224, SCROLL_OF_ANCIENT_MAGIC, 94.0) // Sepulcher Guardian
+			.addSingleDrop(21225, SCROLL_OF_ANCIENT_MAGIC, 97.0) // Sepulcher Sage
+			.addSingleDrop(21226, SCROLL_OF_ANCIENT_MAGIC, 20.2) // Sepulcher Guardian
+			.addSingleDrop(21227, SCROLL_OF_ANCIENT_MAGIC, 29.0) // Sepulcher Sage
+			.addSingleDrop(21228, SCROLL_OF_ANCIENT_MAGIC, 31.6) // Sepulcher Guard
+			.addSingleDrop(21229, SCROLL_OF_ANCIENT_MAGIC, 42.6) // Sepulcher Preacher
+			.addSingleDrop(21230, SCROLL_OF_ANCIENT_MAGIC, 64.6) // Sepulcher Guard
+			.addSingleDrop(21231, SCROLL_OF_ANCIENT_MAGIC, 65.4) // Sepulcher Preacher
+			.addSingleDrop(21236, SCROLL_OF_ANCIENT_MAGIC, 23.8) // Barrow Sentinel
+			.addSingleDrop(21237, SCROLL_OF_ANCIENT_MAGIC, 27.4) // Barrow Monk
+			.addSingleDrop(21238, SCROLL_OF_ANCIENT_MAGIC, 34.2) // Grave Sentinel
+			.addSingleDrop(21239, SCROLL_OF_ANCIENT_MAGIC, 36.0) // Grave Monk
+			.addSingleDrop(21240, SCROLL_OF_ANCIENT_MAGIC, 41.0) // Barrow Overlord
+			.addSingleDrop(21241, SCROLL_OF_ANCIENT_MAGIC, 46.0) // Barrow Priest
+			.addSingleDrop(21242, SCROLL_OF_ANCIENT_MAGIC, 55.8) // Grave Overlord
+			.addSingleDrop(21243, SCROLL_OF_ANCIENT_MAGIC, 57.8) // Grave Priest
+			.addSingleDrop(21244, SCROLL_OF_ANCIENT_MAGIC, 64.2) // Crypt Archon
+			.addSingleDrop(21245, SCROLL_OF_ANCIENT_MAGIC, 70.0) // Crypt Inquisitor
+			.addSingleDrop(21246, SCROLL_OF_ANCIENT_MAGIC, 84.2) // Tomb Archon
+			.addSingleDrop(21247, SCROLL_OF_ANCIENT_MAGIC, 86.2) // Tomb Inquisitor
+			.addSingleDrop(21248, SCROLL_OF_ANCIENT_MAGIC, 94.0) // Crypt Guardian
+			.addSingleDrop(21249, SCROLL_OF_ANCIENT_MAGIC, 97.0) // Crypt Sage
+			.addSingleDrop(21250, SCROLL_OF_ANCIENT_MAGIC, 79.8) // Tomb Guardian
+			.addSingleDrop(21251, SCROLL_OF_ANCIENT_MAGIC, 71.0) // Tomb Sage
+			.addSingleDrop(21252, SCROLL_OF_ANCIENT_MAGIC, 68.4) // Crypt Guard
+			.addSingleDrop(21253, SCROLL_OF_ANCIENT_MAGIC, 57.4) // Crypt Preacher
+			.addSingleDrop(21254, SCROLL_OF_ANCIENT_MAGIC, 35.4) // Tomb Guard
+			.addSingleDrop(21255, SCROLL_OF_ANCIENT_MAGIC, 25.0) // Tomb Preacher
+			.build();
 	// Reward
 	private static final int BLANK_SCROLL = 5965;
-	// Monsters
-	private static final Map<Integer, Double> MONSTER_CHANCES = new HashMap<>();
-	{
-		MONSTER_CHANCES.put(21144, 0.306); // Catacomb Shadow
-		MONSTER_CHANCES.put(21156, 0.994); // Purgatory Shadow
-		MONSTER_CHANCES.put(21208, 0.146); // Hallowed Watchman
-		MONSTER_CHANCES.put(21209, 0.166); // Hallowed Seer
-		MONSTER_CHANCES.put(21210, 0.202); // Vault Guardian
-		MONSTER_CHANCES.put(21211, 0.212); // Vault Seer
-		MONSTER_CHANCES.put(21213, 0.274); // Hallowed Monk
-		MONSTER_CHANCES.put(21214, 0.342); // Vault Sentinel
-		MONSTER_CHANCES.put(21215, 0.360); // Vault Monk
-		MONSTER_CHANCES.put(21217, 0.460); // Hallowed Priest
-		MONSTER_CHANCES.put(21218, 0.558); // Vault Overlord
-		MONSTER_CHANCES.put(21219, 0.578); // Vault Priest
-		MONSTER_CHANCES.put(21221, 0.710); // Sepulcher Inquisitor
-		MONSTER_CHANCES.put(21222, 0.842); // Sepulcher Archon
-		MONSTER_CHANCES.put(21223, 0.862); // Sepulcher Inquisitor
-		MONSTER_CHANCES.put(21224, 0.940); // Sepulcher Guardian
-		MONSTER_CHANCES.put(21225, 0.970); // Sepulcher Sage
-		MONSTER_CHANCES.put(21226, 0.202); // Sepulcher Guardian
-		MONSTER_CHANCES.put(21227, 0.290); // Sepulcher Sage
-		MONSTER_CHANCES.put(21228, 0.316); // Sepulcher Guard
-		MONSTER_CHANCES.put(21229, 0.426); // Sepulcher Preacher
-		MONSTER_CHANCES.put(21230, 0.646); // Sepulcher Guard
-		MONSTER_CHANCES.put(21231, 0.654); // Sepulcher Preacher
-		MONSTER_CHANCES.put(21236, 0.238); // Barrow Sentinel
-		MONSTER_CHANCES.put(21237, 0.274); // Barrow Monk
-		MONSTER_CHANCES.put(21238, 0.342); // Grave Sentinel
-		MONSTER_CHANCES.put(21239, 0.360); // Grave Monk
-		MONSTER_CHANCES.put(21240, 0.410); // Barrow Overlord
-		MONSTER_CHANCES.put(21241, 0.460); // Barrow Priest
-		MONSTER_CHANCES.put(21242, 0.558); // Grave Overlord
-		MONSTER_CHANCES.put(21243, 0.578); // Grave Priest
-		MONSTER_CHANCES.put(21244, 0.642); // Crypt Archon
-		MONSTER_CHANCES.put(21245, 0.700); // Crypt Inquisitor
-		MONSTER_CHANCES.put(21246, 0.842); // Tomb Archon
-		MONSTER_CHANCES.put(21247, 0.862); // Tomb Inquisitor
-		MONSTER_CHANCES.put(21248, 0.940); // Crypt Guardian
-		MONSTER_CHANCES.put(21249, 0.970); // Crypt Sage
-		MONSTER_CHANCES.put(21250, 0.798); // Tomb Guardian
-		MONSTER_CHANCES.put(21251, 0.710); // Tomb Sage
-		MONSTER_CHANCES.put(21252, 0.684); // Crypt Guard
-		MONSTER_CHANCES.put(21253, 0.574); // Crypt Preacher
-		MONSTER_CHANCES.put(21254, 0.354); // Tomb Guard
-		MONSTER_CHANCES.put(21255, 0.250); // Tomb Preacher
-	}
 	// Misc
 	private static final int MIN_LVL = 20;
 	
@@ -100,7 +96,7 @@ public final class Q00385_YokeOfThePast extends Quest {
 		super(385, Q00385_YokeOfThePast.class.getSimpleName(), "Yoke of the Past");
 		addStartNpc(ZIGGURATS);
 		addTalkId(ZIGGURATS);
-		addKillId(MONSTER_CHANCES.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(SCROLL_OF_ANCIENT_MAGIC);
 	}
 	
@@ -161,7 +157,7 @@ public final class Q00385_YokeOfThePast extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			giveItemRandomly(qs.getPlayer(), npc, SCROLL_OF_ANCIENT_MAGIC, 1, 0, MONSTER_CHANCES.get(npc.getId()), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00386_StolenDignity/Q00386_StolenDignity.java b/src/main/java/com/l2jserver/datapack/quests/Q00386_StolenDignity/Q00386_StolenDignity.java
index 3a73ef5dde..da478bb706 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00386_StolenDignity/Q00386_StolenDignity.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00386_StolenDignity/Q00386_StolenDignity.java
@@ -18,17 +18,15 @@
  */
 package com.l2jserver.datapack.quests.Q00386_StolenDignity;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 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.util.Util;
+
+import java.util.Arrays;
+import java.util.Collections;
 
 /**
  * Stolen Dignity (386)
@@ -37,7 +35,6 @@ import com.l2jserver.gameserver.util.Util;
 public final class Q00386_StolenDignity extends Quest {
 	// NPCs
 	private static final int WAREHOUSE_KEEPER_ROMP = 30843;
-	
 	// Monsters
 	private static final int CRIMSON_DRAKE = 20670;
 	private static final int KADIOS = 20671;
@@ -67,41 +64,72 @@ public final class Q00386_StolenDignity extends Quest {
 	private static final int SHARP_TALON_TIGER_TRANS = 21259;
 	// Items
 	private static final int Q_STOLEN_INF_ORE = 6363;
-	// Reward
-	private static final int DRAGON_SLAYER_EDGE = 5529;
-	private static final int METEOR_SHOWER_HEAD = 5532;
-	private static final int ELYSIAN_HEAD = 5533;
-	private static final int SOUL_BOW_SHAFT = 5534;
-	private static final int CARNIUM_BOW_SHAFT = 5535;
-	private static final int BLOODY_ORCHID_HEAD = 5536;
-	private static final int SOUL_SEPARATOR_HEAD = 5537;
-	private static final int DRAGON_GRINDER_EDGE = 5538;
-	private static final int BLOOD_TORNADO_EDGE = 5539;
-	private static final int TALLUM_GLAIVE_EDGE = 5541;
-	private static final int HALBARD_EDGE = 5542;
-	private static final int DASPARIONS_STAFF_HEAD = 5543;
-	private static final int WORLDTREES_BRANCH_HEAD = 5544;
-	private static final int DARK_LEGIONS_EDGE_EDGE = 5545;
-	private static final int SWORD_OF_MIRACLE_EDGE = 5546;
-	private static final int ELEMENTAL_SWORD_EDGE = 5547;
-	private static final int TALLUM_BLADE_EDGE = 5548;
-	private static final int INFERNO_MASTER_BLADE = 8331;
-	private static final int EYE_OF_SOUL_PIECE = 8341;
-	private static final int DRAGON_FLAME_HEAD_PIECE = 8342;
-	private static final int DOOM_CRUSHER_HEAD = 8349;
-	private static final int HAMMER_OF_DESTROYER_PIECE = 8346;
-	private static final int SIRR_BLADE_BLADE = 8712;
-	private static final int SWORD_OF_IPOS_BLADE = 8713;
-	private static final int BARAKIEL_AXE_PIECE = 8714;
-	private static final int TUNING_FORK_OF_BEHEMOTH_PIECE = 8715;
-	private static final int NAGA_STORM_PIECE = 8716;
-	private static final int TIPHON_SPEAR_EDGE = 8717;
-	private static final int SHYID_BOW_SHAFT = 8718;
-	private static final int SOBEKK_HURRICANE_EDGE = 8719;
-	private static final int TONGUE_OF_THEMIS_PIECE = 8720;
-	private static final int HAND_OF_CABRIO_HEAD = 8721;
-	private static final int CRYSTAL_OF_DEAMON_PIECE = 8722;
-	
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(CRIMSON_DRAKE, Q_STOLEN_INF_ORE, 20.200001)
+			.addSingleDrop(KADIOS, Q_STOLEN_INF_ORE, 21.1)
+			.addSingleDrop(HUNGRY_CORPSE, Q_STOLEN_INF_ORE, 18.4)
+			.addSingleDrop(PAST_KNIGHT, Q_STOLEN_INF_ORE, 21.6)
+			.addSingleDrop(BLADE_DEATH, Q_STOLEN_INF_ORE, 17.0)
+			.addSingleDrop(DARK_GUARD, Q_STOLEN_INF_ORE, 27.3)
+			.addSingleDrop(BLOODY_GHOST, Q_STOLEN_INF_ORE, 14.9)
+			.addSingleDrop(BLOODY_LORD, Q_STOLEN_INF_ORE, 19.9)
+			.addSingleDrop(PAST_CREATURE, Q_STOLEN_INF_ORE, 25.7)
+			.addSingleDrop(GIANT_SHADOW, Q_STOLEN_INF_ORE, 20.5)
+			.addSingleDrop(ANCIENTS_SOLDIER, Q_STOLEN_INF_ORE, 20.8)
+			.addSingleDrop(ANCIENTS_WARRIOR, Q_STOLEN_INF_ORE, 29.9)
+			.addSingleDrop(SPITE_SOUL_LEADER, Q_STOLEN_INF_ORE, 44.0)
+			.addSingleDrop(SPITE_SOUL_WIZARD, Q_STOLEN_INF_ORE, 39.0)
+			.addSingleDrop(WRECKED_ARCHER, Q_STOLEN_INF_ORE, 21.4)
+			.addSingleDrop(FLOAT_OF_GRAVE, Q_STOLEN_INF_ORE, 17.3)
+			.addSingleDrop(GRAVE_PREDATOR, Q_STOLEN_INF_ORE, 21.1)
+			.addSingleDrop(FALLEN_ORC_SHAMAN, Q_STOLEN_INF_ORE, 47.8)
+			.addSingleDrop(SHARP_TALON_TIGER, Q_STOLEN_INF_ORE, 23.4)
+			.addSingleDrop(GLOW_WISP, Q_STOLEN_INF_ORE, 24.5)
+			.addSingleDrop(MARSH_PREDATOR, Q_STOLEN_INF_ORE, 26.0)
+			.addSingleDrop(HAMES_ORC_SNIPER, Q_STOLEN_INF_ORE, 37.0)
+			.addSingleDrop(CURSED_GUARDIAN, Q_STOLEN_INF_ORE, 35.2)
+			.addSingleDrop(HAMES_ORC_CHIEFTAIN, Q_STOLEN_INF_ORE, 48.7)
+			.addSingleDrop(FALLEN_ORC_SHAMAN_TRANS, Q_STOLEN_INF_ORE, 48.7)
+			.addSingleDrop(SHARP_TALON_TIGER_TRANS, Q_STOLEN_INF_ORE, 48.7)
+			.build();
+	// Rewards
+	private static final int[] REWARDS = {
+		5529, // Dragon Slayer Edge
+		5532, // Meteor Shower Head
+		5533, // Elysian Head
+		5534, // Soul Bow Shaft
+		5535, // Carnium Bow Shaft
+		5536, // Bloody Orchid Head
+		5537, // Soul Separator Head
+		5538, // Dragon Grinder Edge
+		5539, // Blood Tornado Edge
+		5541, // Tallum Glaive Edge
+		5542, // Halbard Edge
+		5543, // Dasparions Staff Head
+		5544, // Worldtrees Branch Head
+		5545, // Dark Legions Edge Edge
+		5546, // Sword of Miracle Edge
+		5547, // Elemental Sword Edge
+		5548, // Tallum Blade Edge
+		8331, // Inferno Master Blade
+		8341, // Eye of Soul Piece
+		8342, // Dragon Flame Head Piece
+		8349, // Doom Crusher Head
+		8346, // Hammer of Destroyer Piece
+		8712, // Sirr Blade Blade
+		8713, // Sword of Ipos Blade
+		8714, // Barakiel Axe Piece
+		8715, // Tuning Fork of Behemoth Piece
+		8716, // Naga Storm Piece
+		8717, // Tiphon Spear Edge
+		8718, // Shyid Bow Shaft
+		8719, // Sobekk Hurricane Edge
+		8720, // Tongue of Themis Piece
+		8721, // Hand of Cabrio Head
+		8722 // Crystal of Deamon Piece
+	};
+
 	public Q00386_StolenDignity() {
 		super(386, Q00386_StolenDignity.class.getSimpleName(), "Stolen Dignity");
 		addStartNpc(WAREHOUSE_KEEPER_ROMP);
@@ -260,10 +288,10 @@ public final class Q00386_StolenDignity extends Quest {
 			int i3 = getMatchedBingoLineCount(qs);
 			String html;
 			if ((i3 == 3) && ((getBingoSelectCount(qs)) == 6)) {
-				reward(player, qs, 4);
+				reward(player, 4);
 				html = getHtm(player.getHtmlPrefix(), "30843-22.html");
 			} else if ((i3 == 0) && (getBingoSelectCount(qs) == 6)) {
-				reward(player, qs, 10);
+				reward(player, 10);
 				html = getHtm(player.getHtmlPrefix(), "30843-24.html");
 			} else {
 				html = getHtm(player.getHtmlPrefix(), "30843-23.html");
@@ -273,146 +301,11 @@ public final class Q00386_StolenDignity extends Quest {
 		return fillBoard(player, qs, getHtm(player.getHtmlPrefix(), "30843-25.html"));
 	}
 	
-	private void reward(L2PcInstance player, QuestState qs, int count) {
-		switch (getRandom(33)) {
-			case 0: {
-				qs.giveItems(DRAGON_SLAYER_EDGE, count);
-				break;
-			}
-			case 1: {
-				qs.giveItems(METEOR_SHOWER_HEAD, count);
-				break;
-			}
-			case 2: {
-				qs.giveItems(ELYSIAN_HEAD, count);
-				break;
-			}
-			case 3: {
-				qs.giveItems(SOUL_BOW_SHAFT, count);
-				break;
-			}
-			case 4: {
-				qs.giveItems(CARNIUM_BOW_SHAFT, count);
-				break;
-			}
-			case 5: {
-				qs.giveItems(BLOODY_ORCHID_HEAD, count);
-				break;
-			}
-			case 6: {
-				qs.giveItems(SOUL_SEPARATOR_HEAD, count);
-				break;
-			}
-			case 7: {
-				qs.giveItems(DRAGON_GRINDER_EDGE, count);
-				break;
-			}
-			case 8: {
-				qs.giveItems(BLOOD_TORNADO_EDGE, count);
-				break;
-			}
-			case 9: {
-				qs.giveItems(TALLUM_GLAIVE_EDGE, count);
-				break;
-			}
-			case 10: {
-				qs.giveItems(HALBARD_EDGE, count);
-				break;
-			}
-			case 11: {
-				qs.giveItems(DASPARIONS_STAFF_HEAD, count);
-				break;
-			}
-			case 12: {
-				qs.giveItems(WORLDTREES_BRANCH_HEAD, count);
-				break;
-			}
-			case 13: {
-				qs.giveItems(DARK_LEGIONS_EDGE_EDGE, count);
-				break;
-			}
-			case 14: {
-				qs.giveItems(SWORD_OF_MIRACLE_EDGE, count);
-				break;
-			}
-			case 15: {
-				qs.giveItems(ELEMENTAL_SWORD_EDGE, count);
-				break;
-			}
-			case 16: {
-				qs.giveItems(TALLUM_BLADE_EDGE, count);
-				break;
-			}
-			case 17: {
-				qs.giveItems(INFERNO_MASTER_BLADE, count);
-				break;
-			}
-			case 18: {
-				qs.giveItems(EYE_OF_SOUL_PIECE, count);
-				break;
-			}
-			case 19: {
-				qs.giveItems(DRAGON_FLAME_HEAD_PIECE, count);
-				break;
-			}
-			case 20: {
-				qs.giveItems(DOOM_CRUSHER_HEAD, count);
-				break;
-			}
-			case 21: {
-				qs.giveItems(HAMMER_OF_DESTROYER_PIECE, count);
-				break;
-			}
-			case 22: {
-				qs.giveItems(SIRR_BLADE_BLADE, count);
-				break;
-			}
-			case 23: {
-				qs.giveItems(SWORD_OF_IPOS_BLADE, count);
-				break;
-			}
-			case 24: {
-				qs.giveItems(BARAKIEL_AXE_PIECE, count);
-				break;
-			}
-			case 25: {
-				qs.giveItems(TUNING_FORK_OF_BEHEMOTH_PIECE, count);
-				break;
-			}
-			case 26: {
-				qs.giveItems(NAGA_STORM_PIECE, count);
-				break;
-			}
-			case 27: {
-				qs.giveItems(TIPHON_SPEAR_EDGE, count);
-				break;
-			}
-			case 28: {
-				qs.giveItems(SHYID_BOW_SHAFT, count);
-				break;
-			}
-			case 29: {
-				qs.giveItems(SOBEKK_HURRICANE_EDGE, count);
-				break;
-			}
-			case 30: {
-				qs.giveItems(TONGUE_OF_THEMIS_PIECE, count);
-				break;
-			}
-			case 31: {
-				qs.giveItems(HAND_OF_CABRIO_HEAD, count);
-				break;
-			}
-			case 32: {
-				qs.giveItems(CRYSTAL_OF_DEAMON_PIECE, count);
-				break;
-			}
-		}
+	private void reward(L2PcInstance player, int count) {
+		int index = getRandom(33);
+		giveItems(player, REWARDS[index], count);
 	}
-	
-	/**
-	 * @param qs
-	 */
+
 	private void createBingoBoard(QuestState qs) {
 		//@formatter:off
 		Integer[] arr = {1,2,3,4,5,6,7,8,9};
@@ -421,11 +314,7 @@ public final class Q00386_StolenDignity extends Quest {
 		qs.set("numbers", Arrays.asList(arr).toString().replaceAll("[^\\d ]", ""));
 		qs.set("selected", "? ? ? ? ? ? ? ? ?");
 	}
-	
-	/**
-	 * @param qs
-	 * @return
-	 */
+
 	private int getMatchedBingoLineCount(QuestState qs) {
 		String[] q = qs.get("selected").split(" ");
 		int found = 0;
@@ -458,11 +347,7 @@ public final class Q00386_StolenDignity extends Quest {
 		}
 		return found;
 	}
-	
-	/**
-	 * @param qs
-	 * @param num
-	 */
+
 	private void selectBingoNumber(QuestState qs, int num) {
 		String[] numbers = qs.get("numbers").split(" ");
 		int pos = 0;
@@ -479,35 +364,21 @@ public final class Q00386_StolenDignity extends Quest {
 				continue;
 			}
 		}
-		String result = selected[0];
+		StringBuilder result = new StringBuilder(selected[0]);
 		for (int i = 1; i < selected.length; i++) {
-			result += " " + selected[i];
+			result.append(" ").append(selected[i]);
 		}
-		qs.set("selected", result);
+		qs.set("selected", result.toString());
 	}
 	
-	/**
-	 * @param qs
-	 * @param num
-	 * @return
-	 */
 	private boolean isSelectedBingoNumber(QuestState qs, int num) {
 		return qs.get("selected").contains(num + "");
 	}
 	
-	/**
-	 * @param qs
-	 * @param num
-	 * @return
-	 */
 	private int getNumberFromBingoBoard(QuestState qs, int num) {
 		return Integer.parseInt(qs.get("numbers").split(" ")[num]);
 	}
 	
-	/**
-	 * @param qs
-	 * @return
-	 */
 	private int getBingoSelectCount(QuestState qs) {
 		String current = qs.get("selected");
 		return current.replaceAll("\\D", "").length();
@@ -515,179 +386,10 @@ public final class Q00386_StolenDignity extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
-		final QuestState qs = getRandomPlayerFromParty(killer, npc);
+		final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
 		if (qs != null) {
-			switch (npc.getId()) {
-				case CRIMSON_DRAKE: {
-					if (getRandom(1000) < 20.200001) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case KADIOS: {
-					if (getRandom(1000) < 211) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case HUNGRY_CORPSE: {
-					if (getRandom(1000) < 184) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case PAST_KNIGHT: {
-					if (getRandom(1000) < 216) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case BLADE_DEATH: {
-					if (getRandom(100) < 17) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case DARK_GUARD: {
-					if (getRandom(1000) < 273) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case BLOODY_GHOST: {
-					if (getRandom(1000) < 149) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case BLOODY_LORD: {
-					if (getRandom(1000) < 199) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case PAST_CREATURE: {
-					if (getRandom(1000) < 257) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case GIANT_SHADOW: {
-					if (getRandom(1000) < 205) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case ANCIENTS_SOLDIER: {
-					if (getRandom(1000) < 208) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case ANCIENTS_WARRIOR: {
-					if (getRandom(1000) < 299) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case SPITE_SOUL_LEADER: {
-					if (getRandom(100) < 44) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case SPITE_SOUL_WIZARD: {
-					if (getRandom(100) < 39) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case WRECKED_ARCHER: {
-					if (getRandom(1000) < 214) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case FLOAT_OF_GRAVE: {
-					if (getRandom(1000) < 173) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case GRAVE_PREDATOR: {
-					if (getRandom(1000) < 211) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case FALLEN_ORC_SHAMAN: {
-					if (getRandom(1000) < 478) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case SHARP_TALON_TIGER: {
-					if (getRandom(1000) < 234) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case GLOW_WISP: {
-					if (getRandom(1000) < 245) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case MARSH_PREDATOR: {
-					if (getRandom(100) < 26) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case HAMES_ORC_SNIPER: {
-					if (getRandom(100) < 37) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case CURSED_GUARDIAN: {
-					if (getRandom(1000) < 352) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-				case HAMES_ORC_CHIEFTAIN:
-				case FALLEN_ORC_SHAMAN_TRANS:
-				case SHARP_TALON_TIGER_TRANS: {
-					if (getRandom(1000) < 487) {
-						giveItemRandomly(qs.getPlayer(), npc, Q_STOLEN_INF_ORE, 1, 0, 1, true);
-					}
-					break;
-				}
-			}
-			
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
-	
-	private QuestState getRandomPlayerFromParty(L2PcInstance player, L2Npc npc) {
-		QuestState qs = getQuestState(player, false);
-		final List<QuestState> candidates = new ArrayList<>();
-		
-		if ((qs != null) && qs.isStarted()) {
-			candidates.add(qs);
-			candidates.add(qs);
-		}
-		
-		if (player.isInParty()) {
-			player.getParty().getMembers().stream().forEach(pm -> {
-				
-				QuestState qss = getQuestState(pm, false);
-				if ((qss != null) && qss.isStarted() && Util.checkIfInRange(1500, npc, pm, true)) {
-					candidates.add(qss);
-				}
-			});
-		}
-		return candidates.isEmpty() ? null : candidates.get(getRandom(candidates.size()));
-	}
 }
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00416_PathOfTheOrcShaman/Q00416_PathOfTheOrcShaman.java b/src/main/java/com/l2jserver/datapack/quests/Q00416_PathOfTheOrcShaman/Q00416_PathOfTheOrcShaman.java
index 048c54196e..a402c132cd 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00416_PathOfTheOrcShaman/Q00416_PathOfTheOrcShaman.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00416_PathOfTheOrcShaman/Q00416_PathOfTheOrcShaman.java
@@ -18,21 +18,21 @@
  */
 package com.l2jserver.datapack.quests.Q00416_PathOfTheOrcShaman;
 
-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.base.ClassId;
-import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
+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.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
 import com.l2jserver.gameserver.network.serverpackets.NpcSay;
 import com.l2jserver.gameserver.network.serverpackets.SocialAction;
 
+import java.util.Map;
+
 /**
  * Path of the Orc Shaman (416)
  * @author Adry_85
@@ -46,47 +46,57 @@ public final class Q00416_PathOfTheOrcShaman extends Quest {
 	private static final int MOIRA = 31979;
 	private static final int TOTEM_SPIRIT_OF_GANDI = 32057;
 	private static final int DEAD_LEOPARDS_CARCASS = 32090;
+	// Monsters
+	private static final int GRIZZLY_BEAR = 20335;
+	private static final int SCARLET_SALAMANDER = 20415;
+	private static final int KASHA_BLADE_SPIDER = 20478;
+	private static final int KASHA_BEAR = 20479;
+	// Quest Monsters
+	private static final int DURKA_SPIRIT = 27056;
+	private static final int BLACK_LEOPARD = 27319;
 	// Items
 	private static final int FIRE_CHARM = 1616;
-	private static final int KASHA_BEAR_PELT = 1617;
-	private static final int KASHA_BLADE_SPIDER_HUSK = 1618;
-	private static final int FIRST_FIERY_EGG = 1619;
 	private static final int HESTUI_MASK = 1620;
 	private static final int SECOND_FIERY_EGG = 1621;
 	private static final int TOTEM_SPIRIT_CLAW = 1622;
 	private static final int TATARUS_LETTER = 1623;
 	private static final int FLAME_CHARM = 1624;
-	private static final int GRIZZLY_BLOOD = 1625;
 	private static final int BLOOD_CAULDRON = 1626;
 	private static final int SPIRIT_NET = 1627;
 	private static final int BOUND_DURKA_SPIRIT = 1628;
 	private static final int DURKA_PARASITE = 1629;
 	private static final int TOTEM_SPIRIT_BLOOD = 1630;
 	private static final int MASK_OF_MEDIUM = 1631;
-	// Quest Monsters
-	private static final int DURKA_SPIRIT = 27056;
-	private static final int BLACK_LEOPARD = 27319;
+	private static final QuestItemChanceHolder KASHA_BEAR_PELT = new QuestItemChanceHolder(1617, 1L);
+	private static final QuestItemChanceHolder KASHA_BLADE_SPIDER_HUSK = new QuestItemChanceHolder(1618, 1L);
+	private static final QuestItemChanceHolder FIRST_FIERY_EGG = new QuestItemChanceHolder(1619, 1L);
+	private static final QuestItemChanceHolder GRIZZLY_BLOOD = new QuestItemChanceHolder(1625, 3L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(SCARLET_SALAMANDER, FIRST_FIERY_EGG)
+			.addSingleDrop(KASHA_BLADE_SPIDER, KASHA_BLADE_SPIDER_HUSK)
+			.addSingleDrop(KASHA_BEAR, KASHA_BEAR_PELT)
+			.addSingleDrop(GRIZZLY_BEAR, GRIZZLY_BLOOD)
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 18;
 	// Mobs
-	private static final Map<Integer, ItemChanceHolder> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20415, new ItemChanceHolder(FIRST_FIERY_EGG, 1.0, 1)); // scarlet_salamander
-		MOBS.put(20478, new ItemChanceHolder(KASHA_BLADE_SPIDER_HUSK, 1.0, 1)); // kasha_blade_spider
-		MOBS.put(20479, new ItemChanceHolder(KASHA_BEAR_PELT, 1.0, 1)); // kasha_bear
-		MOBS.put(20335, new ItemChanceHolder(GRIZZLY_BLOOD, 1.0, 6)); // grizzly_bear
-		MOBS.put(20038, new ItemChanceHolder(DURKA_PARASITE, 1.0, 9)); // poison_spider
-		MOBS.put(20043, new ItemChanceHolder(DURKA_PARASITE, 1.0, 9)); // bind_poison_spider
-		MOBS.put(27056, new ItemChanceHolder(DURKA_PARASITE, 1.0, 9)); // durka_spirit
-	}
-	
+	private static final Map<Integer, Integer> MOBS_CONDITIONS = Map.of(
+			SCARLET_SALAMANDER, 1,
+			KASHA_BLADE_SPIDER, 1,
+			KASHA_BEAR, 1,
+			GRIZZLY_BEAR, 6,
+			20038, 9, // poison_spider
+			20043, 9, // bind_poison_spider
+			DURKA_SPIRIT, 9);
+
 	public Q00416_PathOfTheOrcShaman() {
 		super(416, Q00416_PathOfTheOrcShaman.class.getSimpleName(), "Path of the Orc Shaman");
 		addStartNpc(TATARU_ZU_HESTUI);
 		addTalkId(TATARU_ZU_HESTUI, UMOS, MOIRA, DEAD_LEOPARDS_CARCASS, DUDA_MARA_TOTEM_SPIRIT, HESTUI_TOTEM_SPIRIT, TOTEM_SPIRIT_OF_GANDI);
-		addKillId(MOBS.keySet());
+		addKillId(MOBS_CONDITIONS.keySet());
 		addKillId(BLACK_LEOPARD);
-		registerQuestItems(FIRE_CHARM, KASHA_BEAR_PELT, KASHA_BLADE_SPIDER_HUSK, FIRST_FIERY_EGG, HESTUI_MASK, SECOND_FIERY_EGG, TOTEM_SPIRIT_CLAW, TATARUS_LETTER, FLAME_CHARM, GRIZZLY_BLOOD, BLOOD_CAULDRON, SPIRIT_NET, BOUND_DURKA_SPIRIT, DURKA_PARASITE, TOTEM_SPIRIT_BLOOD);
+		registerQuestItems(FIRE_CHARM, KASHA_BEAR_PELT.getId(), KASHA_BLADE_SPIDER_HUSK.getId(), FIRST_FIERY_EGG.getId(), HESTUI_MASK, SECOND_FIERY_EGG, TOTEM_SPIRIT_CLAW, TATARUS_LETTER, FLAME_CHARM, GRIZZLY_BLOOD.getId(), BLOOD_CAULDRON, SPIRIT_NET, BOUND_DURKA_SPIRIT, DURKA_PARASITE, TOTEM_SPIRIT_BLOOD);
 	}
 	
 	@Override
@@ -238,44 +248,38 @@ public final class Q00416_PathOfTheOrcShaman extends Quest {
 		
 		if (npc.getId() == BLACK_LEOPARD) {
 			switch (st.getMemoState()) {
-				case 102: {
-					st.setMemoState(103);
-					break;
-				}
-				case 103: {
+				case 102 -> st.setMemoState(103);
+				case 103 -> {
 					st.setMemoState(104);
 					st.setCond(15, true);
 					if (getRandom(100) < 66) {
 						npc.broadcastPacket(new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), NpcStringId.MY_DEAR_FRIEND_OF_S1_WHO_HAS_GONE_ON_AHEAD_OF_ME).addStringParameter(st.getPlayer().getName()));
 					}
-					break;
 				}
-				case 105: {
+				case 105 -> {
 					st.setMemoState(106);
 					st.setCond(17, true);
 					if (getRandom(100) < 66) {
 						npc.broadcastPacket(new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), NpcStringId.LISTEN_TO_TEJAKAR_GANDI_YOUNG_OROKA_THE_SPIRIT_OF_THE_SLAIN_LEOPARD_IS_CALLING_YOU_S1).addStringParameter(st.getPlayer().getName()));
 					}
-					break;
 				}
-				case 107: {
+				case 107 -> {
 					st.setMemoState(108);
 					st.setCond(19, true);
-					break;
 				}
 			}
 			return super.onKill(npc, player, isSummon);
 		}
 		
-		final ItemChanceHolder item = MOBS.get(npc.getId());
-		if (item.getCount() == st.getCond()) {
+		final int mobCond = MOBS_CONDITIONS.get(npc.getId());
+		if (mobCond == st.getCond()) {
 			if (st.isCond(1) && hasQuestItems(st.getPlayer(), FIRE_CHARM)) {
-				if (giveItemRandomly(st.getPlayer(), npc, item.getId(), 1, 1, item.getChance(), true) //
-					&& hasQuestItems(st.getPlayer(), FIRST_FIERY_EGG, KASHA_BLADE_SPIDER_HUSK, KASHA_BEAR_PELT)) {
-					st.setCond(2, true);
+				if (giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)
+					&& hasQuestItems(st.getPlayer(), FIRST_FIERY_EGG.getId(), KASHA_BLADE_SPIDER_HUSK.getId(), KASHA_BEAR_PELT.getId())) {
+					st.setCond(2);
 				}
 			} else if (st.isCond(6) && hasQuestItems(st.getPlayer(), FLAME_CHARM)) {
-				if (giveItemRandomly(st.getPlayer(), npc, item.getId(), 1, 3, item.getChance(), true)) {
+				if (giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
 					st.setCond(7);
 				}
 			} else if (st.isCond(9) && hasQuestItems(st.getPlayer(), SPIRIT_NET) //
@@ -317,10 +321,10 @@ public final class Q00416_PathOfTheOrcShaman extends Quest {
 				case TATARU_ZU_HESTUI: {
 					if (st.isMemoState(1)) {
 						if (hasQuestItems(player, FIRE_CHARM)) {
-							if (getQuestItemsCount(player, KASHA_BEAR_PELT, KASHA_BLADE_SPIDER_HUSK, FIRST_FIERY_EGG) < 3) {
+							if (!hasItemsAtLimit(player, KASHA_BEAR_PELT, KASHA_BLADE_SPIDER_HUSK, FIRST_FIERY_EGG)) {
 								htmltext = "30585-08.html";
 							} else {
-								takeItems(player, -1, FIRE_CHARM, KASHA_BEAR_PELT, KASHA_BLADE_SPIDER_HUSK, FIRST_FIERY_EGG);
+								takeItems(player, -1, FIRE_CHARM, KASHA_BEAR_PELT.getId(), KASHA_BLADE_SPIDER_HUSK.getId(), FIRST_FIERY_EGG.getId());
 								giveItems(player, HESTUI_MASK, 1);
 								giveItems(player, SECOND_FIERY_EGG, 1);
 								st.setCond(3, true);
@@ -332,7 +336,7 @@ public final class Q00416_PathOfTheOrcShaman extends Quest {
 							htmltext = "30585-11.html";
 						} else if (hasQuestItems(player, TATARUS_LETTER)) {
 							htmltext = "30585-15.html";
-						} else if (hasAtLeastOneQuestItem(player, GRIZZLY_BLOOD, FLAME_CHARM, BLOOD_CAULDRON, SPIRIT_NET, BOUND_DURKA_SPIRIT, TOTEM_SPIRIT_BLOOD)) {
+						} else if (hasAtLeastOneQuestItem(player, GRIZZLY_BLOOD.getId(), FLAME_CHARM, BLOOD_CAULDRON, SPIRIT_NET, BOUND_DURKA_SPIRIT, TOTEM_SPIRIT_BLOOD)) {
 							htmltext = "30585-16.html";
 						}
 					} else if (st.isMemoState(100)) {
@@ -348,10 +352,10 @@ public final class Q00416_PathOfTheOrcShaman extends Quest {
 							st.setCond(6, true);
 							htmltext = "30502-01.html";
 						} else if (hasQuestItems(player, FLAME_CHARM)) {
-							if (getQuestItemsCount(player, GRIZZLY_BLOOD) < 3) {
+							if (!hasItemsAtLimit(player, GRIZZLY_BLOOD)) {
 								htmltext = "30502-02.html";
 							} else {
-								takeItems(player, -1, FLAME_CHARM, GRIZZLY_BLOOD);
+								takeItems(player, -1, FLAME_CHARM, GRIZZLY_BLOOD.getId());
 								giveItems(player, BLOOD_CAULDRON, 1);
 								st.setCond(8, true);
 								htmltext = "30502-03.html";
@@ -449,7 +453,7 @@ public final class Q00416_PathOfTheOrcShaman extends Quest {
 							htmltext = "30592-01.html";
 						} else if (hasQuestItems(player, TOTEM_SPIRIT_CLAW)) {
 							htmltext = "30592-04.html";
-						} else if (hasAtLeastOneQuestItem(player, GRIZZLY_BLOOD, FLAME_CHARM, BLOOD_CAULDRON, SPIRIT_NET, BOUND_DURKA_SPIRIT, TOTEM_SPIRIT_BLOOD, TATARUS_LETTER)) {
+						} else if (hasAtLeastOneQuestItem(player, GRIZZLY_BLOOD.getId(), FLAME_CHARM, BLOOD_CAULDRON, SPIRIT_NET, BOUND_DURKA_SPIRIT, TOTEM_SPIRIT_BLOOD, TATARUS_LETTER)) {
 							htmltext = "30592-05.html";
 						}
 					}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00417_PathOfTheScavenger/Q00417_PathOfTheScavenger.java b/src/main/java/com/l2jserver/datapack/quests/Q00417_PathOfTheScavenger/Q00417_PathOfTheScavenger.java
index f792e49b44..d1ad7ee5ac 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00417_PathOfTheScavenger/Q00417_PathOfTheScavenger.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00417_PathOfTheScavenger/Q00417_PathOfTheScavenger.java
@@ -22,6 +22,7 @@ import com.l2jserver.gameserver.model.actor.L2Attackable;
 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.QuestState;
 import com.l2jserver.gameserver.model.skills.Skill;
@@ -56,10 +57,10 @@ public final class Q00417_PathOfTheScavenger extends Quest {
 	private static final int ZIMENFS_PAY = 1652;
 	private static final int BEAR_PICTURE = 1653;
 	private static final int TARANTULA_PICTURE = 1654;
-	private static final int HONEY_JAR = 1655;
-	private static final int BEAD = 1656;
 	private static final int BEAD_PARCEL = 1657;
 	private static final int BEAD_PARCEL2 = 8543;
+	private static final QuestItemChanceHolder HONEY_JAR = new QuestItemChanceHolder(1655, 5L);
+	private static final QuestItemChanceHolder BEAD = new QuestItemChanceHolder(1656, 20L);
 	// Reward
 	private static final int RING_OF_RAVEN = 1642;
 	// Monster
@@ -81,7 +82,7 @@ public final class Q00417_PathOfTheScavenger extends Quest {
 		addTalkId(COLLECTOR_PIPI, WAREHOUSE_KEEPER_RAUT, TRADER_MION, TRADER_SHARI, HEAD_BLACKSMITH_BRONK, PRIEST_OF_THE_EARTH_ZIMENF, MASTER_TOMA, TORAI, WAREHOUSE_CHIEF_YASENI);
 		addAttackId(HUNTER_TARANTULA, PLUNDER_TARANTULA, HUNTER_BEAR, HONEY_BEAR);
 		addKillId(HUNTER_TARANTULA, PLUNDER_TARANTULA, HUNTER_BEAR, HONEY_BEAR);
-		registerQuestItems(PIPPIS_LETTER_OF_RECOMMENDATION, ROUTS_TELEPORT_SCROLL, SUCCUBUS_UNDIES, MIONS_LETTER, BRONKS_INGOT, SHARIS_AXE, ZIMENFS_POTION, BRONKS_PAY, SHARIS_PAY, ZIMENFS_PAY, BEAR_PICTURE, TARANTULA_PICTURE, HONEY_JAR, BEAD, BEAD_PARCEL, BEAD_PARCEL2);
+		registerQuestItems(PIPPIS_LETTER_OF_RECOMMENDATION, ROUTS_TELEPORT_SCROLL, SUCCUBUS_UNDIES, MIONS_LETTER, BRONKS_INGOT, SHARIS_AXE, ZIMENFS_POTION, BRONKS_PAY, SHARIS_PAY, ZIMENFS_PAY, BEAR_PICTURE, TARANTULA_PICTURE, HONEY_JAR.getId(), BEAD.getId(), BEAD_PARCEL, BEAD_PARCEL2);
 	}
 	
 	@Override
@@ -204,9 +205,9 @@ public final class Q00417_PathOfTheScavenger extends Quest {
 				break;
 			}
 			case "30556-05b.html": {
-				if (hasQuestItems(player, TARANTULA_PICTURE) && (getQuestItemsCount(player, BEAD) >= 20)) {
+				if (hasQuestItems(player, TARANTULA_PICTURE) && hasItemsAtLimit(player, BEAD)) {
 					takeItems(player, TARANTULA_PICTURE, 1);
-					takeItems(player, BEAD, -1);
+					takeItems(player, BEAD.getId(), -1);
 					giveItems(player, BEAD_PARCEL, 1);
 					qs.setCond(9, true);
 					htmltext = event;
@@ -214,9 +215,9 @@ public final class Q00417_PathOfTheScavenger extends Quest {
 				break;
 			}
 			case "30556-06b.html": {
-				if (hasQuestItems(player, TARANTULA_PICTURE) && (getQuestItemsCount(player, BEAD) >= 20)) {
+				if (hasQuestItems(player, TARANTULA_PICTURE) && hasItemsAtLimit(player, BEAD)) {
 					takeItems(player, TARANTULA_PICTURE, 1);
-					takeItems(player, BEAD, -1);
+					takeItems(player, BEAD.getId(), -1);
 					giveItems(player, BEAD_PARCEL2, 1);
 					qs.setMemoState(2);
 					qs.setCond(12, true);
@@ -323,8 +324,8 @@ public final class Q00417_PathOfTheScavenger extends Quest {
 		if ((qs != null) && qs.isStarted() && Util.checkIfInRange(1500, npc, killer, true) && npc.isAttackable()) {
 			final boolean firstAttacker = (killer.getObjectId() == npc.getVariables().getInt(FIRST_ATTACKER));
 			switch (npc.getId()) {
-				case HUNTER_BEAR: {
-					if (npc.isScriptValue(1) && firstAttacker && hasQuestItems(killer, BEAR_PICTURE) && (getQuestItemsCount(killer, HONEY_JAR) < 5)) {
+				case HUNTER_BEAR -> {
+					if (npc.isScriptValue(1) && firstAttacker && hasQuestItems(killer, BEAR_PICTURE) && !hasItemsAtLimit(killer, HONEY_JAR)) {
 						final int flag = qs.getInt(FLAG);
 						if ((flag > 0) && (getRandom(100) < (20 * flag))) {
 							addSpawn(HONEY_BEAR, npc, true, 0, true);
@@ -333,24 +334,20 @@ public final class Q00417_PathOfTheScavenger extends Quest {
 							qs.set(FLAG, flag + 1);
 						}
 					}
-					break;
 				}
-				case HONEY_BEAR: {
+				case HONEY_BEAR -> {
 					if (npc.isScriptValue(2) && firstAttacker && ((L2Attackable) npc).isSpoiled() && hasQuestItems(killer, BEAR_PICTURE)) {
-						if (giveItemRandomly(killer, npc, HONEY_JAR, 1, 5, 1.0, true)) {
+						if (giveItemRandomly(killer, npc, HONEY_JAR, true)) {
 							qs.setCond(6);
 						}
 					}
-					break;
 				}
-				case HUNTER_TARANTULA:
-				case PLUNDER_TARANTULA: {
+				case HUNTER_TARANTULA, PLUNDER_TARANTULA -> {
 					if (npc.isScriptValue(2) && firstAttacker && ((L2Attackable) npc).isSpoiled() && hasQuestItems(killer, TARANTULA_PICTURE)) {
-						if (giveItemRandomly(killer, npc, BEAD, 1, 20, 1.0, true)) {
+						if (giveItemRandomly(killer, npc, BEAD, true)) {
 							qs.setCond(8);
 						}
 					}
-					break;
 				}
 			}
 		}
@@ -471,17 +468,17 @@ public final class Q00417_PathOfTheScavenger extends Quest {
 						qs.set(FLAG, 0);
 						htmltext = "30556-01.html";
 					} else if (hasQuestItems(player, BEAR_PICTURE)) {
-						if (getQuestItemsCount(player, HONEY_JAR) < 5) {
+						if (!hasItemsAtLimit(player, HONEY_JAR)) {
 							htmltext = "30556-02.html";
 						} else {
 							takeItems(player, BEAR_PICTURE, 1);
 							giveItems(player, TARANTULA_PICTURE, 1);
-							takeItems(player, HONEY_JAR, -1);
+							takeItems(player, HONEY_JAR.getId(), -1);
 							qs.setCond(7, true);
 							htmltext = "30556-03.html";
 						}
 					} else if (hasQuestItems(player, TARANTULA_PICTURE)) {
-						if (getQuestItemsCount(player, BEAD) < 20) {
+						if (!hasItemsAtLimit(player, BEAD)) {
 							htmltext = "30556-04.html";
 						} else {
 							htmltext = "30556-05a.html";
@@ -534,4 +531,4 @@ public final class Q00417_PathOfTheScavenger extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00420_LittleWing/Q00420_LittleWing.java b/src/main/java/com/l2jserver/datapack/quests/Q00420_LittleWing/Q00420_LittleWing.java
index fbdf2ff31a..d9f5e43de6 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00420_LittleWing/Q00420_LittleWing.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00420_LittleWing/Q00420_LittleWing.java
@@ -18,14 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00420_LittleWing;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-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.QuestState;
 import com.l2jserver.gameserver.model.quest.State;
@@ -33,6 +29,13 @@ import com.l2jserver.gameserver.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
 import com.l2jserver.gameserver.network.serverpackets.NpcSay;
 
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.l2jserver.gameserver.model.quest.QuestDroplist.singleDropItem;
+
 /**
  * Little Wing (420)
  * @author Pandragon
@@ -61,7 +64,6 @@ public final class Q00420_LittleWing extends Quest {
 	private static final int DELUXE_FAIRY_STONE = 3817;
 	private static final int FAIRY_STONE_LIST = 3818;
 	private static final int DELUXE_STONE_LIST = 3819;
-	private static final int TOAD_SKIN = 3820;
 	private static final int MONKSHOOD_JUICE = 3821;
 	private static final int EXARION_SCALE = 3822;
 	private static final int EXARION_EGG = 3823;
@@ -73,6 +75,9 @@ public final class Q00420_LittleWing extends Quest {
 	private static final int SUZET_EGG = 3829;
 	private static final int SHAMHAI_SCALE = 3830;
 	private static final int SHAMHAI_EGG = 3831;
+	private static final long TOAD_SKIN_FAIRY_STONE_LIMIT = 10;
+	private static final long TOAD_SKIN_DELUXE_FAIRY_STONE_LIMIT = 20;
+	private static final QuestItemChanceHolder TOAD_SKIN = new QuestItemChanceHolder(3820, 30.0);
 	// Monsters
 	private static final int DEAD_SEEKER = 20202;
 	private static final int TOAD_LORD = 20231;
@@ -123,7 +128,7 @@ public final class Q00420_LittleWing extends Quest {
 		addTalkId(MARIA, CRONOS, BYRON, MIMYU, EXARION, ZWOV, KALIBRAN, SUZET, SHAMHAI, COOPER);
 		addAttackId(DELUXE_STONE_BREAKERS);
 		addKillId(TOAD_LORD, DEAD_SEEKER, MARSH_SPIDER, BREKA_OVERLORD, ROAD_SCAVENGER, LETO_WARRIOR);
-		registerQuestItems(FAIRY_DUST, FAIRY_STONE, DELUXE_FAIRY_STONE, FAIRY_STONE_LIST, DELUXE_STONE_LIST, TOAD_SKIN, MONKSHOOD_JUICE, EXARION_SCALE, EXARION_EGG, ZWOV_SCALE, ZWOV_EGG, KALIBRAN_SCALE, KALIBRAN_EGG, SUZET_SCALE, SUZET_EGG, SHAMHAI_SCALE, SHAMHAI_EGG);
+		registerQuestItems(FAIRY_DUST, FAIRY_STONE, DELUXE_FAIRY_STONE, FAIRY_STONE_LIST, DELUXE_STONE_LIST, TOAD_SKIN.getId(), MONKSHOOD_JUICE, EXARION_SCALE, EXARION_EGG, ZWOV_SCALE, ZWOV_EGG, KALIBRAN_SCALE, KALIBRAN_EGG, SUZET_SCALE, SUZET_EGG, SHAMHAI_SCALE, SHAMHAI_EGG);
 	}
 	
 	@Override
@@ -194,13 +199,14 @@ public final class Q00420_LittleWing extends Quest {
 			}
 			case "30608-03.html": {
 				if (qs.isCond(2)) {
-					if ((qs.getInt("fairy_stone") == 1) && (getQuestItemsCount(player, COAL) >= 10) && (getQuestItemsCount(player, CHARCOAL) >= 10) && (getQuestItemsCount(player, GEMSTONE_D) >= 1) && (getQuestItemsCount(player, SILVER_NUGGET) >= 3) && (getQuestItemsCount(player, TOAD_SKIN) >= 10)) {
+					if ((qs.getInt("fairy_stone") == 1) && (getQuestItemsCount(player, COAL) >= 10) && (getQuestItemsCount(player, CHARCOAL) >= 10) && (getQuestItemsCount(player, GEMSTONE_D) >= 1)
+							&& (getQuestItemsCount(player, SILVER_NUGGET) >= 3) && (getQuestItemsCount(player, TOAD_SKIN.getId()) >= TOAD_SKIN_FAIRY_STONE_LIMIT)) {
 						takeItems(player, FAIRY_STONE_LIST, -1);
 						takeItems(player, COAL, 10);
 						takeItems(player, CHARCOAL, 10);
 						takeItems(player, GEMSTONE_D, 1);
 						takeItems(player, SILVER_NUGGET, 3);
-						takeItems(player, TOAD_SKIN, -1);
+						takeItems(player, TOAD_SKIN.getId(), -1);
 						giveItems(player, FAIRY_STONE, 1);
 					}
 					qs.setCond(3, true);
@@ -211,14 +217,14 @@ public final class Q00420_LittleWing extends Quest {
 			case "30608-05.html": {
 				if (qs.isCond(2)) {
 					if ((qs.getInt("fairy_stone") == 2) && (getQuestItemsCount(player, COAL) >= 10) && (getQuestItemsCount(player, CHARCOAL) >= 10) && (getQuestItemsCount(player, GEMSTONE_C) >= 1) && (getQuestItemsCount(player, STONE_OF_PURITY) >= 1)
-						&& (getQuestItemsCount(player, SILVER_NUGGET) >= 5) && (getQuestItemsCount(player, TOAD_SKIN) >= 20)) {
+							&& (getQuestItemsCount(player, SILVER_NUGGET) >= 5) && (getQuestItemsCount(player, TOAD_SKIN.getId()) >= TOAD_SKIN_DELUXE_FAIRY_STONE_LIMIT)) {
 						takeItems(player, DELUXE_STONE_LIST, -1);
 						takeItems(player, COAL, 10);
 						takeItems(player, CHARCOAL, 10);
 						takeItems(player, GEMSTONE_C, 1);
 						takeItems(player, STONE_OF_PURITY, 1);
 						takeItems(player, SILVER_NUGGET, 5);
-						takeItems(player, TOAD_SKIN, -1);
+						takeItems(player, TOAD_SKIN.getId(), -1);
 						giveItems(player, DELUXE_FAIRY_STONE, 1);
 					}
 					qs.setCond(3, true);
@@ -423,10 +429,10 @@ public final class Q00420_LittleWing extends Quest {
 						switch (qs.getCond()) {
 							case 2: {
 								if ((qs.getInt("fairy_stone") == 1) && (getQuestItemsCount(talker, COAL) >= 10) && (getQuestItemsCount(talker, CHARCOAL) >= 10) && (getQuestItemsCount(talker, GEMSTONE_D) >= 1) && (getQuestItemsCount(talker, SILVER_NUGGET) >= 3)
-									&& (getQuestItemsCount(talker, TOAD_SKIN) >= 10)) {
+									&& (getQuestItemsCount(talker, TOAD_SKIN.getId()) >= TOAD_SKIN_FAIRY_STONE_LIMIT)) {
 									htmltext = "30608-02.html";
 								} else if ((qs.getInt("fairy_stone") == 2) && (getQuestItemsCount(talker, COAL) >= 10) && (getQuestItemsCount(talker, CHARCOAL) >= 10) && (getQuestItemsCount(talker, GEMSTONE_C) >= 1) && (getQuestItemsCount(talker, STONE_OF_PURITY) >= 1)
-									&& (getQuestItemsCount(talker, SILVER_NUGGET) >= 5) && (getQuestItemsCount(talker, TOAD_SKIN) >= 20)) {
+									&& (getQuestItemsCount(talker, SILVER_NUGGET) >= 5) && (getQuestItemsCount(talker, TOAD_SKIN.getId()) >= TOAD_SKIN_DELUXE_FAIRY_STONE_LIMIT)) {
 									htmltext = "30608-04.html";
 								} else {
 									htmltext = "30608-01.html";
@@ -654,9 +660,9 @@ public final class Q00420_LittleWing extends Quest {
 		if (qs != null) {
 			if (qs.isCond(2) && (npc.getId() == TOAD_LORD)) {
 				if (qs.getInt("fairy_stone") == 1) {
-					giveItemRandomly(qs.getPlayer(), npc, TOAD_SKIN, 1, 10, 0.3, true);
+					giveItemRandomly(qs.getPlayer(), npc, singleDropItem(TOAD_SKIN), TOAD_SKIN_FAIRY_STONE_LIMIT, true);
 				} else {
-					giveItemRandomly(qs.getPlayer(), npc, TOAD_SKIN, 1, 20, 0.3, true);
+					giveItemRandomly(qs.getPlayer(), npc, singleDropItem(TOAD_SKIN), TOAD_SKIN_DELUXE_FAIRY_STONE_LIMIT, true);
 				}
 			} else if (qs.isCond(6) && (npc.getId() == qs.getInt("drake_hunt"))) {
 				giveItemRandomly(qs.getPlayer(), npc, EGG_DROPS.get(npc.getId()), 1, 20, 0.5, true);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00501_ProofOfClanAlliance/Q00501_ProofOfClanAlliance.java b/src/main/java/com/l2jserver/datapack/quests/Q00501_ProofOfClanAlliance/Q00501_ProofOfClanAlliance.java
index 31ef720e54..95c6cda9db 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00501_ProofOfClanAlliance/Q00501_ProofOfClanAlliance.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00501_ProofOfClanAlliance/Q00501_ProofOfClanAlliance.java
@@ -18,25 +18,25 @@
  */
 package com.l2jserver.datapack.quests.Q00501_ProofOfClanAlliance;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
 import com.l2jserver.gameserver.model.L2Clan;
 import com.l2jserver.gameserver.model.Location;
 import com.l2jserver.gameserver.model.actor.L2Character;
 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.holders.SkillHolder;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
 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;
 import com.l2jserver.gameserver.model.skills.AbnormalType;
 import com.l2jserver.gameserver.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
 import com.l2jserver.gameserver.network.serverpackets.NpcSay;
-import com.l2jserver.gameserver.util.Util;
+
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Proof of Clan Alliance (501)
@@ -58,9 +58,6 @@ public final class Q00501_ProofOfClanAlliance extends Quest {
 	private static final int BOX_OF_ATHREA_4 = 27176;
 	private static final int BOX_OF_ATHREA_5 = 27177;
 	// Items
-	private static final int HERB_OF_HARIT = 3832;
-	private static final int HERB_OF_VANOR = 3833;
-	private static final int HERB_OF_OEL_MAHUM = 3834;
 	private static final int BLOOD_OF_EVA = 3835;
 	private static final int ATHREAS_COIN = 3836;
 	private static final int SYMBOL_OF_LOYALTY = 3837;
@@ -68,6 +65,15 @@ public final class Q00501_ProofOfClanAlliance extends Quest {
 	private static final int VOUCHER_OF_FAITH = 3873;
 	private static final int ALLIANCE_MANIFESTO = 3874;
 	private static final int POTION_OF_RECOVERY = 3889;
+	private static final QuestItemChanceHolder HERB_OF_HARIT = new QuestItemChanceHolder(3832, 10.0);
+	private static final QuestItemChanceHolder HERB_OF_VANOR = new QuestItemChanceHolder(3833, 10.0);
+	private static final QuestItemChanceHolder HERB_OF_OEL_MAHUM = new QuestItemChanceHolder(3834, 10.0);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(OEL_MAHUM_WITCH_DOCTOR, HERB_OF_OEL_MAHUM)
+			.addSingleDrop(HARIT_LIZARDMAN_SHAMAN, HERB_OF_HARIT)
+			.addSingleDrop(VANOR_SILENOS_SHAMAN, HERB_OF_VANOR)
+			.build();
 	// Skills
 	private static final SkillHolder POISON_OF_DEATH = new SkillHolder(4082);
 	private static final SkillHolder DIE_YOU_FOOL = new SkillHolder(4083);
@@ -101,7 +107,7 @@ public final class Q00501_ProofOfClanAlliance extends Quest {
 		addStartNpc(SIR_KRISTOF_RODEMAI, STATUE_OF_OFFERING);
 		addTalkId(SIR_KRISTOF_RODEMAI, STATUE_OF_OFFERING, ATHREA, KALIS);
 		addKillId(OEL_MAHUM_WITCH_DOCTOR, HARIT_LIZARDMAN_SHAMAN, VANOR_SILENOS_SHAMAN, BOX_OF_ATHREA_1, BOX_OF_ATHREA_2, BOX_OF_ATHREA_3, BOX_OF_ATHREA_4, BOX_OF_ATHREA_5);
-		registerQuestItems(ANTIDOTE_RECIPE_LIST, VOUCHER_OF_FAITH, HERB_OF_HARIT, HERB_OF_VANOR, HERB_OF_OEL_MAHUM, BLOOD_OF_EVA, ATHREAS_COIN, SYMBOL_OF_LOYALTY);
+		registerQuestItems(ANTIDOTE_RECIPE_LIST, VOUCHER_OF_FAITH, HERB_OF_HARIT.getId(), HERB_OF_VANOR.getId(), HERB_OF_OEL_MAHUM.getId(), BLOOD_OF_EVA, ATHREAS_COIN, SYMBOL_OF_LOYALTY);
 	}
 	
 	@Override
@@ -218,29 +224,12 @@ public final class Q00501_ProofOfClanAlliance extends Quest {
 		final QuestState lqs = getLeaderQuestState(player, getName());
 		if (lqs != null) {
 			switch (npc.getId()) {
-				case OEL_MAHUM_WITCH_DOCTOR: {
-					if ((getRandom(10) == 1) && (lqs.getMemoState() >= 3) && (lqs.getMemoState() < 6)) {
-						giveItemRandomly(player, npc, HERB_OF_OEL_MAHUM, 1, 0, 1.0, true);
-					}
-					break;
-				}
-				case HARIT_LIZARDMAN_SHAMAN: {
-					if ((getRandom(10) == 1) && (lqs.getMemoState() >= 3) && (lqs.getMemoState() < 6)) {
-						giveItemRandomly(player, npc, HERB_OF_HARIT, 1, 0, 1.0, true);
+				case OEL_MAHUM_WITCH_DOCTOR, HARIT_LIZARDMAN_SHAMAN, VANOR_SILENOS_SHAMAN -> {
+					if ((lqs.getMemoState() >= 3) && (lqs.getMemoState() < 6)) {
+						giveItemRandomly(player, npc, DROPLIST.get(npc), true);
 					}
-					break;
 				}
-				case VANOR_SILENOS_SHAMAN: {
-					if ((getRandom(10) == 1) && (lqs.getMemoState() >= 3) && (lqs.getMemoState() < 6)) {
-						giveItemRandomly(player, npc, HERB_OF_VANOR, 1, 0, 1.0, true);
-					}
-					break;
-				}
-				case BOX_OF_ATHREA_1:
-				case BOX_OF_ATHREA_2:
-				case BOX_OF_ATHREA_3:
-				case BOX_OF_ATHREA_4:
-				case BOX_OF_ATHREA_5: {
+				case BOX_OF_ATHREA_1, BOX_OF_ATHREA_2, BOX_OF_ATHREA_3, BOX_OF_ATHREA_4, BOX_OF_ATHREA_5 -> {
 					final L2Character summoner = npc.getSummoner();
 					if ((summoner != null) && summoner.isNpc() && lqs.isMemoState(4)) {
 						final L2Npc arthea = (L2Npc) summoner;
@@ -264,7 +253,6 @@ public final class Q00501_ProofOfClanAlliance extends Quest {
 						}
 						arthea.setScriptValue(arthea.getScriptValue() + 1);
 					}
-					break;
 				}
 			}
 		}
@@ -365,14 +353,14 @@ public final class Q00501_ProofOfClanAlliance extends Quest {
 					htmltext = "30759-05.html";
 				} else if ((getQuestItemsCount(player, SYMBOL_OF_LOYALTY) >= 3) && !hasAbnormal(player)) {
 					htmltext = "30759-06.html";
-				} else if (qs.isMemoState(5) && hasQuestItems(player, BLOOD_OF_EVA) && hasQuestItems(player, HERB_OF_VANOR) && hasQuestItems(player, HERB_OF_HARIT) && hasQuestItems(player, HERB_OF_OEL_MAHUM) && hasAbnormal(player)) {
+				} else if (qs.isMemoState(5) && hasQuestItems(player, BLOOD_OF_EVA) && hasQuestItems(player, HERB_OF_VANOR.getId()) && hasQuestItems(player, HERB_OF_HARIT.getId()) && hasQuestItems(player, HERB_OF_OEL_MAHUM.getId()) && hasAbnormal(player)) {
 					giveItems(player, VOUCHER_OF_FAITH, 1);
 					giveItems(player, POTION_OF_RECOVERY, 1);
 					takeItems(player, BLOOD_OF_EVA, -1);
 					takeItems(player, ANTIDOTE_RECIPE_LIST, -1);
-					takeItems(player, HERB_OF_OEL_MAHUM, -1);
-					takeItems(player, HERB_OF_HARIT, -1);
-					takeItems(player, HERB_OF_VANOR, -1);
+					takeItems(player, HERB_OF_OEL_MAHUM.getId(), -1);
+					takeItems(player, HERB_OF_HARIT.getId(), -1);
+					takeItems(player, HERB_OF_VANOR.getId(), -1);
 					qs.setCond(4, true);
 					qs.setMemoState(6);
 					htmltext = "30759-08.html";
@@ -380,7 +368,7 @@ public final class Q00501_ProofOfClanAlliance extends Quest {
 					takeItems(player, ANTIDOTE_RECIPE_LIST, -1);
 					qs.setMemoState(1);
 					htmltext = "30759-09.html";
-				} else if ((qs.getMemoState() < 6) && (getQuestItemsCount(player, SYMBOL_OF_LOYALTY) >= 3) && !hasAtLeastOneQuestItem(player, BLOOD_OF_EVA, HERB_OF_VANOR, HERB_OF_HARIT, HERB_OF_OEL_MAHUM) && hasAbnormal(player)) {
+				} else if ((qs.getMemoState() < 6) && (getQuestItemsCount(player, SYMBOL_OF_LOYALTY) >= 3) && !hasAtLeastOneQuestItem(player, BLOOD_OF_EVA, HERB_OF_VANOR.getId(), HERB_OF_HARIT.getId(), HERB_OF_OEL_MAHUM.getId()) && hasAbnormal(player)) {
 					htmltext = "30759-10.html";
 				} else if (qs.isMemoState(6)) {
 					htmltext = "30759-11.html";
@@ -417,47 +405,4 @@ public final class Q00501_ProofOfClanAlliance extends Quest {
 		}
 		return null;
 	}
-	
-	@Override
-	public QuestState getRandomPartyMemberState(L2PcInstance player, int condition, int playerChance, L2Npc target) {
-		if ((player == null) || (playerChance < 1)) {
-			return null;
-		}
-		
-		QuestState qs = getQuestState(player, false);
-		if (!player.isInParty()) {
-			if (!Util.checkIfInRange(1500, player, target, true)) {
-				return null;
-			}
-			return qs;
-		}
-		
-		final List<QuestState> candidates = new ArrayList<>();
-		if ((qs != null) && (playerChance > 0)) {
-			for (int i = 0; i < playerChance; i++) {
-				candidates.add(qs);
-			}
-		}
-		
-		for (L2PcInstance member : player.getParty().getMembers()) {
-			if (member == player) {
-				continue;
-			}
-			
-			qs = getQuestState(member, false);
-			if (qs != null) {
-				candidates.add(qs);
-			}
-		}
-		
-		if (candidates.isEmpty()) {
-			return null;
-		}
-		
-		qs = candidates.get(getRandom(candidates.size()));
-		if (!Util.checkIfInRange(1500, qs.getPlayer(), target, true)) {
-			return null;
-		}
-		return qs;
-	}
 }
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00503_PursuitOfClanAmbition/Q00503_PursuitOfClanAmbition.java b/src/main/java/com/l2jserver/datapack/quests/Q00503_PursuitOfClanAmbition/Q00503_PursuitOfClanAmbition.java
index 0702e57e74..447c63a101 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00503_PursuitOfClanAmbition/Q00503_PursuitOfClanAmbition.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00503_PursuitOfClanAmbition/Q00503_PursuitOfClanAmbition.java
@@ -21,6 +21,7 @@ package com.l2jserver.datapack.quests.Q00503_PursuitOfClanAmbition;
 import com.l2jserver.gameserver.model.L2Clan;
 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;
 import com.l2jserver.gameserver.network.NpcStringId;
@@ -46,23 +47,6 @@ public final class Q00503_PursuitOfClanAmbition extends Quest {
 	private static final int IMPERIAL_COFFER = 30765;
 	private static final int WITCH_CLEO = 30766;
 	private static final int SIR_ERIC_RODEMAI = 30868;
-	// Items
-	private static final int MIST_DRAKES_EGG = 3839;
-	private static final int BLITZ_WYRM_EGG = 3840;
-	private static final int DRAKES_EGG = 3841;
-	private static final int THUNDER_WYRM_EGG = 3842;
-	private static final int BROOCH_OF_THE_MAGPIE = 3843;
-	private static final int IMPERIAL_KEY = 3847;
-	private static final int GUSTAVS_1ST_LETTER = 3866;
-	private static final int GUSTAVS_2ND_LETTER = 3867;
-	private static final int GUSTAVS_3RD_LETTER = 3868;
-	private static final int SCEPTER_OF_JUDGMENT = 3869;
-	private static final int BLACK_ANVIL_COIN = 3871;
-	private static final int RECIPE_SPITEFUL_SOUL_ENERGY = 14854;
-	private static final int SPITEFUL_SOUL_ENERGY = 14855;
-	private static final int SPITEFUL_SOUL_VENGEANCE = 14856;
-	// Reward
-	private static final int SEAL_OF_ASPIRATION = 3870;
 	// Monsters
 	private static final int DRAKE = 20137;
 	private static final int DRAKE2 = 20285;
@@ -74,14 +58,31 @@ public final class Q00503_PursuitOfClanAmbition extends Quest {
 	private static final int GRAVE_KEYMASTER = 27179;
 	private static final int IMPERIAL_GRAVEKEEPER = 27181;
 	private static final int BLITZ_WYRM = 27178;
-	
+	// Items
+	private static final int BROOCH_OF_THE_MAGPIE = 3843;
+	private static final int GUSTAVS_1ST_LETTER = 3866;
+	private static final int GUSTAVS_2ND_LETTER = 3867;
+	private static final int GUSTAVS_3RD_LETTER = 3868;
+	private static final int SCEPTER_OF_JUDGMENT = 3869;
+	private static final int BLACK_ANVIL_COIN = 3871;
+	private static final int RECIPE_SPITEFUL_SOUL_ENERGY = 14854;
+	private static final int SPITEFUL_SOUL_VENGEANCE = 14856;
+	private static final QuestItemChanceHolder MIST_DRAKES_EGG = new QuestItemChanceHolder(3839, 10.0, 10);
+	private static final QuestItemChanceHolder BLITZ_WYRM_EGG = new QuestItemChanceHolder(3840, 10L);
+	private static final QuestItemChanceHolder DRAKES_EGG = new QuestItemChanceHolder(3841, 50.0, 10);
+	private static final QuestItemChanceHolder THUNDER_WYRM_EGG = new QuestItemChanceHolder(3842, 50.0, 10);
+	private static final QuestItemChanceHolder IMPERIAL_KEY = new QuestItemChanceHolder(3847, 6L);
+	private static final QuestItemChanceHolder SPITEFUL_SOUL_ENERGY = new QuestItemChanceHolder(14855, 10L);
+	// Reward
+	private static final int SEAL_OF_ASPIRATION = 3870;
+
 	public Q00503_PursuitOfClanAmbition() {
 		super(503, Q00503_PursuitOfClanAmbition.class.getSimpleName(), "Pursuit Of Clan Ambition");
 		addStartNpc(SIR_GUSTAV_ATHEBALDT);
 		addTalkId(SIR_GUSTAV_ATHEBALDT, HEAD_BLACKSMITH_KUSTO, MARTIEN, WITCH_ATHREA, WITCH_KALIS, CORPSE_OF_FRITZ, CORPSE_OF_LUTZ, CORPSE_OF_KURTZ, BALTHAZAR, IMPERIAL_COFFER, WITCH_CLEO, SIR_ERIC_RODEMAI);
 		addKillId(DRAKE, DRAKE2, THUNDER_WYRM, THUNDER_WYRM2, GRAVE_GUARD, SPITEFUL_SOUL_LEADER, GRAVE_KEYMASTER, BLITZ_WYRM, IMPERIAL_GRAVEKEEPER);
 		addSpawnId(WITCH_ATHREA, WITCH_KALIS, IMPERIAL_COFFER, BLITZ_WYRM);
-		registerQuestItems(MIST_DRAKES_EGG, BLITZ_WYRM_EGG, DRAKES_EGG, THUNDER_WYRM_EGG, BROOCH_OF_THE_MAGPIE, IMPERIAL_KEY, GUSTAVS_1ST_LETTER, GUSTAVS_2ND_LETTER, GUSTAVS_3RD_LETTER, SCEPTER_OF_JUDGMENT, BLACK_ANVIL_COIN, RECIPE_SPITEFUL_SOUL_ENERGY, SPITEFUL_SOUL_ENERGY, SPITEFUL_SOUL_VENGEANCE);
+		registerQuestItems(MIST_DRAKES_EGG.getId(), BLITZ_WYRM_EGG.getId(), DRAKES_EGG.getId(), THUNDER_WYRM_EGG.getId(), BROOCH_OF_THE_MAGPIE, IMPERIAL_KEY.getId(), GUSTAVS_1ST_LETTER, GUSTAVS_2ND_LETTER, GUSTAVS_3RD_LETTER, SCEPTER_OF_JUDGMENT, BLACK_ANVIL_COIN, RECIPE_SPITEFUL_SOUL_ENERGY, SPITEFUL_SOUL_ENERGY.getId(), SPITEFUL_SOUL_VENGEANCE);
 	}
 	
 	@Override
@@ -220,7 +221,7 @@ public final class Q00503_PursuitOfClanAmbition extends Quest {
 				break;
 			}
 			case "30765-04.html": {
-				takeItems(player, IMPERIAL_KEY, -1);
+				takeItems(player, IMPERIAL_KEY.getId(), -1);
 				giveItems(player, SCEPTER_OF_JUDGMENT, 1);
 				qs.setMemoState(8700);
 				htmltext = event;
@@ -294,7 +295,7 @@ public final class Q00503_PursuitOfClanAmbition extends Quest {
 		}
 		
 		final L2PcInstance leader = clan.getLeader().getPlayerInstance();
-		if ((leader == null) || !Util.checkIfInRange(1500, npc, leader, true)) {
+		if (!Util.checkIfInRange(1500, npc, leader, true)) {
 			return super.onKill(npc, killer, isSummon);
 		}
 		
@@ -302,28 +303,23 @@ public final class Q00503_PursuitOfClanAmbition extends Quest {
 		if (leaderQS == null) {
 			return super.onKill(npc, killer, isSummon);
 		}
-		
+
 		switch (npc.getId()) {
-			case DRAKE:
-			case DRAKE2: {
+			case DRAKE, DRAKE2 -> {
 				if ((leaderQS.getMemoState() >= 2000) || (leaderQS.getMemoState() < 3000)) {
-					giveItemRandomly(leader, MIST_DRAKES_EGG, 1, 10, 0.1, true);
-					
-					giveItemRandomly(leader, DRAKES_EGG, 1, 10, 0.5, true);
+					giveItemRandomly(leader, npc, MIST_DRAKES_EGG, true);
+					giveItemRandomly(leader, npc, DRAKES_EGG, true);
 				}
-				break;
 			}
-			case THUNDER_WYRM:
-			case THUNDER_WYRM2: {
+			case THUNDER_WYRM, THUNDER_WYRM2 -> {
 				if ((leaderQS.getMemoState() >= 2000) || (leaderQS.getMemoState() < 3000)) {
-					giveItemRandomly(leader, THUNDER_WYRM_EGG, 1, 10, 0.5, true);
+					giveItemRandomly(leader, npc, THUNDER_WYRM_EGG, true);
 				}
-				break;
 			}
-			case GRAVE_GUARD: {
+			case GRAVE_GUARD -> {
 				if ((leaderQS.getMemoState() < 8511) || (leaderQS.getMemoState() >= 8500)) {
 					leaderQS.setMemoState(leaderQS.getMemoState() + 1);
-					
+
 					if ((leaderQS.getMemoState() >= 8505) && (getRandom(100) < 50)) {
 						leaderQS.setMemoState(8500);
 						addSpawn(GRAVE_KEYMASTER, npc, true, 0, false);
@@ -332,36 +328,31 @@ public final class Q00503_PursuitOfClanAmbition extends Quest {
 						addSpawn(GRAVE_KEYMASTER, npc, true, 0, false);
 					}
 				}
-				break;
 			}
-			case SPITEFUL_SOUL_LEADER: {
+			case SPITEFUL_SOUL_LEADER -> {
 				if (leaderQS.getMemoState() == 5000) {
 					final int rand = getRandom(100);
 					if (rand < 10) {
-						giveItemRandomly(leader, SPITEFUL_SOUL_ENERGY, 1, 10, 1, false);
+						giveItemRandomly(leader, npc, SPITEFUL_SOUL_ENERGY, false);
 					} else if (rand < 60) {
 						giveItems(leader, SPITEFUL_SOUL_VENGEANCE, 1);
 					}
 				}
-				break;
 			}
-			case BLITZ_WYRM: {
+			case BLITZ_WYRM -> {
 				if ((leaderQS.getMemoState() >= 2000) || (leaderQS.getMemoState() < 3000)) {
-					giveItemRandomly(leader, BLITZ_WYRM_EGG, 1, 10, 1, true);
+					giveItemRandomly(leader, npc, BLITZ_WYRM_EGG, true);
 				}
-				break;
 			}
-			case GRAVE_KEYMASTER: {
+			case GRAVE_KEYMASTER -> {
 				if (leaderQS.getMemoState() >= 8500) {
-					giveItemRandomly(leader, IMPERIAL_KEY, 1, 6, 1, true);
+					giveItemRandomly(leader, npc, IMPERIAL_KEY, true);
 				}
-				break;
 			}
-			case IMPERIAL_GRAVEKEEPER: {
+			case IMPERIAL_GRAVEKEEPER -> {
 				if ((leaderQS.getMemoState() < 8511) || (leaderQS.getMemoState() >= 8500)) {
 					addSpawn(IMPERIAL_COFFER, npc, true, 0, false);
 				}
-				break;
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -456,13 +447,13 @@ public final class Q00503_PursuitOfClanAmbition extends Quest {
 								htmltext = "30645-02.html";
 							}
 						} else if ((qs.getMemoState() < 3000) && (qs.getMemoState() >= 2000)) {
-							if ((getQuestItemsCount(player, MIST_DRAKES_EGG) < 10) || (getQuestItemsCount(player, BLITZ_WYRM_EGG) < 10) || (getQuestItemsCount(player, THUNDER_WYRM_EGG) < 10) || (getQuestItemsCount(player, DRAKES_EGG) < 10)) {
+							if (!hasItemsAtLimit(player, MIST_DRAKES_EGG, BLITZ_WYRM_EGG, THUNDER_WYRM_EGG, DRAKES_EGG)) {
 								htmltext = "30645-04.html";
 							} else {
-								takeItems(player, MIST_DRAKES_EGG, -1);
-								takeItems(player, BLITZ_WYRM_EGG, -1);
-								takeItems(player, DRAKES_EGG, -1);
-								takeItems(player, THUNDER_WYRM_EGG, -1);
+								takeItems(player, MIST_DRAKES_EGG.getId(), -1);
+								takeItems(player, BLITZ_WYRM_EGG.getId(), -1);
+								takeItems(player, DRAKES_EGG.getId(), -1);
+								takeItems(player, THUNDER_WYRM_EGG.getId(), -1);
 								qs.setMemoState(3000);
 								qs.setCond(3, true);
 								htmltext = "30645-05.html";
@@ -518,10 +509,10 @@ public final class Q00503_PursuitOfClanAmbition extends Quest {
 								htmltext = "30764-04.html";
 							}
 						} else if ((qs.getMemoState() == 5000)) {
-							if (getQuestItemsCount(player, SPITEFUL_SOUL_ENERGY) < 10) {
+							if (!hasItemsAtLimit(player, SPITEFUL_SOUL_ENERGY)) {
 								htmltext = "30764-07a.html";
 							} else {
-								takeItems(player, SPITEFUL_SOUL_ENERGY, -1);
+								takeItems(player, SPITEFUL_SOUL_ENERGY.getId(), -1);
 								qs.setMemoState(6000);
 								qs.setCond(6, true);
 								htmltext = "30764-08a.html";
@@ -535,7 +526,7 @@ public final class Q00503_PursuitOfClanAmbition extends Quest {
 				case IMPERIAL_COFFER: {
 					if (lqs != null) {
 						if ((qs.getMemoState() >= 8500) && (qs.getMemoState() < 8700)) {
-							if (getQuestItemsCount(player, IMPERIAL_KEY) >= 6) {
+							if (hasItemsAtLimit(player, IMPERIAL_KEY)) {
 								if (!player.isClanLeader()) {
 									htmltext = "30765-01.html";
 								} else {
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00603_DaimonTheWhiteEyedPart1/Q00603_DaimonTheWhiteEyedPart1.java b/src/main/java/com/l2jserver/datapack/quests/Q00603_DaimonTheWhiteEyedPart1/Q00603_DaimonTheWhiteEyedPart1.java
index b2d4ee7245..d7cbf86254 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00603_DaimonTheWhiteEyedPart1/Q00603_DaimonTheWhiteEyedPart1.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00603_DaimonTheWhiteEyedPart1/Q00603_DaimonTheWhiteEyedPart1.java
@@ -18,12 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00603_DaimonTheWhiteEyedPart1;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
@@ -40,15 +39,14 @@ public final class Q00603_DaimonTheWhiteEyedPart1 extends Quest {
 	private static final int TABLET_4 = 31551;
 	private static final int TABLET_5 = 31552;
 	// Items
-	private static final int SPIRIT_OF_DARKNESS = 7190;
 	private static final int BROKEN_CRYSTAL = 7191;
-	// Monsters
-	private final Map<Integer, Double> MONSTER_CHANCES = new HashMap<>();
-	{
-		MONSTER_CHANCES.put(21297, 0.5); // Canyon Bandersnatch Slave
-		MONSTER_CHANCES.put(21299, 0.519); // Buffalo Slave
-		MONSTER_CHANCES.put(21304, 0.673); // Grendel Slave
-	}
+	private static final QuestItemChanceHolder SPIRIT_OF_DARKNESS = new QuestItemChanceHolder(7190, 200L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21297, SPIRIT_OF_DARKNESS, 50.0) // Canyon Bandersnatch Slave
+			.addSingleDrop(21299, SPIRIT_OF_DARKNESS, 51.9) // Buffalo Slave
+			.addSingleDrop(21304, SPIRIT_OF_DARKNESS, 67.3) // Grendel Slave
+			.build();
 	// Reward
 	private static final int UNFINISHED_CRYSTAL = 7192;
 	// Misc
@@ -58,8 +56,8 @@ public final class Q00603_DaimonTheWhiteEyedPart1 extends Quest {
 		super(603, Q00603_DaimonTheWhiteEyedPart1.class.getSimpleName(), "Daimon the White-Eyed - Part 1");
 		addStartNpc(EYE_OF_ARGOS);
 		addTalkId(EYE_OF_ARGOS, TABLET_1, TABLET_2, TABLET_3, TABLET_4, TABLET_5);
-		addKillId(MONSTER_CHANCES.keySet());
-		registerQuestItems(SPIRIT_OF_DARKNESS, BROKEN_CRYSTAL);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(SPIRIT_OF_DARKNESS.getId(), BROKEN_CRYSTAL);
 	}
 	
 	@Override
@@ -106,8 +104,8 @@ public final class Q00603_DaimonTheWhiteEyedPart1 extends Quest {
 			}
 			case "31683-10.html": {
 				if (qs.isCond(8)) {
-					if (getQuestItemsCount(player, SPIRIT_OF_DARKNESS) >= 200) {
-						takeItems(player, SPIRIT_OF_DARKNESS, -1);
+					if (hasItemsAtLimit(player, SPIRIT_OF_DARKNESS)) {
+						takeItems(player, SPIRIT_OF_DARKNESS.getId(), -1);
 						giveItems(player, UNFINISHED_CRYSTAL, 1);
 						qs.exitQuest(true, true);
 						htmltext = event;
@@ -175,8 +173,8 @@ public final class Q00603_DaimonTheWhiteEyedPart1 extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 7, 3, npc);
 		if (qs != null) {
-			if (giveItemRandomly(qs.getPlayer(), npc, SPIRIT_OF_DARKNESS, 1, 200, MONSTER_CHANCES.get(npc.getId()), true)) {
-				qs.setCond(8, true);
+			if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)) {
+				qs.setCond(8);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00619_RelicsOfTheOldEmpire/Q00619_RelicsOfTheOldEmpire.java b/src/main/java/com/l2jserver/datapack/quests/Q00619_RelicsOfTheOldEmpire/Q00619_RelicsOfTheOldEmpire.java
index 16b38ca9bd..8d251ffed2 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00619_RelicsOfTheOldEmpire/Q00619_RelicsOfTheOldEmpire.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00619_RelicsOfTheOldEmpire/Q00619_RelicsOfTheOldEmpire.java
@@ -18,49 +18,30 @@
  */
 package com.l2jserver.datapack.quests.Q00619_RelicsOfTheOldEmpire;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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.QuestDroplist.QuestDropInfo;
 import com.l2jserver.gameserver.model.quest.QuestState;
-import com.l2jserver.gameserver.util.Util;
 
 /**
  * Relics of the Old Empire (619)
  * @author Adry_85, jurchiks
  */
 public final class Q00619_RelicsOfTheOldEmpire extends Quest {
-	private static final class DropInfo {
-		public final double _dropChance;
-		public final int _doubleItemChance;
-		public final boolean _dropEntrancePass;
-		
-		public DropInfo(double dropChance, int doubleItemChance, boolean dropEntrancePass) {
-			_dropChance = dropChance;
-			_doubleItemChance = doubleItemChance;
-			_dropEntrancePass = dropEntrancePass;
-		}
-		
-		public double getDropChance() {
-			return _dropChance;
-		}
-		
-		public int getDoubleItemChance() {
-			return _doubleItemChance;
-		}
-		
-		public boolean getDropEntrancePass() {
-			return _dropEntrancePass;
-		}
-	}
-	
 	// NPC
 	private static final int GHOST_OF_ADVENTURER = 31538;
+	// Monsters
+	// @formatter:off
+	private static final int[] ARCHON_OF_HALISHA = {
+			18212, 18213, 18214, 18215, 18216, 18217, 18218, 18219
+	};
+	// @formatter:on
 	// Items
-	private static final int ENTRANCE_PASS_TO_THE_SEPULCHER = 7075;
-	private static final int BROKEN_RELIC_PART = 7254;
+	private static final QuestItemChanceHolder ENTRANCE_PASS_TO_THE_SEPULCHER = new QuestItemChanceHolder(7075, 3.333);
+	private static final QuestItemChanceHolder BROKEN_RELIC_PART = new QuestItemChanceHolder(7254);
 	// Misc
 	private static final int MIN_LEVEL = 74;
 	private static final int REQUIRED_RELIC_COUNT = 1000;
@@ -77,141 +58,134 @@ public final class Q00619_RelicsOfTheOldEmpire extends Quest {
 		6899, // Recipe: Arcana Mace (60%)
 		7580, // Recipe: Draconic Bow (60%)
 	};
-	// Mobs
-	private static final Map<Integer, DropInfo> MOBS = new HashMap<>();
-	static {
-		MOBS.put(21396, new DropInfo(0.51, 0, true)); // carrion_scarab
-		MOBS.put(21397, new DropInfo(0.50, 0, true)); // carrion_scarab_a
-		MOBS.put(21398, new DropInfo(0.95, 0, true)); // soldier_scarab
-		MOBS.put(21399, new DropInfo(0.84, 0, true)); // soldier_scarab_a
-		MOBS.put(21400, new DropInfo(0.76, 0, true)); // hexa_beetle
-		MOBS.put(21401, new DropInfo(0.67, 0, true)); // hexa_beetle_a
-		MOBS.put(21402, new DropInfo(0.69, 0, true)); // katraxith
-		MOBS.put(21403, new DropInfo(0.80, 0, true)); // katraxith_a
-		MOBS.put(21404, new DropInfo(0.90, 0, true)); // tera_beetle
-		MOBS.put(21405, new DropInfo(0.64, 0, true)); // tera_beetle_a
-		MOBS.put(21406, new DropInfo(0.87, 0, true)); // imperial_knight
-		MOBS.put(21407, new DropInfo(0.56, 0, true)); // imperial_knight_a
-		MOBS.put(21408, new DropInfo(0.82, 0, true)); // imperial_guard
-		MOBS.put(21409, new DropInfo(0.92, 0, true)); // imperial_guard_a
-		MOBS.put(21410, new DropInfo(0.81, 0, true)); // guardian_scarab
-		MOBS.put(21411, new DropInfo(0.66, 0, true)); // guardian_scarab_a
-		MOBS.put(21412, new DropInfo(1.00, 6, true)); // ustralith
-		MOBS.put(21413, new DropInfo(0.81, 0, true)); // ustralith_a
-		MOBS.put(21414, new DropInfo(0.79, 0, true)); // imperial_assassin
-		MOBS.put(21415, new DropInfo(0.80, 0, true)); // imperial_assassin_a
-		MOBS.put(21416, new DropInfo(0.82, 0, true)); // imperial_warlord
-		MOBS.put(21417, new DropInfo(1.00, 27, true)); // imperial_warlord_a
-		MOBS.put(21418, new DropInfo(0.66, 0, true)); // imperial_highguard
-		MOBS.put(21419, new DropInfo(0.67, 0, true)); // imperial_highguard_a
-		MOBS.put(21420, new DropInfo(0.82, 0, true)); // ashuras
-		MOBS.put(21421, new DropInfo(0.77, 0, true)); // ashuras_a
-		MOBS.put(21422, new DropInfo(0.88, 0, true)); // imperial_dancer
-		MOBS.put(21423, new DropInfo(0.94, 0, true)); // imperial_dancer_a
-		MOBS.put(21424, new DropInfo(1.00, 19, true)); // ashikenas
-		MOBS.put(21425, new DropInfo(1.00, 21, true)); // ashikenas_a
-		MOBS.put(21426, new DropInfo(1.00, 8, true)); // abraxian
-		MOBS.put(21427, new DropInfo(0.74, 0, true)); // abraxian_a
-		MOBS.put(21428, new DropInfo(0.76, 0, true)); // hasturan
-		MOBS.put(21429, new DropInfo(0.80, 0, true)); // hasturan_a
-		MOBS.put(21430, new DropInfo(1.00, 10, true)); // ahrimanes
-		MOBS.put(21431, new DropInfo(0.94, 0, true)); // ahrimanes_a
-		MOBS.put(21432, new DropInfo(1.00, 34, true)); // chakram_beetle
-		MOBS.put(21433, new DropInfo(1.00, 34, true)); // jamadhr_beetle
-		MOBS.put(21434, new DropInfo(1.00, 90, true)); // priest_of_blood
-		MOBS.put(21435, new DropInfo(1.00, 60, true)); // sacrifice_guide
-		MOBS.put(21436, new DropInfo(1.00, 66, true)); // sacrifice_bearer
-		MOBS.put(21437, new DropInfo(0.69, 0, true)); // sacrifice_scarab
-		MOBS.put(21798, new DropInfo(0.33, 0, true)); // guard_skeleton_2d
-		MOBS.put(21799, new DropInfo(0.61, 0, true)); // guard_skeleton_3d
-		MOBS.put(21800, new DropInfo(0.31, 0, true)); // guard_undead
-		MOBS.put(18120, new DropInfo(1.00, 28, false)); // r11_roomboss_strong
-		MOBS.put(18121, new DropInfo(1.00, 21, false)); // r11_roomboss_weak
-		MOBS.put(18122, new DropInfo(0.93, 0, false)); // r11_roomboss_teleport
-		MOBS.put(18123, new DropInfo(1.00, 28, false)); // r12_roomboss_strong
-		MOBS.put(18124, new DropInfo(1.00, 21, false)); // r12_roomboss_weak
-		MOBS.put(18125, new DropInfo(0.93, 0, false)); // r12_roomboss_teleport
-		MOBS.put(18126, new DropInfo(1.00, 28, false)); // r13_roomboss_strong
-		MOBS.put(18127, new DropInfo(1.00, 21, false)); // r13_roomboss_weak
-		MOBS.put(18128, new DropInfo(0.93, 0, false)); // r13_roomboss_teleport
-		MOBS.put(18129, new DropInfo(1.00, 28, false)); // r14_roomboss_strong
-		MOBS.put(18130, new DropInfo(1.00, 21, false)); // r14_roomboss_weak
-		MOBS.put(18131, new DropInfo(0.93, 0, false)); // r14_roomboss_teleport
-		MOBS.put(18132, new DropInfo(1.00, 30, false)); // r1_beatle_healer
-		MOBS.put(18133, new DropInfo(1.00, 20, false)); // r1_scorpion_warrior
-		MOBS.put(18134, new DropInfo(0.90, 0, false)); // r1_warrior_longatk1_h
-		MOBS.put(18135, new DropInfo(1.00, 20, false)); // r1_warrior_longatk2
-		MOBS.put(18136, new DropInfo(1.00, 20, false)); // r1_warrior_selfbuff
-		MOBS.put(18137, new DropInfo(0.89, 0, false)); // r1_wizard_h
-		MOBS.put(18138, new DropInfo(1.00, 19, false)); // r1_wizard_clanbuff
-		MOBS.put(18139, new DropInfo(1.00, 17, false)); // r1_wizard_debuff
-		MOBS.put(18140, new DropInfo(1.00, 19, false)); // r1_wizard_selfbuff
-		MOBS.put(18141, new DropInfo(0.76, 0, false)); // r21_scarab_roombosss
-		MOBS.put(18142, new DropInfo(0.76, 0, false)); // r22_scarab_roombosss
-		MOBS.put(18143, new DropInfo(0.76, 0, false)); // r23_scarab_roombosss
-		MOBS.put(18144, new DropInfo(0.76, 0, false)); // r24_scarab_roombosss
-		MOBS.put(18145, new DropInfo(0.65, 0, false)); // r2_wizard_clanbuff
-		MOBS.put(18146, new DropInfo(0.66, 0, false)); // r2_warrior_longatk2
-		MOBS.put(18147, new DropInfo(0.62, 0, false)); // r2_wizard
-		MOBS.put(18148, new DropInfo(0.72, 0, false)); // r2_warrior
-		MOBS.put(18149, new DropInfo(0.63, 0, false)); // r2_bomb
-		MOBS.put(18166, new DropInfo(0.92, 0, false)); // r3_warrior
-		MOBS.put(18167, new DropInfo(0.92, 0, false)); // r3_warrior_longatk1_h
-		MOBS.put(18168, new DropInfo(0.93, 0, false)); // r3_warrior_longatk2
-		MOBS.put(18169, new DropInfo(0.90, 0, false)); // r3_warrior_selfbuff
-		MOBS.put(18170, new DropInfo(0.90, 0, false)); // r3_wizard_h
-		MOBS.put(18171, new DropInfo(0.94, 0, false)); // r3_wizard_clanbuff
-		MOBS.put(18172, new DropInfo(0.89, 0, false)); // r3_wizard_selfbuff
-		MOBS.put(18173, new DropInfo(0.99, 0, false)); // r41_roomboss_strong
-		MOBS.put(18174, new DropInfo(1.00, 22, false)); // r41_roomboss_weak
-		MOBS.put(18175, new DropInfo(0.93, 0, false)); // r41_roomboss_teleport
-		MOBS.put(18176, new DropInfo(0.99, 0, false)); // r42_roomboss_strong
-		MOBS.put(18177, new DropInfo(1.00, 22, false)); // r42_roomboss_weak
-		MOBS.put(18178, new DropInfo(0.93, 0, false)); // r42_roomboss_teleport
-		MOBS.put(18179, new DropInfo(0.99, 0, false)); // r43_roomboss_strong
-		MOBS.put(18180, new DropInfo(1.00, 22, false)); // r43_roomboss_weak
-		MOBS.put(18181, new DropInfo(0.93, 0, false)); // r43_roomboss_teleport
-		MOBS.put(18183, new DropInfo(1.00, 22, false)); // r44_roomboss_weak
-		MOBS.put(18183, new DropInfo(0.99, 0, false)); // r44_roomboss_strong
-		MOBS.put(18184, new DropInfo(0.93, 0, false)); // r44_roomboss_teleport
-		MOBS.put(18185, new DropInfo(1.00, 23, false)); // r4_healer_srddmagic
-		MOBS.put(18186, new DropInfo(1.00, 24, false)); // r4_hearler_srdebuff
-		MOBS.put(18187, new DropInfo(1.00, 20, false)); // r4_warrior
-		MOBS.put(18188, new DropInfo(0.90, 0, false)); // r4_warrior_longatk1_h
-		MOBS.put(18189, new DropInfo(1.00, 20, false)); // r4_warrior_longatk2
-		MOBS.put(18190, new DropInfo(1.00, 20, false)); // r4_warrior_selfbuff
-		MOBS.put(18191, new DropInfo(0.89, 0, false)); // r4_wizard_h
-		MOBS.put(18192, new DropInfo(1.00, 19, false)); // r4_wizard_clanbuff
-		MOBS.put(18193, new DropInfo(1.00, 17, false)); // r4_wizard_debuff
-		MOBS.put(18194, new DropInfo(1.00, 19, false)); // r4_wizard_selfbuff
-		MOBS.put(18195, new DropInfo(0.91, 0, false)); // r4_bomb
-		MOBS.put(18220, new DropInfo(1.00, 24, false)); // r5_healer1
-		MOBS.put(18221, new DropInfo(1.00, 27, false)); // r5_healer2
-		MOBS.put(18222, new DropInfo(1.00, 21, false)); // r5_warrior
-		MOBS.put(18223, new DropInfo(0.90, 0, false)); // r5_warrior_longatk1_h
-		MOBS.put(18224, new DropInfo(1.00, 22, false)); // r5_warrior_longatk2
-		MOBS.put(18225, new DropInfo(1.00, 21, false)); // r5_warrior_sbuff
-		MOBS.put(18226, new DropInfo(0.89, 0, false)); // r5_wizard_h
-		MOBS.put(18227, new DropInfo(1.00, 53, false)); // r5_wizard_clanbuff
-		MOBS.put(18228, new DropInfo(1.00, 15, false)); // r5_wizard_debuff
-		MOBS.put(18229, new DropInfo(1.00, 19, false)); // r5_wizard_slefbuff
-		MOBS.put(18230, new DropInfo(0.49, 0, false)); // r5_bomb
-	}
-	
-	// @formatter:off
-	private static final int[] ARCHON_OF_HALISHA =
-	{
-		18212, 18213, 18214, 18215, 18216, 18217, 18218, 18219
-	};
-	// @formatter:on
+
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21396, BROKEN_RELIC_PART, 51.0).addSingleDrop(21396, ENTRANCE_PASS_TO_THE_SEPULCHER) // carrion_scarab
+			.addSingleDrop(21397, BROKEN_RELIC_PART, 50.0).addSingleDrop(21396, ENTRANCE_PASS_TO_THE_SEPULCHER) // carrion_scarab_a
+			.addSingleDrop(21398, BROKEN_RELIC_PART, 95.0).addSingleDrop(21398, ENTRANCE_PASS_TO_THE_SEPULCHER) // soldier_scarab
+			.addSingleDrop(21399, BROKEN_RELIC_PART, 84.0).addSingleDrop(21399, ENTRANCE_PASS_TO_THE_SEPULCHER) // soldier_scarab_a
+			.addSingleDrop(21400, BROKEN_RELIC_PART, 76.0).addSingleDrop(21400, ENTRANCE_PASS_TO_THE_SEPULCHER) // hexa_beetle
+			.addSingleDrop(21401, BROKEN_RELIC_PART, 67.0).addSingleDrop(21401, ENTRANCE_PASS_TO_THE_SEPULCHER) // hexa_beetle_a
+			.addSingleDrop(21402, BROKEN_RELIC_PART, 69.0).addSingleDrop(21402, ENTRANCE_PASS_TO_THE_SEPULCHER) // katraxith
+			.addSingleDrop(21403, BROKEN_RELIC_PART, 80.0).addSingleDrop(21403, ENTRANCE_PASS_TO_THE_SEPULCHER) // katraxith_a
+			.addSingleDrop(21404, BROKEN_RELIC_PART, 90.0).addSingleDrop(21404, ENTRANCE_PASS_TO_THE_SEPULCHER) // tera_beetle
+			.addSingleDrop(21405, BROKEN_RELIC_PART, 64.0).addSingleDrop(21405, ENTRANCE_PASS_TO_THE_SEPULCHER) // tera_beetle_a
+			.addSingleDrop(21406, BROKEN_RELIC_PART, 87.0).addSingleDrop(21406, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_knight
+			.addSingleDrop(21407, BROKEN_RELIC_PART, 56.0).addSingleDrop(21407, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_knight_a
+			.addSingleDrop(21408, BROKEN_RELIC_PART, 82.0).addSingleDrop(21408, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_guard
+			.addSingleDrop(21409, BROKEN_RELIC_PART, 92.0).addSingleDrop(21409, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_guard_a
+			.addSingleDrop(21410, BROKEN_RELIC_PART, 81.0).addSingleDrop(21410, ENTRANCE_PASS_TO_THE_SEPULCHER) // guardian_scarab
+			.addSingleDrop(21411, BROKEN_RELIC_PART, 66.0).addSingleDrop(21411, ENTRANCE_PASS_TO_THE_SEPULCHER) // guardian_scarab_a
+			.addSingleDrop(21412, BROKEN_RELIC_PART, 106.0).addSingleDrop(21412, ENTRANCE_PASS_TO_THE_SEPULCHER) // ustralith
+			.addSingleDrop(21413, BROKEN_RELIC_PART, 81.0).addSingleDrop(21413, ENTRANCE_PASS_TO_THE_SEPULCHER) // ustralith_a
+			.addSingleDrop(21414, BROKEN_RELIC_PART, 79.0).addSingleDrop(21414, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_assassin
+			.addSingleDrop(21415, BROKEN_RELIC_PART, 80.0).addSingleDrop(21415, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_assassin_a
+			.addSingleDrop(21416, BROKEN_RELIC_PART, 82.0).addSingleDrop(21416, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_warlord
+			.addSingleDrop(21417, BROKEN_RELIC_PART, 127.0).addSingleDrop(21417, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_warlord_a
+			.addSingleDrop(21418, BROKEN_RELIC_PART, 66.0).addSingleDrop(21418, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_highguard
+			.addSingleDrop(21419, BROKEN_RELIC_PART, 67.0).addSingleDrop(21419, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_highguard_a
+			.addSingleDrop(21420, BROKEN_RELIC_PART, 82.0).addSingleDrop(21420, ENTRANCE_PASS_TO_THE_SEPULCHER) // ashuras
+			.addSingleDrop(21421, BROKEN_RELIC_PART, 77.0).addSingleDrop(21421, ENTRANCE_PASS_TO_THE_SEPULCHER) // ashuras_a
+			.addSingleDrop(21422, BROKEN_RELIC_PART, 88.0).addSingleDrop(21422, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_dancer
+			.addSingleDrop(21423, BROKEN_RELIC_PART, 94.0).addSingleDrop(21423, ENTRANCE_PASS_TO_THE_SEPULCHER) // imperial_dancer_a
+			.addSingleDrop(21424, BROKEN_RELIC_PART, 119.0).addSingleDrop(21424, ENTRANCE_PASS_TO_THE_SEPULCHER) // ashikenas
+			.addSingleDrop(21425, BROKEN_RELIC_PART, 121.0).addSingleDrop(21425, ENTRANCE_PASS_TO_THE_SEPULCHER) // ashikenas_a
+			.addSingleDrop(21426, BROKEN_RELIC_PART, 108.0).addSingleDrop(21426, ENTRANCE_PASS_TO_THE_SEPULCHER) // abraxian
+			.addSingleDrop(21427, BROKEN_RELIC_PART, 74.0).addSingleDrop(21427, ENTRANCE_PASS_TO_THE_SEPULCHER) // abraxian_a
+			.addSingleDrop(21428, BROKEN_RELIC_PART, 76.0).addSingleDrop(21428, ENTRANCE_PASS_TO_THE_SEPULCHER) // hasturan
+			.addSingleDrop(21429, BROKEN_RELIC_PART, 80.0).addSingleDrop(21429, ENTRANCE_PASS_TO_THE_SEPULCHER) // hasturan_a
+			.addSingleDrop(21430, BROKEN_RELIC_PART, 110.0).addSingleDrop(21430, ENTRANCE_PASS_TO_THE_SEPULCHER) // ahrimanes
+			.addSingleDrop(21431, BROKEN_RELIC_PART, 94.0).addSingleDrop(21431, ENTRANCE_PASS_TO_THE_SEPULCHER) // ahrimanes_a
+			.addSingleDrop(21432, BROKEN_RELIC_PART, 134.0).addSingleDrop(21432, ENTRANCE_PASS_TO_THE_SEPULCHER) // chakram_beetle
+			.addSingleDrop(21433, BROKEN_RELIC_PART, 134.0).addSingleDrop(21433, ENTRANCE_PASS_TO_THE_SEPULCHER) // jamadhr_beetle
+			.addSingleDrop(21434, BROKEN_RELIC_PART, 190.0).addSingleDrop(21434, ENTRANCE_PASS_TO_THE_SEPULCHER) // priest_of_blood
+			.addSingleDrop(21435, BROKEN_RELIC_PART, 160.0).addSingleDrop(21435, ENTRANCE_PASS_TO_THE_SEPULCHER) // sacrifice_guide
+			.addSingleDrop(21436, BROKEN_RELIC_PART, 166.0).addSingleDrop(21436, ENTRANCE_PASS_TO_THE_SEPULCHER) // sacrifice_bearer
+			.addSingleDrop(21437, BROKEN_RELIC_PART, 69.0).addSingleDrop(21437, ENTRANCE_PASS_TO_THE_SEPULCHER) // sacrifice_scarab
+			.addSingleDrop(21798, BROKEN_RELIC_PART, 33.0).addSingleDrop(21798, ENTRANCE_PASS_TO_THE_SEPULCHER) // guard_skeleton_2d
+			.addSingleDrop(21799, BROKEN_RELIC_PART, 61.0).addSingleDrop(21799, ENTRANCE_PASS_TO_THE_SEPULCHER) // guard_skeleton_3d
+			.addSingleDrop(21800, BROKEN_RELIC_PART, 31.0).addSingleDrop(21800, ENTRANCE_PASS_TO_THE_SEPULCHER) // guard_undead
+			.addSingleDrop(18120, BROKEN_RELIC_PART, 128.0) // r11_roomboss_strong
+			.addSingleDrop(18121, BROKEN_RELIC_PART, 121.0) // r11_roomboss_weak
+			.addSingleDrop(18122, BROKEN_RELIC_PART, 93.0) // r11_roomboss_teleport
+			.addSingleDrop(18123, BROKEN_RELIC_PART, 128.0) // r12_roomboss_strong
+			.addSingleDrop(18124, BROKEN_RELIC_PART, 121.0) // r12_roomboss_weak
+			.addSingleDrop(18125, BROKEN_RELIC_PART, 93.0) // r12_roomboss_teleport
+			.addSingleDrop(18126, BROKEN_RELIC_PART, 128.0) // r13_roomboss_strong
+			.addSingleDrop(18127, BROKEN_RELIC_PART, 121.0) // r13_roomboss_weak
+			.addSingleDrop(18128, BROKEN_RELIC_PART, 93.0) // r13_roomboss_teleport
+			.addSingleDrop(18129, BROKEN_RELIC_PART, 128.0) // r14_roomboss_strong
+			.addSingleDrop(18130, BROKEN_RELIC_PART, 121.0) // r14_roomboss_weak
+			.addSingleDrop(18131, BROKEN_RELIC_PART, 93.0) // r14_roomboss_teleport
+			.addSingleDrop(18132, BROKEN_RELIC_PART, 130.0) // r1_beatle_healer
+			.addSingleDrop(18133, BROKEN_RELIC_PART, 120.0) // r1_scorpion_warrior
+			.addSingleDrop(18134, BROKEN_RELIC_PART, 90.0) // r1_warrior_longatk1_h
+			.addSingleDrop(18135, BROKEN_RELIC_PART, 120.0) // r1_warrior_longatk2
+			.addSingleDrop(18136, BROKEN_RELIC_PART, 120.0) // r1_warrior_selfbuff
+			.addSingleDrop(18137, BROKEN_RELIC_PART, 89.0) // r1_wizard_h
+			.addSingleDrop(18138, BROKEN_RELIC_PART, 119.0) // r1_wizard_clanbuff
+			.addSingleDrop(18139, BROKEN_RELIC_PART, 117.0) // r1_wizard_debuff
+			.addSingleDrop(18140, BROKEN_RELIC_PART, 119.0) // r1_wizard_selfbuff
+			.addSingleDrop(18141, BROKEN_RELIC_PART, 76.0) // r21_scarab_roombosss
+			.addSingleDrop(18142, BROKEN_RELIC_PART, 76.0) // r22_scarab_roombosss
+			.addSingleDrop(18143, BROKEN_RELIC_PART, 76.0) // r23_scarab_roombosss
+			.addSingleDrop(18144, BROKEN_RELIC_PART, 76.0) // r24_scarab_roombosss
+			.addSingleDrop(18145, BROKEN_RELIC_PART, 65.0) // r2_wizard_clanbuff
+			.addSingleDrop(18146, BROKEN_RELIC_PART, 66.0) // r2_warrior_longatk2
+			.addSingleDrop(18147, BROKEN_RELIC_PART, 62.0) // r2_wizard
+			.addSingleDrop(18148, BROKEN_RELIC_PART, 72.0) // r2_warrior
+			.addSingleDrop(18149, BROKEN_RELIC_PART, 63.0) // r2_bomb
+			.addSingleDrop(18166, BROKEN_RELIC_PART, 92.0) // r3_warrior
+			.addSingleDrop(18167, BROKEN_RELIC_PART, 92.0) // r3_warrior_longatk1_h
+			.addSingleDrop(18168, BROKEN_RELIC_PART, 93.0) // r3_warrior_longatk2
+			.addSingleDrop(18169, BROKEN_RELIC_PART, 90.0) // r3_warrior_selfbuff
+			.addSingleDrop(18170, BROKEN_RELIC_PART, 90.0) // r3_wizard_h
+			.addSingleDrop(18171, BROKEN_RELIC_PART, 94.0) // r3_wizard_clanbuff
+			.addSingleDrop(18172, BROKEN_RELIC_PART, 89.0) // r3_wizard_selfbuff
+			.addSingleDrop(18173, BROKEN_RELIC_PART, 99.0) // r41_roomboss_strong
+			.addSingleDrop(18174, BROKEN_RELIC_PART, 122.0) // r41_roomboss_weak
+			.addSingleDrop(18175, BROKEN_RELIC_PART, 93.0) // r41_roomboss_teleport
+			.addSingleDrop(18176, BROKEN_RELIC_PART, 99.0) // r42_roomboss_strong
+			.addSingleDrop(18177, BROKEN_RELIC_PART, 122.0) // r42_roomboss_weak
+			.addSingleDrop(18178, BROKEN_RELIC_PART, 93.0) // r42_roomboss_teleport
+			.addSingleDrop(18179, BROKEN_RELIC_PART, 99.0) // r43_roomboss_strong
+			.addSingleDrop(18180, BROKEN_RELIC_PART, 122.0) // r43_roomboss_weak
+			.addSingleDrop(18181, BROKEN_RELIC_PART, 93.0) // r43_roomboss_teleport
+			.addSingleDrop(18182, BROKEN_RELIC_PART, 122.0) // r44_roomboss_weak
+			.addSingleDrop(18183, BROKEN_RELIC_PART, 99.0) // r44_roomboss_strong
+			.addSingleDrop(18184, BROKEN_RELIC_PART, 93.0) // r44_roomboss_teleport
+			.addSingleDrop(18185, BROKEN_RELIC_PART, 123.0) // r4_healer_srddmagic
+			.addSingleDrop(18186, BROKEN_RELIC_PART, 124.0) // r4_hearler_srdebuff
+			.addSingleDrop(18187, BROKEN_RELIC_PART, 120.0) // r4_warrior
+			.addSingleDrop(18188, BROKEN_RELIC_PART, 90.0) // r4_warrior_longatk1_h
+			.addSingleDrop(18189, BROKEN_RELIC_PART, 120.0) // r4_warrior_longatk2
+			.addSingleDrop(18190, BROKEN_RELIC_PART, 120.0) // r4_warrior_selfbuff
+			.addSingleDrop(18191, BROKEN_RELIC_PART, 89.0) // r4_wizard_h
+			.addSingleDrop(18192, BROKEN_RELIC_PART, 119.0) // r4_wizard_clanbuff
+			.addSingleDrop(18193, BROKEN_RELIC_PART, 117.0) // r4_wizard_debuff
+			.addSingleDrop(18194, BROKEN_RELIC_PART, 119.0) // r4_wizard_selfbuff
+			.addSingleDrop(18195, BROKEN_RELIC_PART, 91.0) // r4_bomb
+			.addSingleDrop(18220, BROKEN_RELIC_PART, 124.0) // r5_healer1
+			.addSingleDrop(18221, BROKEN_RELIC_PART, 127.0) // r5_healer2
+			.addSingleDrop(18222, BROKEN_RELIC_PART, 121.0) // r5_warrior
+			.addSingleDrop(18223, BROKEN_RELIC_PART, 90.0) // r5_warrior_longatk1_h
+			.addSingleDrop(18224, BROKEN_RELIC_PART, 122.0) // r5_warrior_longatk2
+			.addSingleDrop(18225, BROKEN_RELIC_PART, 121.0) // r5_warrior_sbuff
+			.addSingleDrop(18226, BROKEN_RELIC_PART, 89.0) // r5_wizard_h
+			.addSingleDrop(18227, BROKEN_RELIC_PART, 153.0) // r5_wizard_clanbuff
+			.addSingleDrop(18228, BROKEN_RELIC_PART, 115.0) // r5_wizard_debuff
+			.addSingleDrop(18229, BROKEN_RELIC_PART, 119.0) // r5_wizard_slefbuff
+			.addSingleDrop(18230, BROKEN_RELIC_PART, 49.0) // r5_bomb
+			.bulkAddSingleDrop(BROKEN_RELIC_PART, 379.0).withNpcs(ARCHON_OF_HALISHA).build()
+			.build();
 	
 	public Q00619_RelicsOfTheOldEmpire() {
 		super(619, Q00619_RelicsOfTheOldEmpire.class.getSimpleName(), "Relics of the Old Empire");
 		addStartNpc(GHOST_OF_ADVENTURER);
 		addTalkId(GHOST_OF_ADVENTURER);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		addKillId(ARCHON_OF_HALISHA);
-		registerQuestItems(BROKEN_RELIC_PART);
+		registerQuestItems(BROKEN_RELIC_PART.getId());
 	}
 	
 	@Override
@@ -233,9 +207,9 @@ public final class Q00619_RelicsOfTheOldEmpire extends Quest {
 				break;
 			}
 			case "31538-06.html": {
-				if (st.getQuestItemsCount(BROKEN_RELIC_PART) >= REQUIRED_RELIC_COUNT) {
+				if (st.getQuestItemsCount(BROKEN_RELIC_PART.getId()) >= REQUIRED_RELIC_COUNT) {
 					st.rewardItems(RECIPES[getRandom(RECIPES.length)], 1);
-					st.takeItems(BROKEN_RELIC_PART, REQUIRED_RELIC_COUNT);
+					st.takeItems(BROKEN_RELIC_PART.getId(), REQUIRED_RELIC_COUNT);
 					htmltext = event;
 				}
 				break;
@@ -253,25 +227,11 @@ public final class Q00619_RelicsOfTheOldEmpire extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState st = getRandomPartyMemberState(player, -1, 3, npc);
 		if (st != null) {
-			int npcId = npc.getId();
-			if (Util.contains(ARCHON_OF_HALISHA, npcId)) {
-				final int itemCount = ((getRandom(100) < 79) ? 4 : 3);
-				st.giveItemRandomly(npc, BROKEN_RELIC_PART, itemCount, 0, 1.0, true);
-			} else {
-				final DropInfo info = MOBS.get(npcId);
-				final int itemCount;
-				
-				if (info.getDoubleItemChance() > 0) {
-					itemCount = ((getRandom(100) < info.getDoubleItemChance()) ? 2 : 1);
-				} else {
-					itemCount = 1;
-				}
-				
-				st.giveItemRandomly(npc, BROKEN_RELIC_PART, itemCount, 0, info.getDropChance(), true);
-				
-				if (info.getDropEntrancePass()) {
-					st.giveItemRandomly(npc, ENTRANCE_PASS_TO_THE_SEPULCHER, 1, 0, 1.0 / 30, false);
-				}
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
+
+			QuestDropInfo passDropInfo = DROPLIST.get(npc, ENTRANCE_PASS_TO_THE_SEPULCHER);
+			if (passDropInfo != null) {
+				giveItemRandomly(st.getPlayer(), npc, ENTRANCE_PASS_TO_THE_SEPULCHER, false);
 			}
 		}
 		return super.onKill(npc, player, isSummon);
@@ -284,7 +244,7 @@ public final class Q00619_RelicsOfTheOldEmpire extends Quest {
 		if (st.isCreated()) {
 			htmltext = ((player.getLevel() >= MIN_LEVEL) ? "31538-01.htm" : "31538-03.html");
 		} else if (st.isStarted()) {
-			htmltext = ((getQuestItemsCount(player, BROKEN_RELIC_PART) >= REQUIRED_RELIC_COUNT) ? "31538-04.html" : "31538-07.html");
+			htmltext = ((getQuestItemsCount(player, BROKEN_RELIC_PART.getId()) >= REQUIRED_RELIC_COUNT) ? "31538-04.html" : "31538-07.html");
 		}
 		return htmltext;
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00620_FourGoblets/Q00620_FourGoblets.java b/src/main/java/com/l2jserver/datapack/quests/Q00620_FourGoblets/Q00620_FourGoblets.java
index c3ce2ab6f2..25d3f1ca65 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00620_FourGoblets/Q00620_FourGoblets.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00620_FourGoblets/Q00620_FourGoblets.java
@@ -18,18 +18,19 @@
  */
 package com.l2jserver.datapack.quests.Q00620_FourGoblets;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.instancemanager.FourSepulchersManager;
 import com.l2jserver.gameserver.model.Location;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
 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.util.Util;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Four Goblets (620)
  * @author Adry_85
@@ -55,6 +56,38 @@ public class Q00620_FourGoblets extends Quest {
 	private static final int CHAPEL_KEY = 7260;
 	private static final int USED_GRAVE_PASS = 7261;
 	private static final int ANTIQUE_BROOCH = 7262;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.bulkAddSingleDrop(SEALED_BOX, 90.0).withNpcs(18141, 18142, 18143, 18144).build()
+			.addSingleDrop(18145, SEALED_BOX, 76.0)
+			.addSingleDrop(18146, SEALED_BOX, 78.0)
+			.addSingleDrop(18147, SEALED_BOX, 73.0)
+			.addSingleDrop(18148, SEALED_BOX, 85.0)
+			.addSingleDrop(18149, SEALED_BOX, 75.0)
+			.addSingleDrop(18230, SEALED_BOX, 58.0)
+			.bulkAddSingleDrop(SEALED_BOX, 151.0).withNpcs(18120, 18123, 18126, 18129, 18221).build()
+			.bulkAddSingleDrop(SEALED_BOX, 144.0).withNpcs(18121, 18124, 18127, 18130, 18224).build()
+			.bulkAddSingleDrop(SEALED_BOX, 110.0).withNpcs(18122, 18125, 18128, 18131, 18168, 18175, 18178, 18181, 18184).build()
+			.bulkAddSingleDrop(SEALED_BOX, 142.0).withNpcs(18133, 18135, 18136, 18187, 18189, 18190).build()
+			.addSingleDrop(18132, SEALED_BOX, 154.0)
+			.bulkAddSingleDrop(SEALED_BOX, 107.0).withNpcs(18134, 18167, 18170, 18188, 18223).build()
+			.bulkAddSingleDrop(SEALED_BOX, 106.0).withNpcs(18137, 18169, 18172, 18191, 18226).build()
+			.bulkAddSingleDrop(SEALED_BOX, 141.0).withNpcs(18138, 18140, 18192, 18194, 18229).build()
+			.addSingleDrop(18139, SEALED_BOX, 139.0)
+			.addSingleDrop(18166, SEALED_BOX, 108.0)
+			.addSingleDrop(18171, SEALED_BOX, 111.0)
+			.bulkAddSingleDrop(SEALED_BOX, 117.0).withNpcs(18173, 18176, 18179, 18182).build()
+			.bulkAddSingleDrop(SEALED_BOX, 145.0).withNpcs(18174, 18177, 18180, 18183).build()
+			.addSingleDrop(18185, SEALED_BOX, 146.0)
+			.addSingleDrop(18186, SEALED_BOX, 147.0)
+			.addSingleDrop(18193, SEALED_BOX, 139.0)
+			.addSingleDrop(18195, SEALED_BOX, 108.0)
+			.addSingleDrop(18220, SEALED_BOX, 147.0)
+			.addSingleDrop(18222, SEALED_BOX, 143.0)
+			.addSingleDrop(18225, SEALED_BOX, 143.0)
+			.addSingleDrop(18227, SEALED_BOX, 182.0)
+			.bulkAddSingleDrop(SEALED_BOX, 450.0).withNpcs(18212, 18213, 18214, 18215, 18216, 18217, 18218, 18219).build()
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 74;
 	// Locations
@@ -136,86 +169,6 @@ public class Q00620_FourGoblets extends Quest {
 	private static final Map<Integer, Double> MOB1 = new HashMap<>();
 	private static final Map<Integer, Integer> MOB2 = new HashMap<>();
 	private static final Map<Integer, Integer> MOB3 = new HashMap<>();
-	static {
-		MOB1.put(18141, 0.9);
-		MOB1.put(18142, 0.9);
-		MOB1.put(18143, 0.9);
-		MOB1.put(18144, 0.9);
-		MOB1.put(18145, 0.76);
-		MOB1.put(18146, 0.78);
-		MOB1.put(18147, 0.73);
-		MOB1.put(18148, 0.85);
-		MOB1.put(18149, 0.75);
-		MOB1.put(18230, 0.58);
-		MOB2.put(18120, 51);
-		MOB2.put(18121, 44);
-		MOB2.put(18122, 10);
-		MOB2.put(18123, 51);
-		MOB2.put(18124, 44);
-		MOB2.put(18125, 10);
-		MOB2.put(18126, 51);
-		MOB2.put(18127, 44);
-		MOB2.put(18128, 10);
-		MOB2.put(18129, 51);
-		MOB2.put(18130, 44);
-		MOB2.put(18131, 10);
-		MOB2.put(18132, 54);
-		MOB2.put(18133, 42);
-		MOB2.put(18134, 7);
-		MOB2.put(18135, 42);
-		MOB2.put(18136, 42);
-		MOB2.put(18137, 6);
-		MOB2.put(18138, 41);
-		MOB2.put(18139, 39);
-		MOB2.put(18140, 41);
-		MOB2.put(18166, 8);
-		MOB2.put(18167, 7);
-		MOB2.put(18168, 10);
-		MOB2.put(18169, 6);
-		MOB2.put(18170, 7);
-		MOB2.put(18171, 11);
-		MOB2.put(18172, 6);
-		MOB2.put(18173, 17);
-		MOB2.put(18174, 45);
-		MOB2.put(18175, 10);
-		MOB2.put(18176, 17);
-		MOB2.put(18177, 45);
-		MOB2.put(18178, 10);
-		MOB2.put(18179, 17);
-		MOB2.put(18180, 45);
-		MOB2.put(18181, 10);
-		MOB2.put(18182, 17);
-		MOB2.put(18183, 45);
-		MOB2.put(18184, 10);
-		MOB2.put(18185, 46);
-		MOB2.put(18186, 47);
-		MOB2.put(18187, 42);
-		MOB2.put(18188, 7);
-		MOB2.put(18189, 42);
-		MOB2.put(18190, 42);
-		MOB2.put(18191, 6);
-		MOB2.put(18192, 41);
-		MOB2.put(18193, 39);
-		MOB2.put(18194, 41);
-		MOB2.put(18195, 8);
-		MOB2.put(18220, 47);
-		MOB2.put(18221, 51);
-		MOB2.put(18222, 43);
-		MOB2.put(18223, 7);
-		MOB2.put(18224, 44);
-		MOB2.put(18225, 43);
-		MOB2.put(18226, 6);
-		MOB2.put(18227, 82);
-		MOB2.put(18229, 41);
-		MOB3.put(18212, 50);
-		MOB3.put(18213, 50);
-		MOB3.put(18214, 50);
-		MOB3.put(18215, 50);
-		MOB3.put(18216, 50);
-		MOB3.put(18217, 50);
-		MOB3.put(18218, 50);
-		MOB3.put(18219, 50);
-	}
 	
 	public Q00620_FourGoblets() {
 		super(620, Q00620_FourGoblets.class.getSimpleName(), "Four Goblets");
@@ -404,28 +357,13 @@ public class Q00620_FourGoblets extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		switch (npc.getId()) {
-			case HALISHA_ALECTIA:
-			case HALISHA_TISHAS:
-			case HALISHA_MEKARA:
-			case HALISHA_MORIGUL: {
-				executeForEachPlayer(player, npc, isSummon, true, false);
-				break;
-			}
-			default: {
+			case HALISHA_ALECTIA, HALISHA_TISHAS, HALISHA_MEKARA, HALISHA_MORIGUL ->
+					executeForEachPlayer(player, npc, isSummon, true, false);
+			default -> {
 				final QuestState st = getRandomPartyMemberState(player, -1, 3, npc);
 				if (st != null) {
-					int npcId = npc.getId();
-					if (MOB1.containsKey(npcId)) {
-						st.giveItemRandomly(npc, SEALED_BOX, 1, 0, MOB1.get(npcId), true);
-					} else if (MOB2.containsKey(npcId)) {
-						final int itemCount = ((getRandom(100) < MOB2.get(npc.getId())) ? 2 : 1);
-						st.giveItemRandomly(npc, SEALED_BOX, itemCount, 0, 1.0, true);
-					} else {
-						final int itemCount = ((getRandom(100) < MOB3.get(npc.getId())) ? 5 : 4);
-						st.giveItemRandomly(npc, SEALED_BOX, itemCount, 0, 1.0, true);
-					}
+					giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 				}
-				break;
 			}
 		}
 		return super.onKill(npc, player, isSummon);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00623_TheFinestFood/Q00623_TheFinestFood.java b/src/main/java/com/l2jserver/datapack/quests/Q00623_TheFinestFood/Q00623_TheFinestFood.java
index ed2442ddee..3468d1250d 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00623_TheFinestFood/Q00623_TheFinestFood.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00623_TheFinestFood/Q00623_TheFinestFood.java
@@ -18,13 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00623_TheFinestFood;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
+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;
 
 /**
@@ -39,23 +38,22 @@ public final class Q00623_TheFinestFood extends Quest {
 	private static final int THERMAL_FLAVA = 21316;
 	private static final int THERMAL_ANTELOPE = 21318;
 	// Items
-	private static final ItemHolder LEAF_OF_FLAVA = new ItemHolder(7199, 100);
-	private static final ItemHolder BUFFALO_MEAT = new ItemHolder(7200, 100);
-	private static final ItemHolder HORN_OF_ANTELOPE = new ItemHolder(7201, 100);
+	private static final QuestItemChanceHolder LEAF_OF_FLAVA = new QuestItemChanceHolder(7199, 100L);
+	private static final QuestItemChanceHolder BUFFALO_MEAT = new QuestItemChanceHolder(7200, 100L);
+	private static final QuestItemChanceHolder HORN_OF_ANTELOPE = new QuestItemChanceHolder(7201, 100L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(THERMAL_BUFFALO, BUFFALO_MEAT)
+			.addSingleDrop(THERMAL_FLAVA, LEAF_OF_FLAVA)
+			.addSingleDrop(THERMAL_ANTELOPE, HORN_OF_ANTELOPE)
+			.build();
 	// Rewards
 	private static final ItemHolder RING_OF_AURAKYRA = new ItemHolder(6849, 1);
 	private static final ItemHolder SEALED_SANDDRAGONS_EARING = new ItemHolder(6847, 1);
 	private static final ItemHolder DRAGON_NECKLACE = new ItemHolder(6851, 1);
 	// Misc
 	private static final int MIN_LVL = 71;
-	
-	private static final Map<Integer, ItemHolder> MONSTER_DROPS = new HashMap<>();
-	static {
-		MONSTER_DROPS.put(THERMAL_BUFFALO, BUFFALO_MEAT);
-		MONSTER_DROPS.put(THERMAL_FLAVA, LEAF_OF_FLAVA);
-		MONSTER_DROPS.put(THERMAL_ANTELOPE, HORN_OF_ANTELOPE);
-	}
-	
+
 	public Q00623_TheFinestFood() {
 		super(623, Q00623_TheFinestFood.class.getSimpleName(), "The Finest Food");
 		addStartNpc(JEREMY);
@@ -81,7 +79,7 @@ public final class Q00623_TheFinestFood extends Quest {
 			}
 			case "31521-06.html": {
 				if (qs.isCond(2)) {
-					if (hasAllItems(player, true, LEAF_OF_FLAVA, BUFFALO_MEAT, HORN_OF_ANTELOPE)) {
+					if (hasItemsAtLimit(player, LEAF_OF_FLAVA, BUFFALO_MEAT, HORN_OF_ANTELOPE)) {
 						int random = getRandom(1000);
 						if (random < 120) {
 							giveAdena(player, 25000, true);
@@ -139,12 +137,11 @@ public final class Q00623_TheFinestFood extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 1, 3, npc);
-		final ItemHolder holder = MONSTER_DROPS.get(npc.getId());
-		if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, holder.getId(), 1, holder.getCount(), 1, true)) {
-			if (hasAllItems(qs.getPlayer(), true, BUFFALO_MEAT, HORN_OF_ANTELOPE, LEAF_OF_FLAVA)) {
+		if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			if (hasItemsAtLimit(qs.getPlayer(), BUFFALO_MEAT, HORN_OF_ANTELOPE, LEAF_OF_FLAVA)) {
 				qs.setCond(2);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00626_ADarkTwilight/Q00626_ADarkTwilight.java b/src/main/java/com/l2jserver/datapack/quests/Q00626_ADarkTwilight/Q00626_ADarkTwilight.java
index 1b96e54d12..2e4bb4a15a 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00626_ADarkTwilight/Q00626_ADarkTwilight.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00626_ADarkTwilight/Q00626_ADarkTwilight.java
@@ -18,15 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00626_ADarkTwilight;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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;
 
@@ -39,25 +35,24 @@ public class Q00626_ADarkTwilight extends Quest {
 	// NPCs
 	private static final int HIERARCH = 31517;
 	// Items
-	private static final int BLOOD_OF_SAINT = 7169;
-	// Monsters
-	private static final Map<Integer, Integer> MONSTERS = new HashMap<>();
-	static {
-		MONSTERS.put(21520, 641); // Eye of Splendor
-		MONSTERS.put(21523, 648); // Flash of Splendor
-		MONSTERS.put(21524, 692); // Blade of Splendor
-		MONSTERS.put(21525, 710); // Blade of Splendor
-		MONSTERS.put(21526, 772); // Wisdom of Splendor
-		MONSTERS.put(21529, 639); // Soul of Splendor
-		MONSTERS.put(21530, 683); // Victory of Splendor
-		MONSTERS.put(21531, 767); // Punishment of Splendor
-		MONSTERS.put(21532, 795); // Shout of Splendor
-		MONSTERS.put(21535, 802); // Signet of Splendor
-		MONSTERS.put(21536, 774); // Crown of Splendor
-		MONSTERS.put(21539, 848); // Wailing of Splendor
-		MONSTERS.put(21540, 880); // Wailing of Splendor
-		MONSTERS.put(21658, 790); // Punishment of Splendor
-	}
+	private static final QuestItemChanceHolder BLOOD_OF_SAINT = new QuestItemChanceHolder(7169, 300L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21520, BLOOD_OF_SAINT, 64.1) // Eye of Splendor
+			.addSingleDrop(21523, BLOOD_OF_SAINT, 64.8) // Flash of Splendor
+			.addSingleDrop(21524, BLOOD_OF_SAINT, 69.2) // Blade of Splendor
+			.addSingleDrop(21525, BLOOD_OF_SAINT, 71.0) // Blade of Splendor
+			.addSingleDrop(21526, BLOOD_OF_SAINT, 77.2) // Wisdom of Splendor
+			.addSingleDrop(21529, BLOOD_OF_SAINT, 63.9) // Soul of Splendor
+			.addSingleDrop(21530, BLOOD_OF_SAINT, 68.3) // Victory of Splendor
+			.addSingleDrop(21531, BLOOD_OF_SAINT, 76.7) // Punishment of Splendor
+			.addSingleDrop(21532, BLOOD_OF_SAINT, 79.5) // Shout of Splendor
+			.addSingleDrop(21535, BLOOD_OF_SAINT, 80.2) // Signet of Splendor
+			.addSingleDrop(21536, BLOOD_OF_SAINT, 77.4) // Crown of Splendor
+			.addSingleDrop(21539, BLOOD_OF_SAINT, 84.8) // Wailing of Splendor
+			.addSingleDrop(21540, BLOOD_OF_SAINT, 88.0) // Wailing of Splendor
+			.addSingleDrop(21658, BLOOD_OF_SAINT, 79.0) // Punishment of Splendor
+			.build();
 	// Misc
 	private static final int MIN_LEVEL_REQUIRED = 60;
 	private static final int ITEMS_COUNT_REQUIRED = 300;
@@ -70,8 +65,8 @@ public class Q00626_ADarkTwilight extends Quest {
 		super(626, Q00626_ADarkTwilight.class.getSimpleName(), "A Dark Twilight");
 		addStartNpc(HIERARCH);
 		addTalkId(HIERARCH);
-		addKillId(MONSTERS.keySet());
-		registerQuestItems(BLOOD_OF_SAINT);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(BLOOD_OF_SAINT.getId());
 	}
 	
 	@Override
@@ -88,7 +83,7 @@ public class Q00626_ADarkTwilight extends Quest {
 				st.startQuest();
 				break;
 			case "Exp":
-				if (st.getQuestItemsCount(BLOOD_OF_SAINT) < ITEMS_COUNT_REQUIRED) {
+				if (!hasItemsAtLimit(st.getPlayer(), BLOOD_OF_SAINT)) {
 					return "31517-06.html";
 				}
 				st.addExpAndSp(XP_COUNT, SP_COUNT);
@@ -96,7 +91,7 @@ public class Q00626_ADarkTwilight extends Quest {
 				htmltext = "31517-07.html";
 				break;
 			case "Adena":
-				if (st.getQuestItemsCount(BLOOD_OF_SAINT) < ITEMS_COUNT_REQUIRED) {
+				if (!hasItemsAtLimit(st.getPlayer(), BLOOD_OF_SAINT)) {
 					return "31517-06.html";
 				}
 				st.giveAdena(ADENA_COUNT, true);
@@ -112,18 +107,9 @@ public class Q00626_ADarkTwilight extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(killer, 1);
-		if (partyMember != null) {
-			final QuestState st = getQuestState(partyMember, false);
-			final double chance = MONSTERS.get(npc.getId()) * rates().getRateQuestDrop();
-			if (getRandom(1000) < chance) {
-				st.giveItems(BLOOD_OF_SAINT, 1);
-				if (st.getQuestItemsCount(BLOOD_OF_SAINT) < ITEMS_COUNT_REQUIRED) {
-					st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-				} else {
-					st.setCond(2, true);
-				}
-			}
+		QuestState st = getRandomPartyMemberState(killer, 1, 1, npc);
+		if (st != null && giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			st.setCond(2);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -149,4 +135,4 @@ public class Q00626_ADarkTwilight extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00627_HeartInSearchOfPower/Q00627_HeartInSearchOfPower.java b/src/main/java/com/l2jserver/datapack/quests/Q00627_HeartInSearchOfPower/Q00627_HeartInSearchOfPower.java
index e7f722ddd2..8b2e90f9b9 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00627_HeartInSearchOfPower/Q00627_HeartInSearchOfPower.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00627_HeartInSearchOfPower/Q00627_HeartInSearchOfPower.java
@@ -18,15 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00627_HeartInSearchOfPower;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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;
 
@@ -40,26 +36,25 @@ public class Q00627_HeartInSearchOfPower extends Quest {
 	private static final int ENFEUX = 31519;
 	// Items
 	private static final int SEAL_OF_LIGHT = 7170;
-	private static final int BEAD_OF_OBEDIENCE = 7171;
 	private static final int GEM_OF_SAINTS = 7172;
-	// Monsters
-	private static final Map<Integer, Integer> MONSTERS = new HashMap<>();
-	static {
-		MONSTERS.put(21520, 661); // Eye of Splendor
-		MONSTERS.put(21523, 668); // Flash of Splendor
-		MONSTERS.put(21524, 714); // Blade of Splendor
-		MONSTERS.put(21525, 714); // Blade of Splendor
-		MONSTERS.put(21526, 796); // Wisdom of Splendor
-		MONSTERS.put(21529, 659); // Soul of Splendor
-		MONSTERS.put(21530, 704); // Victory of Splendor
-		MONSTERS.put(21531, 791); // Punishment of Splendor
-		MONSTERS.put(21532, 820); // Shout of Splendor
-		MONSTERS.put(21535, 827); // Signet of Splendor
-		MONSTERS.put(21536, 798); // Crown of Splendor
-		MONSTERS.put(21539, 875); // Wailing of Splendor
-		MONSTERS.put(21540, 875); // Wailing of Splendor
-		MONSTERS.put(21658, 791); // Punishment of Splendor
-	}
+	private static final QuestItemChanceHolder BEAD_OF_OBEDIENCE = new QuestItemChanceHolder(7171, 300L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21520, BEAD_OF_OBEDIENCE, 66.1) // Eye of Splendor
+			.addSingleDrop(21523, BEAD_OF_OBEDIENCE, 66.8) // Flash of Splendor
+			.addSingleDrop(21524, BEAD_OF_OBEDIENCE, 71.4) // Blade of Splendor
+			.addSingleDrop(21525, BEAD_OF_OBEDIENCE, 71.4) // Blade of Splendor
+			.addSingleDrop(21526, BEAD_OF_OBEDIENCE, 79.6) // Wisdom of Splendor
+			.addSingleDrop(21529, BEAD_OF_OBEDIENCE, 65.9) // Soul of Splendor
+			.addSingleDrop(21530, BEAD_OF_OBEDIENCE, 70.4) // Victory of Splendor
+			.addSingleDrop(21531, BEAD_OF_OBEDIENCE, 79.1) // Punishment of Splendor
+			.addSingleDrop(21532, BEAD_OF_OBEDIENCE, 82.0) // Shout of Splendor
+			.addSingleDrop(21535, BEAD_OF_OBEDIENCE, 82.7) // Signet of Splendor
+			.addSingleDrop(21536, BEAD_OF_OBEDIENCE, 79.8) // Crown of Splendor
+			.addSingleDrop(21539, BEAD_OF_OBEDIENCE, 87.5) // Wailing of Splendor
+			.addSingleDrop(21540, BEAD_OF_OBEDIENCE, 87.5) // Wailing of Splendor
+			.addSingleDrop(21658, BEAD_OF_OBEDIENCE, 79.1) // Punishment of Splendor
+			.build();
 	// Misc
 	private static final int MIN_LEVEL_REQUIRED = 60;
 	private static final int BEAD_OF_OBEDIENCE_COUNT_REQUIRED = 300;
@@ -73,8 +68,8 @@ public class Q00627_HeartInSearchOfPower extends Quest {
 		super(627, Q00627_HeartInSearchOfPower.class.getSimpleName(), "Heart in Search of Power");
 		addStartNpc(MYSTERIOUS_NECROMANCER);
 		addTalkId(MYSTERIOUS_NECROMANCER, ENFEUX);
-		addKillId(MONSTERS.keySet());
-		registerQuestItems(SEAL_OF_LIGHT, BEAD_OF_OBEDIENCE, GEM_OF_SAINTS);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(SEAL_OF_LIGHT, BEAD_OF_OBEDIENCE.getId(), GEM_OF_SAINTS);
 	}
 	
 	@Override
@@ -89,11 +84,11 @@ public class Q00627_HeartInSearchOfPower extends Quest {
 				st.startQuest();
 				break;
 			case "31518-06.html":
-				if (st.getQuestItemsCount(BEAD_OF_OBEDIENCE) < BEAD_OF_OBEDIENCE_COUNT_REQUIRED) {
+				if (!hasItemsAtLimit(st.getPlayer(), BEAD_OF_OBEDIENCE)) {
 					return "31518-05.html";
 				}
 				st.giveItems(SEAL_OF_LIGHT, 1);
-				st.takeItems(BEAD_OF_OBEDIENCE, -1);
+				st.takeItems(BEAD_OF_OBEDIENCE.getId(), -1);
 				st.setCond(3);
 				break;
 			case "Adena":
@@ -148,18 +143,9 @@ public class Q00627_HeartInSearchOfPower extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(killer, 1);
-		if (partyMember != null) {
-			final QuestState st = getQuestState(partyMember, false);
-			final double chance = MONSTERS.get(npc.getId()) * rates().getRateQuestDrop();
-			if (getRandom(1000) < chance) {
-				st.giveItems(BEAD_OF_OBEDIENCE, 1);
-				if (st.getQuestItemsCount(BEAD_OF_OBEDIENCE) < BEAD_OF_OBEDIENCE_COUNT_REQUIRED) {
-					st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-				} else {
-					st.setCond(2, true);
-				}
-			}
+		QuestState st = getRandomPartyMemberState(killer, 1, 1, npc);
+		if (st != null && giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			st.setCond(2);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -207,4 +193,4 @@ public class Q00627_HeartInSearchOfPower extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00628_HuntGoldenRam/Q00628_HuntGoldenRam.java b/src/main/java/com/l2jserver/datapack/quests/Q00628_HuntGoldenRam/Q00628_HuntGoldenRam.java
index 9f1f3a8d1d..29b6553e0a 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00628_HuntGoldenRam/Q00628_HuntGoldenRam.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00628_HuntGoldenRam/Q00628_HuntGoldenRam.java
@@ -18,13 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00628_HuntGoldenRam;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
+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;
 
@@ -33,38 +31,39 @@ import com.l2jserver.gameserver.model.quest.State;
  * @author netvirus, Zoey76
  */
 public final class Q00628_HuntGoldenRam extends Quest {
+	// Misc
+	private static final int MIN_LVL = 66;
+	private static final long REQUIRED_ITEM_COUNT = 100L;
 	// NPCs
 	private static final int KAHMAN = 31554;
 	// Items
 	private static final int GOLDEN_RAM_BADGE_RECRUIT = 7246;
 	private static final int GOLDEN_RAM_BADGE_SOLDIER = 7247;
-	private static final int SPLINTER_STAKATO_CHITIN = 7248;
-	private static final int NEEDLE_STAKATO_CHITIN = 7249;
-	// Misc
-	private static final int REQUIRED_ITEM_COUNT = 100;
-	private static final int MIN_LVL = 66;
-	// Mobs
-	private static final Map<Integer, ItemChanceHolder> MOBS_DROP_CHANCES = new HashMap<>();
-	
-	static {
-		MOBS_DROP_CHANCES.put(21508, new ItemChanceHolder(SPLINTER_STAKATO_CHITIN, 0.500, 1)); // splinter_stakato
-		MOBS_DROP_CHANCES.put(21509, new ItemChanceHolder(SPLINTER_STAKATO_CHITIN, 0.430, 1)); // splinter_stakato_worker
-		MOBS_DROP_CHANCES.put(21510, new ItemChanceHolder(SPLINTER_STAKATO_CHITIN, 0.521, 1)); // splinter_stakato_soldier
-		MOBS_DROP_CHANCES.put(21511, new ItemChanceHolder(SPLINTER_STAKATO_CHITIN, 0.575, 1)); // splinter_stakato_drone
-		MOBS_DROP_CHANCES.put(21512, new ItemChanceHolder(SPLINTER_STAKATO_CHITIN, 0.746, 1)); // splinter_stakato_drone_a
-		MOBS_DROP_CHANCES.put(21513, new ItemChanceHolder(NEEDLE_STAKATO_CHITIN, 0.500, 2)); // needle_stakato
-		MOBS_DROP_CHANCES.put(21514, new ItemChanceHolder(NEEDLE_STAKATO_CHITIN, 0.430, 2)); // needle_stakato_worker
-		MOBS_DROP_CHANCES.put(21515, new ItemChanceHolder(NEEDLE_STAKATO_CHITIN, 0.520, 2)); // needle_stakato_soldier
-		MOBS_DROP_CHANCES.put(21516, new ItemChanceHolder(NEEDLE_STAKATO_CHITIN, 0.531, 2)); // needle_stakato_drone
-		MOBS_DROP_CHANCES.put(21517, new ItemChanceHolder(NEEDLE_STAKATO_CHITIN, 0.744, 2)); // needle_stakato_drone_a
-	}
+	private static final QuestItemChanceHolder SPLINTER_STAKATO_CHITIN = new QuestItemChanceHolder(7248, REQUIRED_ITEM_COUNT);
+	private static final QuestItemChanceHolder NEEDLE_STAKATO_CHITIN = new QuestItemChanceHolder(7249, REQUIRED_ITEM_COUNT);
+	// Droplists
+	private static final QuestDroplist SPLINTER_DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21508, SPLINTER_STAKATO_CHITIN, 50.0) // splinter_stakato
+			.addSingleDrop(21509, SPLINTER_STAKATO_CHITIN, 43.0) // splinter_stakato_worker
+			.addSingleDrop(21510, SPLINTER_STAKATO_CHITIN, 52.1) // splinter_stakato_soldier
+			.addSingleDrop(21511, SPLINTER_STAKATO_CHITIN, 57.5) // splinter_stakato_drone
+			.addSingleDrop(21512, SPLINTER_STAKATO_CHITIN, 74.6) // splinter_stakato_drone_a
+			.build();
+	private static final QuestDroplist NEEDLE_DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21513, NEEDLE_STAKATO_CHITIN, 50.0) // needle_stakato
+			.addSingleDrop(21514, NEEDLE_STAKATO_CHITIN, 43.0) // needle_stakato_worker
+			.addSingleDrop(21515, NEEDLE_STAKATO_CHITIN, 52.0) // needle_stakato_soldier
+			.addSingleDrop(21516, NEEDLE_STAKATO_CHITIN, 53.1) // needle_stakato_drone
+			.addSingleDrop(21517, NEEDLE_STAKATO_CHITIN, 74.4) // needle_stakato_drone_a
+			.build();
 	
 	public Q00628_HuntGoldenRam() {
 		super(628, Q00628_HuntGoldenRam.class.getSimpleName(), "Hunt of the Golden Ram Mercenary Force");
 		addStartNpc(KAHMAN);
 		addTalkId(KAHMAN);
-		addKillId(MOBS_DROP_CHANCES.keySet());
-		registerQuestItems(SPLINTER_STAKATO_CHITIN, NEEDLE_STAKATO_CHITIN);
+		addKillId(SPLINTER_DROPLIST.getNpcIds());
+		addKillId(NEEDLE_DROPLIST.getNpcIds());
+		registerQuestItems(SPLINTER_STAKATO_CHITIN.getId(), NEEDLE_STAKATO_CHITIN.getId());
 	}
 	
 	@Override
@@ -92,9 +91,9 @@ public final class Q00628_HuntGoldenRam extends Quest {
 				break;
 			}
 			case "31554-08.html": {
-				if (getQuestItemsCount(player, SPLINTER_STAKATO_CHITIN) >= REQUIRED_ITEM_COUNT) {
+				if (hasItemsAtLimit(player, SPLINTER_STAKATO_CHITIN)) {
 					giveItems(player, GOLDEN_RAM_BADGE_RECRUIT, 1);
-					takeItems(player, SPLINTER_STAKATO_CHITIN, -1);
+					takeItems(player, SPLINTER_STAKATO_CHITIN.getId(), -1);
 					qs.setCond(2, true);
 					htmltext = event;
 				}
@@ -122,9 +121,9 @@ public final class Q00628_HuntGoldenRam extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 1, npc);
 		if (qs != null) {
-			final ItemChanceHolder item = MOBS_DROP_CHANCES.get(npc.getId());
-			if ((item.getCount() <= qs.getCond()) && !qs.isCond(3)) {
-				giveItemRandomly(qs.getPlayer(), npc, item.getId(), 1, REQUIRED_ITEM_COUNT, item.getChance(), true);
+			switch (qs.getCond()) {
+				case 1 -> giveItemRandomly(qs.getPlayer(), npc, SPLINTER_DROPLIST.get(npc), true);
+				case 2 -> giveItemRandomly(qs.getPlayer(), npc, NEEDLE_DROPLIST.get(npc), true);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -140,8 +139,8 @@ public final class Q00628_HuntGoldenRam extends Quest {
 				break;
 			}
 			case State.STARTED: {
-				final long itemCountSplinter = getQuestItemsCount(player, SPLINTER_STAKATO_CHITIN);
-				final long itemCountNeedle = getQuestItemsCount(player, NEEDLE_STAKATO_CHITIN);
+				final long itemCountSplinter = getQuestItemsCount(player, SPLINTER_STAKATO_CHITIN.getId());
+				final long itemCountNeedle = getQuestItemsCount(player, NEEDLE_STAKATO_CHITIN.getId());
 				switch (qs.getCond()) {
 					case 1: {
 						htmltext = ((itemCountSplinter >= REQUIRED_ITEM_COUNT) ? "31554-07.html" : "31554-06.html");
@@ -151,8 +150,8 @@ public final class Q00628_HuntGoldenRam extends Quest {
 						if (hasQuestItems(player, GOLDEN_RAM_BADGE_RECRUIT)) {
 							if ((itemCountSplinter >= REQUIRED_ITEM_COUNT) && (itemCountNeedle >= REQUIRED_ITEM_COUNT)) {
 								takeItems(player, GOLDEN_RAM_BADGE_RECRUIT, -1);
-								takeItems(player, SPLINTER_STAKATO_CHITIN, -1);
-								takeItems(player, NEEDLE_STAKATO_CHITIN, -1);
+								takeItems(player, SPLINTER_STAKATO_CHITIN.getId(), -1);
+								takeItems(player, NEEDLE_STAKATO_CHITIN.getId(), -1);
 								giveItems(player, GOLDEN_RAM_BADGE_SOLDIER, 1);
 								qs.setCond(3, true);
 								htmltext = "31554-10.html";
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00629_CleanUpTheSwampOfScreams/Q00629_CleanUpTheSwampOfScreams.java b/src/main/java/com/l2jserver/datapack/quests/Q00629_CleanUpTheSwampOfScreams/Q00629_CleanUpTheSwampOfScreams.java
index 297bb7abd3..0a513e14b4 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00629_CleanUpTheSwampOfScreams/Q00629_CleanUpTheSwampOfScreams.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00629_CleanUpTheSwampOfScreams/Q00629_CleanUpTheSwampOfScreams.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00629_CleanUpTheSwampOfScreams;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -36,30 +34,28 @@ public final class Q00629_CleanUpTheSwampOfScreams extends Quest {
 	// Items
 	private static final int TALON_OF_STAKATO = 7250;
 	private static final int GOLDEN_RAM_COIN = 7251;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21508, TALON_OF_STAKATO, 59.9) // splinter_stakato
+			.addSingleDrop(21509, TALON_OF_STAKATO, 52.4) // splinter_stakato_worker
+			.addSingleDrop(21510, TALON_OF_STAKATO, 64.0) // splinter_stakato_soldier
+			.addSingleDrop(21511, TALON_OF_STAKATO, 83.0) // splinter_stakato_drone
+			.addSingleDrop(21512, TALON_OF_STAKATO, 97.0) // splinter_stakato_drone_a
+			.addSingleDrop(21513, TALON_OF_STAKATO, 68.2) // needle_stakato
+			.addSingleDrop(21514, TALON_OF_STAKATO, 59.5) // needle_stakato_worker
+			.addSingleDrop(21515, TALON_OF_STAKATO, 72.7) // needle_stakato_soldier
+			.addSingleDrop(21516, TALON_OF_STAKATO, 87.9) // needle_stakato_drone
+			.addSingleDrop(21517, TALON_OF_STAKATO, 99.9) // needle_stakato_drone_a
+			.build();
 	// Misc
 	private static final int REQUIRED_TALON_COUNT = 100;
 	private static final int MIN_LVL = 66;
-	// Mobs
-	private static final Map<Integer, Double> MOBS_DROP_CHANCES = new HashMap<>();
-	
-	static {
-		MOBS_DROP_CHANCES.put(21508, 0.599); // splinter_stakato
-		MOBS_DROP_CHANCES.put(21509, 0.524); // splinter_stakato_worker
-		MOBS_DROP_CHANCES.put(21510, 0.640); // splinter_stakato_soldier
-		MOBS_DROP_CHANCES.put(21511, 0.830); // splinter_stakato_drone
-		MOBS_DROP_CHANCES.put(21512, 0.970); // splinter_stakato_drone_a
-		MOBS_DROP_CHANCES.put(21513, 0.682); // needle_stakato
-		MOBS_DROP_CHANCES.put(21514, 0.595); // needle_stakato_worker
-		MOBS_DROP_CHANCES.put(21515, 0.727); // needle_stakato_soldier
-		MOBS_DROP_CHANCES.put(21516, 0.879); // needle_stakato_drone
-		MOBS_DROP_CHANCES.put(21517, 0.999); // needle_stakato_drone_a
-	}
 	
 	public Q00629_CleanUpTheSwampOfScreams() {
 		super(629, Q00629_CleanUpTheSwampOfScreams.class.getSimpleName(), "Clean Up The Swamp Of Screams");
 		addStartNpc(PIERCE);
 		addTalkId(PIERCE);
-		addKillId(MOBS_DROP_CHANCES.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(TALON_OF_STAKATO, GOLDEN_RAM_COIN);
 	}
 	
@@ -111,7 +107,7 @@ public final class Q00629_CleanUpTheSwampOfScreams extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 2, npc);
 		if (qs != null) {
-			giveItemRandomly(qs.getPlayer(), npc, TALON_OF_STAKATO, 1, 0, MOBS_DROP_CHANCES.get(npc.getId()), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00631_DeliciousTopChoiceMeat/Q00631_DeliciousTopChoiceMeat.java b/src/main/java/com/l2jserver/datapack/quests/Q00631_DeliciousTopChoiceMeat/Q00631_DeliciousTopChoiceMeat.java
index 7089fb3bfe..37cdc3d788 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00631_DeliciousTopChoiceMeat/Q00631_DeliciousTopChoiceMeat.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00631_DeliciousTopChoiceMeat/Q00631_DeliciousTopChoiceMeat.java
@@ -18,12 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00631_DeliciousTopChoiceMeat;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -31,14 +30,24 @@ import com.l2jserver.gameserver.model.quest.QuestState;
  * @author Adry_85
  */
 public class Q00631_DeliciousTopChoiceMeat extends Quest {
+	// Misc
+	private static final int MIN_LEVEL = 82;
 	// NPC
 	private static final int TUNATUN = 31537;
 	// Items
 	private static final int TOP_QUALITY_MEAT = 7546;
-	private static final int PRIME_MEAT = 15534;
-	// Misc
-	private static final int MIN_LEVEL = 82;
-	private static final int PRIME_MEAT_COUNT = 120;
+	private static final QuestItemChanceHolder PRIME_MEAT = new QuestItemChanceHolder(15534, 120L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(18878, PRIME_MEAT, 17.2) // Full Grown Kookaburra
+			.addSingleDrop(18879, PRIME_MEAT, 33.4) // Full Grown Kookaburra
+			.addSingleDrop(18885, PRIME_MEAT, 17.2) // Full Grown Cougar
+			.addSingleDrop(18886, PRIME_MEAT, 33.4) // Full Grown Cougar
+			.addSingleDrop(18892, PRIME_MEAT, 18.2) // Full Grown Buffalo
+			.addSingleDrop(18893, PRIME_MEAT, 34.9) // Full Grown Buffalo
+			.addSingleDrop(18899, PRIME_MEAT, 18.2) // Full Grown Grendel
+			.addSingleDrop(18900, PRIME_MEAT, 34.9) // Full Grown Grendel
+			.build();
 	// Rewards
 	private static final int[] RECIPE = {
 		10373, // Recipe - Icarus Sawsword (60%)
@@ -67,24 +76,12 @@ public class Q00631_DeliciousTopChoiceMeat extends Quest {
 	private static final int GOLDEN_SPICE_CRATE = 15482;
 	private static final int CRYSTAL_SPICE_COMPRESSED_PACK = 15483;
 	
-	private static final Map<Integer, Double> MOBS_MEAT = new HashMap<>();
-	static {
-		MOBS_MEAT.put(18878, 0.172); // Full Grown Kookaburra
-		MOBS_MEAT.put(18879, 0.334); // Full Grown Kookaburra
-		MOBS_MEAT.put(18885, 0.172); // Full Grown Cougar
-		MOBS_MEAT.put(18886, 0.334); // Full Grown Cougar
-		MOBS_MEAT.put(18892, 0.182); // Full Grown Buffalo
-		MOBS_MEAT.put(18893, 0.349); // Full Grown Buffalo
-		MOBS_MEAT.put(18899, 0.182); // Full Grown Grendel
-		MOBS_MEAT.put(18900, 0.349); // Full Grown Grendel
-	}
-	
 	public Q00631_DeliciousTopChoiceMeat() {
 		super(631, Q00631_DeliciousTopChoiceMeat.class.getSimpleName(), "Delicious Top Choice Meat");
 		addStartNpc(TUNATUN);
 		addTalkId(TUNATUN);
-		addKillId(MOBS_MEAT.keySet());
-		registerQuestItems(TOP_QUALITY_MEAT, PRIME_MEAT);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(TOP_QUALITY_MEAT, PRIME_MEAT.getId());
 	}
 	
 	@Override
@@ -106,48 +103,18 @@ public class Q00631_DeliciousTopChoiceMeat extends Quest {
 				break;
 			}
 			case "31537-06.html": {
-				if (st.isCond(2) && (getQuestItemsCount(player, PRIME_MEAT) >= PRIME_MEAT_COUNT)) {
+				if (st.isCond(2) && hasItemsAtLimit(player, PRIME_MEAT)) {
 					switch (getRandom(10)) {
-						case 0: {
-							st.rewardItems(RECIPE[getRandom(RECIPE.length)], 1);
-							break;
-						}
-						case 1: {
-							st.rewardItems(PIECE[getRandom(PIECE.length)], 1);
-							break;
-						}
-						case 2: {
-							st.rewardItems(PIECE[getRandom(PIECE.length)], 2);
-							break;
-						}
-						case 3: {
-							st.rewardItems(PIECE[getRandom(PIECE.length)], 3);
-							break;
-						}
-						case 4: {
-							st.rewardItems(PIECE[getRandom(PIECE.length)], getRandom(5) + 2);
-							break;
-						}
-						case 5: {
-							st.rewardItems(PIECE[getRandom(PIECE.length)], getRandom(7) + 2);
-							break;
-						}
-						case 6: {
-							st.rewardItems(GOLDEN_SPICE_CRATE, 1);
-							break;
-						}
-						case 7: {
-							st.rewardItems(GOLDEN_SPICE_CRATE, 2);
-							break;
-						}
-						case 8: {
-							st.rewardItems(CRYSTAL_SPICE_COMPRESSED_PACK, 1);
-							break;
-						}
-						case 9: {
-							st.rewardItems(CRYSTAL_SPICE_COMPRESSED_PACK, 2);
-							break;
-						}
+						case 0 -> st.rewardItems(RECIPE[getRandom(RECIPE.length)], 1);
+						case 1 -> st.rewardItems(PIECE[getRandom(PIECE.length)], 1);
+						case 2 -> st.rewardItems(PIECE[getRandom(PIECE.length)], 2);
+						case 3 -> st.rewardItems(PIECE[getRandom(PIECE.length)], 3);
+						case 4 -> st.rewardItems(PIECE[getRandom(PIECE.length)], getRandom(5) + 2);
+						case 5 -> st.rewardItems(PIECE[getRandom(PIECE.length)], getRandom(7) + 2);
+						case 6 -> st.rewardItems(GOLDEN_SPICE_CRATE, 1);
+						case 7 -> st.rewardItems(GOLDEN_SPICE_CRATE, 2);
+						case 8 -> st.rewardItems(CRYSTAL_SPICE_COMPRESSED_PACK, 1);
+						case 9 -> st.rewardItems(CRYSTAL_SPICE_COMPRESSED_PACK, 2);
 					}
 					st.exitQuest(true, true);
 					htmltext = event;
@@ -162,8 +129,8 @@ public class Q00631_DeliciousTopChoiceMeat extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState st = getRandomPartyMemberState(player, 1, 3, npc);
 		if (st != null) {
-			if (st.giveItemRandomly(npc, PRIME_MEAT, 1, PRIME_MEAT_COUNT, MOBS_MEAT.get(npc.getId()), true)) {
-				st.setCond(2, true);
+			if (giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
+				st.setCond(2);
 			}
 		}
 		return super.onKill(npc, player, isSummon);
@@ -177,11 +144,11 @@ public class Q00631_DeliciousTopChoiceMeat extends Quest {
 			htmltext = "31537-01.htm";
 		} else if (st.isStarted()) {
 			if (st.isCond(1)) {
-				if (st.getQuestItemsCount(PRIME_MEAT) < PRIME_MEAT_COUNT) {
+				if (!hasItemsAtLimit(st.getPlayer(), PRIME_MEAT)) {
 					htmltext = "31537-04.html";
 				}
 			} else if (st.isCond(2)) {
-				if (st.getQuestItemsCount(PRIME_MEAT) >= PRIME_MEAT_COUNT) {
+				if (hasItemsAtLimit(st.getPlayer(), PRIME_MEAT)) {
 					htmltext = "31537-05.html";
 				}
 			}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00632_NecromancersRequest/Q00632_NecromancersRequest.java b/src/main/java/com/l2jserver/datapack/quests/Q00632_NecromancersRequest/Q00632_NecromancersRequest.java
index af97f288e1..61308b4043 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00632_NecromancersRequest/Q00632_NecromancersRequest.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00632_NecromancersRequest/Q00632_NecromancersRequest.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00632_NecromancersRequest;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -36,51 +34,47 @@ public final class Q00632_NecromancersRequest extends Quest {
 	// Items
 	private static final int VAMPIRES_HEART = 7542;
 	private static final int ZOMBIES_BRAIN = 7543;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21547, ZOMBIES_BRAIN, 56.5) // Corrupted Knight
+			.addSingleDrop(21548, ZOMBIES_BRAIN, 48.4) // Resurrected Knight
+			.addSingleDrop(21549, ZOMBIES_BRAIN, 58.5) // Corrupted Guard
+			.addSingleDrop(21550, ZOMBIES_BRAIN, 59.7) // Corrupted Guard
+			.addSingleDrop(21551, ZOMBIES_BRAIN, 67.3) // Resurrected Guard
+			.addSingleDrop(21552, ZOMBIES_BRAIN, 63.7) // Resurrected Guard
+			.addSingleDrop(21555, ZOMBIES_BRAIN, 57.5) // Slaughter Executioner
+			.addSingleDrop(21556, ZOMBIES_BRAIN, 56.0) // Slaughter Executioner
+			.addSingleDrop(21562, ZOMBIES_BRAIN, 63.1) // Guillotine's Ghost
+			.addSingleDrop(21571, ZOMBIES_BRAIN, 75.8) // Ghost of Rebellion Soldier
+			.addSingleDrop(21576, ZOMBIES_BRAIN, 64.7) // Ghost of Guillotine
+			.addSingleDrop(21577, ZOMBIES_BRAIN, 62.5) // Ghost of Guillotine
+			.addSingleDrop(21579, ZOMBIES_BRAIN, 76.6) // Ghost of Rebellion Leader
+			.addSingleDrop(21568, VAMPIRES_HEART, 45.2) // Devil Bat
+			.addSingleDrop(21569, VAMPIRES_HEART, 48.4) // Devil Bat
+			.addSingleDrop(21573, VAMPIRES_HEART, 49.9) // Atrox
+			.addSingleDrop(21582, VAMPIRES_HEART, 52.2) // Vampire Soldier
+			.addSingleDrop(21585, VAMPIRES_HEART, 41.3) // Vampire Magician
+			.addSingleDrop(21586, VAMPIRES_HEART, 49.6) // Vampire Adept
+			.addSingleDrop(21587, VAMPIRES_HEART, 51.9) // Vampire Warrior
+			.addSingleDrop(21588, VAMPIRES_HEART, 42.8) // Vampire Wizard
+			.addSingleDrop(21589, VAMPIRES_HEART, 43.9) // Vampire Wizard
+			.addSingleDrop(21590, VAMPIRES_HEART, 42.8) // Vampire Magister
+			.addSingleDrop(21591, VAMPIRES_HEART, 50.2) // Vampire Magister
+			.addSingleDrop(21592, VAMPIRES_HEART, 37.0) // Vampire Magister
+			.addSingleDrop(21593, VAMPIRES_HEART, 59.2) // Vampire Warlord
+			.addSingleDrop(21594, VAMPIRES_HEART, 55.4) // Vampire Warlord
+			.addSingleDrop(21595, VAMPIRES_HEART, 39.2) // Vampire Warlord
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 63;
 	private static final int REQUIRED_ITEM_COUNT = 200;
 	private static final int ADENA_REWARD = 120000;
-	// Monsters
-	private static final Map<Integer, Double> BRAIN_MONSTERS = new HashMap<>();
-	private static final Map<Integer, Double> HEART_MONSTERS = new HashMap<>();
-	static {
-		BRAIN_MONSTERS.put(21547, 0.565); // Corrupted Knight
-		BRAIN_MONSTERS.put(21548, 0.484); // Resurrected Knight
-		BRAIN_MONSTERS.put(21549, 0.585); // Corrupted Guard
-		BRAIN_MONSTERS.put(21550, 0.597); // Corrupted Guard
-		BRAIN_MONSTERS.put(21551, 0.673); // Resurrected Guard
-		BRAIN_MONSTERS.put(21552, 0.637); // Resurrected Guard
-		BRAIN_MONSTERS.put(21555, 0.575); // Slaughter Executioner
-		BRAIN_MONSTERS.put(21556, 0.560); // Slaughter Executioner
-		BRAIN_MONSTERS.put(21562, 0.631); // Guillotine's Ghost
-		BRAIN_MONSTERS.put(21571, 0.758); // Ghost of Rebellion Soldier
-		BRAIN_MONSTERS.put(21576, 0.647); // Ghost of Guillotine
-		BRAIN_MONSTERS.put(21577, 0.625); // Ghost of Guillotine
-		BRAIN_MONSTERS.put(21579, 0.766); // Ghost of Rebellion Leader
-		
-		HEART_MONSTERS.put(21568, 0.452); // Devil Bat
-		HEART_MONSTERS.put(21569, 0.484); // Devil Bat
-		HEART_MONSTERS.put(21573, 0.499); // Atrox
-		HEART_MONSTERS.put(21582, 0.522); // Vampire Soldier
-		HEART_MONSTERS.put(21585, 0.413); // Vampire Magician
-		HEART_MONSTERS.put(21586, 0.496); // Vampire Adept
-		HEART_MONSTERS.put(21587, 0.519); // Vampire Warrior
-		HEART_MONSTERS.put(21588, 0.428); // Vampire Wizard
-		HEART_MONSTERS.put(21589, 0.439); // Vampire Wizard
-		HEART_MONSTERS.put(21590, 0.428); // Vampire Magister
-		HEART_MONSTERS.put(21591, 0.502); // Vampire Magister
-		HEART_MONSTERS.put(21592, 0.370); // Vampire Magister
-		HEART_MONSTERS.put(21593, 0.592); // Vampire Warlord
-		HEART_MONSTERS.put(21594, 0.554); // Vampire Warlord
-		HEART_MONSTERS.put(21595, 0.392); // Vampire Warlord
-	}
 	
 	public Q00632_NecromancersRequest() {
 		super(632, Q00632_NecromancersRequest.class.getSimpleName(), "Necromancer's Request");
 		addStartNpc(MYSTERIOUS_WIZARD);
 		addTalkId(MYSTERIOUS_WIZARD);
-		addKillId(BRAIN_MONSTERS.keySet());
-		addKillId(HEART_MONSTERS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(VAMPIRES_HEART, ZOMBIES_BRAIN);
 	}
 	
@@ -130,15 +124,11 @@ public final class Q00632_NecromancersRequest extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(player, -1, 3, npc);
 		if (qs != null) {
-			if (BRAIN_MONSTERS.containsKey(npc.getId())) {
-				qs.giveItemRandomly(npc, ZOMBIES_BRAIN, 1, 0, BRAIN_MONSTERS.get(npc.getId()), true);
-			} else {
-				qs.giveItemRandomly(npc, VAMPIRES_HEART, 1, 0, HEART_MONSTERS.get(npc.getId()), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 				
-				if (getQuestItemsCount(player, VAMPIRES_HEART) >= REQUIRED_ITEM_COUNT) {
-					qs.setCond(2);
-					qs.setMemoState(12);
-				}
+			if (getQuestItemsCount(player, VAMPIRES_HEART) >= REQUIRED_ITEM_COUNT) {
+				qs.setCond(2);
+				qs.setMemoState(12);
 			}
 		}
 		return super.onKill(npc, player, isSummon);
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00633_InTheForgottenVillage/Q00633_InTheForgottenVillage.java b/src/main/java/com/l2jserver/datapack/quests/Q00633_InTheForgottenVillage/Q00633_InTheForgottenVillage.java
index 8add1ce3b2..f972f0bdf9 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00633_InTheForgottenVillage/Q00633_InTheForgottenVillage.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00633_InTheForgottenVillage/Q00633_InTheForgottenVillage.java
@@ -18,13 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00633_InTheForgottenVillage;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
+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;
 
 /**
@@ -35,49 +34,47 @@ public final class Q00633_InTheForgottenVillage extends Quest {
 	// NPC
 	private static final int MINA = 31388;
 	// Items
-	private static final int RIB_BONE_OF_A_BLACK_MAGUS = 7544;
+	private static final QuestItemChanceHolder RIB_BONE_OF_A_BLACK_MAGUS = new QuestItemChanceHolder(7544, 200L);
 	private static final int ZOMBIES_LIVER = 7545;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21553, ZOMBIES_LIVER, 41.7) // Trampled Man
+			.addSingleDrop(21554, ZOMBIES_LIVER, 41.7) // Trampled Man
+			.addSingleDrop(21557, RIB_BONE_OF_A_BLACK_MAGUS, 39.4) // Bone Snatcher
+			.addSingleDrop(21558, RIB_BONE_OF_A_BLACK_MAGUS, 39.4) // Bone Snatcher
+			.addSingleDrop(21559, RIB_BONE_OF_A_BLACK_MAGUS, 43.6) // Bone Maker
+			.addSingleDrop(21560, RIB_BONE_OF_A_BLACK_MAGUS, 43.0) // Bone Shaper
+			.addSingleDrop(21561, ZOMBIES_LIVER, 53.8) // Sacrificed Man
+			.addSingleDrop(21563, RIB_BONE_OF_A_BLACK_MAGUS, 43.6) // Bone Collector
+			.addSingleDrop(21564, RIB_BONE_OF_A_BLACK_MAGUS, 41.4) // Skull Collector
+			.addSingleDrop(21565, RIB_BONE_OF_A_BLACK_MAGUS, 42.0) // Bone Animator
+			.addSingleDrop(21566, RIB_BONE_OF_A_BLACK_MAGUS, 46.0) // Skull Animator
+			.addSingleDrop(21567, RIB_BONE_OF_A_BLACK_MAGUS, 54.9) // Bone Slayer
+			.addSingleDrop(21570, ZOMBIES_LIVER, 50.8) // Ghost of Betrayer
+			.addSingleDrop(21572, RIB_BONE_OF_A_BLACK_MAGUS, 46.5) // Bone Sweeper
+			.addSingleDrop(21574, RIB_BONE_OF_A_BLACK_MAGUS, 58.6) // Bone Grinder
+			.addSingleDrop(21575, RIB_BONE_OF_A_BLACK_MAGUS, 32.9) // Bone Grinder
+			.addSingleDrop(21578, ZOMBIES_LIVER, 64.9) // Behemoth Zombie
+			.addSingleDrop(21580, RIB_BONE_OF_A_BLACK_MAGUS, 46.2) // Bone Caster
+			.addSingleDrop(21581, RIB_BONE_OF_A_BLACK_MAGUS, 50.5) // Bone Puppeteer
+			.addSingleDrop(21583, RIB_BONE_OF_A_BLACK_MAGUS, 47.5) // Bone Scavenger
+			.addSingleDrop(21584, RIB_BONE_OF_A_BLACK_MAGUS, 47.5) // Bone Scavenger
+			.addSingleDrop(21596, RIB_BONE_OF_A_BLACK_MAGUS, 54.3) // Requiem Lord
+			.addSingleDrop(21597, ZOMBIES_LIVER, 51.0) // Requiem Behemoth
+			.addSingleDrop(21598, ZOMBIES_LIVER, 57.2) // Requiem Behemoth
+			.addSingleDrop(21599, RIB_BONE_OF_A_BLACK_MAGUS, 58.0) // Requiem Priest
+			.addSingleDrop(21600, ZOMBIES_LIVER, 56.1) // Requiem Behemoth
+			.addSingleDrop(21601, RIB_BONE_OF_A_BLACK_MAGUS, 67.7) // Requiem Behemoth
+			.build();
 	// Misc
 	private static final int MIN_LVL = 65;
-	private static final int RIB_BONE_REQUIRED_COUNT = 200;
-	// Mobs
-	private static final Map<Integer, ItemChanceHolder> MOBS_DROP_CHANCES = new HashMap<>();
-	static {
-		MOBS_DROP_CHANCES.put(21553, new ItemChanceHolder(ZOMBIES_LIVER, 0.417)); // Trampled Man
-		MOBS_DROP_CHANCES.put(21554, new ItemChanceHolder(ZOMBIES_LIVER, 0.417)); // Trampled Man
-		MOBS_DROP_CHANCES.put(21557, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.394)); // Bone Snatcher
-		MOBS_DROP_CHANCES.put(21558, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.394)); // Bone Snatcher
-		MOBS_DROP_CHANCES.put(21559, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.436)); // Bone Maker
-		MOBS_DROP_CHANCES.put(21560, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.430)); // Bone Shaper
-		MOBS_DROP_CHANCES.put(21561, new ItemChanceHolder(ZOMBIES_LIVER, 0.538)); // Sacrificed Man
-		MOBS_DROP_CHANCES.put(21563, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.436)); // Bone Collector
-		MOBS_DROP_CHANCES.put(21564, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.414)); // Skull Collector
-		MOBS_DROP_CHANCES.put(21565, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.420)); // Bone Animator
-		MOBS_DROP_CHANCES.put(21566, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.460)); // Skull Animator
-		MOBS_DROP_CHANCES.put(21567, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.549)); // Bone Slayer
-		MOBS_DROP_CHANCES.put(21570, new ItemChanceHolder(ZOMBIES_LIVER, 0.508)); // Ghost of Betrayer
-		MOBS_DROP_CHANCES.put(21572, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.465)); // Bone Sweeper
-		MOBS_DROP_CHANCES.put(21574, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.586)); // Bone Grinder
-		MOBS_DROP_CHANCES.put(21575, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.329)); // Bone Grinder
-		MOBS_DROP_CHANCES.put(21578, new ItemChanceHolder(ZOMBIES_LIVER, 0.649)); // Behemoth Zombie
-		MOBS_DROP_CHANCES.put(21580, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.462)); // Bone Caster
-		MOBS_DROP_CHANCES.put(21581, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.505)); // Bone Puppeteer
-		MOBS_DROP_CHANCES.put(21583, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.475)); // Bone Scavenger
-		MOBS_DROP_CHANCES.put(21584, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.475)); // Bone Scavenger
-		MOBS_DROP_CHANCES.put(21596, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.543)); // Requiem Lord
-		MOBS_DROP_CHANCES.put(21597, new ItemChanceHolder(ZOMBIES_LIVER, 0.510)); // Requiem Behemoth
-		MOBS_DROP_CHANCES.put(21598, new ItemChanceHolder(ZOMBIES_LIVER, 0.572)); // Requiem Behemoth
-		MOBS_DROP_CHANCES.put(21599, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.580)); // Requiem Priest
-		MOBS_DROP_CHANCES.put(21600, new ItemChanceHolder(ZOMBIES_LIVER, 0.561)); // Requiem Behemoth
-		MOBS_DROP_CHANCES.put(21601, new ItemChanceHolder(RIB_BONE_OF_A_BLACK_MAGUS, 0.677)); // Requiem Behemoth
-	}
-	
+
 	public Q00633_InTheForgottenVillage() {
 		super(633, Q00633_InTheForgottenVillage.class.getSimpleName(), "In The Forgotten Village");
 		addStartNpc(MINA);
 		addTalkId(MINA);
-		addKillId(MOBS_DROP_CHANCES.keySet());
-		registerQuestItems(RIB_BONE_OF_A_BLACK_MAGUS, ZOMBIES_LIVER);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(RIB_BONE_OF_A_BLACK_MAGUS.getId(), ZOMBIES_LIVER);
 	}
 	
 	@Override
@@ -106,10 +103,10 @@ public final class Q00633_InTheForgottenVillage extends Quest {
 			}
 			case "31388-07.html": {
 				if (qs.isCond(2)) {
-					if (getQuestItemsCount(player, RIB_BONE_OF_A_BLACK_MAGUS) >= RIB_BONE_REQUIRED_COUNT) {
+					if (hasItemsAtLimit(player, RIB_BONE_OF_A_BLACK_MAGUS)) {
 						giveAdena(player, 25000, true);
 						addExpAndSp(player, 305235, 0);
-						takeItems(player, RIB_BONE_OF_A_BLACK_MAGUS, -1);
+						takeItems(player, RIB_BONE_OF_A_BLACK_MAGUS.getId(), -1);
 						qs.setCond(1, true);
 						htmltext = event;
 					} else {
@@ -133,18 +130,12 @@ public final class Q00633_InTheForgottenVillage extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			final ItemChanceHolder info = MOBS_DROP_CHANCES.get(npc.getId());
-			switch (info.getId()) {
-				case RIB_BONE_OF_A_BLACK_MAGUS: {
-					if (qs.isCond(1) && giveItemRandomly(qs.getPlayer(), npc, RIB_BONE_OF_A_BLACK_MAGUS, 1, RIB_BONE_REQUIRED_COUNT, info.getChance(), true)) {
-						qs.setCond(2);
-					}
-					break;
-				}
-				case ZOMBIES_LIVER: {
-					giveItemRandomly(qs.getPlayer(), npc, ZOMBIES_LIVER, 1, 0, info.getChance(), true);
-					break;
-				}
+			QuestDropInfo dropInfo = DROPLIST.get(npc);
+			if (RIB_BONE_OF_A_BLACK_MAGUS.getId() == dropInfo.item().getId() && qs.isCond(1)
+					&& giveItemRandomly(qs.getPlayer(), npc, dropInfo, true)) {
+				qs.setCond(2);
+			} else {
+				giveItemRandomly(qs.getPlayer(), npc, dropInfo, true);
 			}
 		}
 		return super.onKill(npc, killer, isSummon);
@@ -157,7 +148,7 @@ public final class Q00633_InTheForgottenVillage extends Quest {
 		if (qs.isCreated()) {
 			htmltext = ((player.getLevel() >= MIN_LVL) ? "31388-01.htm" : "31388-02.htm");
 		} else if (qs.isStarted()) {
-			htmltext = ((getQuestItemsCount(player, RIB_BONE_OF_A_BLACK_MAGUS) >= RIB_BONE_REQUIRED_COUNT) ? "31388-04.html" : "31388-05.html");
+			htmltext = hasItemsAtLimit(player, RIB_BONE_OF_A_BLACK_MAGUS) ? "31388-04.html" : "31388-05.html";
 		}
 		return htmltext;
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00634_InSearchOfFragmentsOfDimension/Q00634_InSearchOfFragmentsOfDimension.java b/src/main/java/com/l2jserver/datapack/quests/Q00634_InSearchOfFragmentsOfDimension/Q00634_InSearchOfFragmentsOfDimension.java
index c6f4423e84..d46c882834 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00634_InSearchOfFragmentsOfDimension/Q00634_InSearchOfFragmentsOfDimension.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00634_InSearchOfFragmentsOfDimension/Q00634_InSearchOfFragmentsOfDimension.java
@@ -20,9 +20,12 @@ package com.l2jserver.datapack.quests.Q00634_InSearchOfFragmentsOfDimension;
 
 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;
 
+import static com.l2jserver.gameserver.model.quest.QuestDroplist.singleDropItem;
+
 /**
  * In Search of Fragments of Dimension (634)
  * @author Adry_85
@@ -30,24 +33,10 @@ import com.l2jserver.gameserver.model.quest.QuestState;
 public final class Q00634_InSearchOfFragmentsOfDimension extends Quest {
 	// NPCs
 	private static final int[] DIMENSIONAL_GATE_KEEPER = {
-		31494,
-		31495,
-		31496,
-		31497,
-		31498,
-		31499,
-		31500,
-		31501,
-		31502,
-		31503,
-		31504,
-		31505,
-		31506,
-		31507
+		31494, 31495, 31496, 31497, 31498, 31499, 31500, 31501, 31502, 31503, 31504, 31505, 31506, 31507
 	};
-	
 	// Item
-	private static final int DIMENSIONAL_FRAGMENT = 7079;
+	private static final QuestItemChanceHolder DIMENSIONAL_FRAGMENT = new QuestItemChanceHolder(7079, 10.0);
 	// Misc
 	private static final int MIN_LEVEL = 20;
 	// Monsters
@@ -146,10 +135,8 @@ public final class Q00634_InSearchOfFragmentsOfDimension extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(player, -1, 3, npc);
 		if (qs != null) {
-			final int i0 = (int) ((0.15 * npc.getLevel()) + 1.6);
-			if (getRandom(100) < 10) {
-				giveItemRandomly(qs.getPlayer(), npc, DIMENSIONAL_FRAGMENT, i0, 0, 1.0, true);
-			}
+			final long amount = (long) ((0.15 * npc.getLevel()) + 1.6);
+			giveItemRandomly(qs.getPlayer(), npc, singleDropItem(DIMENSIONAL_FRAGMENT, amount), 0L, true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00637_ThroughOnceMore/Q00637_ThroughOnceMore.java b/src/main/java/com/l2jserver/datapack/quests/Q00637_ThroughOnceMore/Q00637_ThroughOnceMore.java
index d6f4f4f95d..6c602f2352 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00637_ThroughOnceMore/Q00637_ThroughOnceMore.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00637_ThroughOnceMore/Q00637_ThroughOnceMore.java
@@ -18,11 +18,9 @@
  */
 package com.l2jserver.datapack.quests.Q00637_ThroughOnceMore;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -33,25 +31,26 @@ import com.l2jserver.gameserver.model.quest.State;
  * @author DS
  */
 public final class Q00637_ThroughOnceMore extends Quest {
+	// NPCs
 	private static final int FLAURON = 32010;
+	// Monsters
 	private static final int[] MOBS = {
 		21565,
 		21566,
 		21567
 	};
+	// Items
 	private static final int VISITOR_MARK = 8064;
 	private static final int FADED_MARK = 8065;
-	private static final int NECRO_HEART = 8066;
 	private static final int MARK = 8067;
-	
-	private static final double DROP_CHANCE = 90;
-	
+	private static final QuestItemChanceHolder NECRO_HEART = new QuestItemChanceHolder(8066, 90.0, 10L);
+
 	public Q00637_ThroughOnceMore() {
 		super(637, Q00637_ThroughOnceMore.class.getSimpleName(), "Through the Gate Once More");
 		addStartNpc(FLAURON);
 		addTalkId(FLAURON);
 		addKillId(MOBS);
-		registerQuestItems(NECRO_HEART);
+		registerQuestItems(NECRO_HEART.getId());
 	}
 	
 	@Override
@@ -72,26 +71,8 @@ public final class Q00637_ThroughOnceMore extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState st = getQuestState(player, false);
-		if ((st != null) && (st.getState() == State.STARTED)) {
-			final long count = st.getQuestItemsCount(NECRO_HEART);
-			if (count < 10) {
-				int chance = (int) (rates().getRateQuestDrop() * DROP_CHANCE);
-				int numItems = chance / 100;
-				chance = chance % 100;
-				if (getRandom(100) < chance) {
-					numItems++;
-				}
-				if (numItems > 0) {
-					if ((count + numItems) >= 10) {
-						numItems = 10 - (int) count;
-						st.setCond(2, true);
-					} else {
-						st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-					}
-					
-					st.giveItems(NECRO_HEART, numItems);
-				}
-			}
+		if ((st != null) && st.isStarted() && giveItemRandomly(st.getPlayer(), npc, NECRO_HEART, true)) {
+			st.setCond(2);
 		}
 		return null;
 	}
@@ -121,8 +102,8 @@ public final class Q00637_ThroughOnceMore extends Quest {
 			st.exitQuest(true);
 			return "32010-01.htm";
 		} else if (id == State.STARTED) {
-			if ((st.isCond(2)) && (st.getQuestItemsCount(NECRO_HEART) == 10)) {
-				st.takeItems(NECRO_HEART, 10);
+			if ((st.isCond(2)) && hasItemsAtLimit(st.getPlayer(), NECRO_HEART)) {
+				st.takeItems(NECRO_HEART.getId(), 10);
 				st.takeItems(FADED_MARK, 1);
 				st.giveItems(MARK, 1);
 				st.giveItems(8273, 10);
@@ -133,4 +114,4 @@ public final class Q00637_ThroughOnceMore extends Quest {
 		}
 		return getNoQuestMsg(player);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00638_SeekersOfTheHolyGrail/Q00638_SeekersOfTheHolyGrail.java b/src/main/java/com/l2jserver/datapack/quests/Q00638_SeekersOfTheHolyGrail/Q00638_SeekersOfTheHolyGrail.java
index 7169194dbc..b4744b1e6b 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00638_SeekersOfTheHolyGrail/Q00638_SeekersOfTheHolyGrail.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00638_SeekersOfTheHolyGrail/Q00638_SeekersOfTheHolyGrail.java
@@ -18,13 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00638_SeekersOfTheHolyGrail;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
+import com.l2jserver.gameserver.model.holders.ItemHolder;
 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;
 
 /**
@@ -32,35 +31,6 @@ import com.l2jserver.gameserver.model.quest.QuestState;
  * @author netvirus
  */
 public final class Q00638_SeekersOfTheHolyGrail extends Quest {
-	private static class DropInfo extends ItemChanceHolder {
-		private final int _keyId;
-		private final int _keyChance;
-		private final int _keyCount;
-		
-		public DropInfo(int itemId, double chance) {
-			this(itemId, chance, 0, 0, 0);
-		}
-		
-		public DropInfo(int itemId, double chance, int keyId, int keyChance, int count) {
-			super(itemId, chance);
-			_keyId = keyId;
-			_keyChance = keyChance;
-			_keyCount = count;
-		}
-		
-		public int getKeyId() {
-			return _keyId;
-		}
-		
-		public int getKeyChance() {
-			return _keyChance;
-		}
-		
-		public int getKeyCount() {
-			return _keyCount;
-		}
-	}
-	
 	// NPC
 	private static final int INNOCENTIN = 31328;
 	// Items
@@ -74,65 +44,70 @@ public final class Q00638_SeekersOfTheHolyGrail extends Quest {
 	// Rewards
 	private static final int SCROLL_ENCHANT_W_S = 959;
 	private static final int SCROLL_ENCHANT_A_S = 960;
-	// Mobs
-	private static final Map<Integer, DropInfo> MOBS_DROP_CHANCES = new HashMap<>();
-	static {
-		MOBS_DROP_CHANCES.put(22136, new DropInfo(TOTEM, 0.55)); // Gatekeeper Zombie
-		MOBS_DROP_CHANCES.put(22137, new DropInfo(TOTEM, 0.06)); // Penance Guard
-		MOBS_DROP_CHANCES.put(22138, new DropInfo(TOTEM, 0.06)); // Chapel Guard
-		MOBS_DROP_CHANCES.put(22139, new DropInfo(TOTEM, 0.54)); // Old Aristocrat's Soldier
-		MOBS_DROP_CHANCES.put(22140, new DropInfo(TOTEM, 0.54)); // Zombie Worker
-		MOBS_DROP_CHANCES.put(22141, new DropInfo(TOTEM, 0.55)); // Forgotten Victim
-		MOBS_DROP_CHANCES.put(22142, new DropInfo(TOTEM, 0.54)); // Triol's Layperson
-		MOBS_DROP_CHANCES.put(22143, new DropInfo(TOTEM, 0.62, CHAPEL_KEY, 100, 1)); // Triol's Believer
-		MOBS_DROP_CHANCES.put(22144, new DropInfo(TOTEM, 0.54)); // Resurrected Temple Knight
-		MOBS_DROP_CHANCES.put(22145, new DropInfo(TOTEM, 0.53)); // Ritual Sacrifice
-		MOBS_DROP_CHANCES.put(22146, new DropInfo(TOTEM, 0.54, KEY_OF_DARKNESS, 10, 1)); // Triol's Priest
-		MOBS_DROP_CHANCES.put(22147, new DropInfo(TOTEM, 0.55)); // Ritual Offering
-		MOBS_DROP_CHANCES.put(22148, new DropInfo(TOTEM, 0.45)); // Triol's Believer
-		MOBS_DROP_CHANCES.put(22149, new DropInfo(TOTEM, 0.54, ANTEROOM_KEY, 100, 6)); // Ritual Offering
-		MOBS_DROP_CHANCES.put(22150, new DropInfo(TOTEM, 0.46)); // Triol's Believer
-		MOBS_DROP_CHANCES.put(22151, new DropInfo(TOTEM, 0.62, KEY_OF_DARKNESS, 10, 1)); // Triol's Priest
-		MOBS_DROP_CHANCES.put(22152, new DropInfo(TOTEM, 0.55)); // Temple Guard
-		MOBS_DROP_CHANCES.put(22153, new DropInfo(TOTEM, 0.54)); // Temple Guard Captain
-		MOBS_DROP_CHANCES.put(22154, new DropInfo(TOTEM, 0.53)); // Ritual Sacrifice
-		MOBS_DROP_CHANCES.put(22155, new DropInfo(TOTEM, 0.75)); // Triol's High Priest
-		MOBS_DROP_CHANCES.put(22156, new DropInfo(TOTEM, 0.67)); // Triol's Priest
-		MOBS_DROP_CHANCES.put(22157, new DropInfo(TOTEM, 0.66)); // Triol's Priest
-		MOBS_DROP_CHANCES.put(22158, new DropInfo(TOTEM, 0.67)); // Triol's Believer
-		MOBS_DROP_CHANCES.put(22159, new DropInfo(TOTEM, 0.75)); // Triol's High Priest
-		MOBS_DROP_CHANCES.put(22160, new DropInfo(TOTEM, 0.67)); // Triol's Priest
-		MOBS_DROP_CHANCES.put(22161, new DropInfo(TOTEM, 0.78)); // Ritual Sacrifice
-		MOBS_DROP_CHANCES.put(22162, new DropInfo(TOTEM, 0.67)); // Triol's Believer
-		MOBS_DROP_CHANCES.put(22163, new DropInfo(TOTEM, 0.87)); // Triol's High Priest
-		MOBS_DROP_CHANCES.put(22164, new DropInfo(TOTEM, 0.67)); // Triol's Believer
-		MOBS_DROP_CHANCES.put(22165, new DropInfo(TOTEM, 0.66)); // Triol's Priest
-		MOBS_DROP_CHANCES.put(22166, new DropInfo(TOTEM, 0.66)); // Triol's Believer
-		MOBS_DROP_CHANCES.put(22167, new DropInfo(TOTEM, 0.75)); // Triol's High Priest
-		MOBS_DROP_CHANCES.put(22168, new DropInfo(TOTEM, 0.66)); // Triol's Priest
-		MOBS_DROP_CHANCES.put(22169, new DropInfo(TOTEM, 0.78)); // Ritual Sacrifice
-		MOBS_DROP_CHANCES.put(22170, new DropInfo(TOTEM, 0.67)); // Triol's Believer
-		MOBS_DROP_CHANCES.put(22171, new DropInfo(TOTEM, 0.87)); // Triol's High Priest
-		MOBS_DROP_CHANCES.put(22172, new DropInfo(TOTEM, 0.78)); // Ritual Sacrifice
-		MOBS_DROP_CHANCES.put(22173, new DropInfo(TOTEM, 0.66)); // Triol's Priest
-		MOBS_DROP_CHANCES.put(22174, new DropInfo(TOTEM, 0.67)); // Triol's Priest
-		MOBS_DROP_CHANCES.put(22175, new DropInfo(TOTEM, 0.03)); // Andreas' Captain of the Royal Guard
-		MOBS_DROP_CHANCES.put(22176, new DropInfo(TOTEM, 0.03)); // Andreas' Royal Guards
-		MOBS_DROP_CHANCES.put(22188, new DropInfo(TOTEM, 0.03)); // Andreas' Captain of the Royal Guard
-		MOBS_DROP_CHANCES.put(22189, new DropInfo(TOTEM, 0.03)); // Andreas' Royal Guards
-		MOBS_DROP_CHANCES.put(22190, new DropInfo(TOTEM, 0.03)); // Ritual Sacrifice
-		MOBS_DROP_CHANCES.put(22191, new DropInfo(TOTEM, 0.03)); // Andreas' Captain of the Royal Guard
-		MOBS_DROP_CHANCES.put(22192, new DropInfo(TOTEM, 0.03)); // Andreas' Royal Guards
-		MOBS_DROP_CHANCES.put(22193, new DropInfo(TOTEM, 0.03)); // Andreas' Royal Guards
-		MOBS_DROP_CHANCES.put(22194, new DropInfo(TOTEM, 0.03)); // Penance Guard
-		MOBS_DROP_CHANCES.put(22194, new DropInfo(TOTEM, 0.03)); // Ritual Sacrifice
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22136, TOTEM, 55.0) // Gatekeeper Zombie
+			.addSingleDrop(22137, TOTEM, 6.0) // Penance Guard
+			.addSingleDrop(22138, TOTEM, 6.0) // Chapel Guard
+			.addSingleDrop(22139, TOTEM, 54.0) // Old Aristocrat's Soldier
+			.addSingleDrop(22140, TOTEM, 54.0) // Zombie Worker
+			.addSingleDrop(22141, TOTEM, 55.0) // Forgotten Victim
+			.addSingleDrop(22142, TOTEM, 54.0) // Triol's Layperson
+			.addSingleDrop(22143, TOTEM, 62.0) // Triol's Believer
+			.addSingleDrop(22144, TOTEM, 54.0) // Resurrected Temple Knight
+			.addSingleDrop(22145, TOTEM, 53.0) // Ritual Sacrifice
+			.addSingleDrop(22146, TOTEM, 54.0) // Triol's Priest
+			.addSingleDrop(22147, TOTEM, 55.0) // Ritual Offering
+			.addSingleDrop(22148, TOTEM, 45.0) // Triol's Believer
+			.addSingleDrop(22149, TOTEM, 54.0) // Ritual Offering
+			.addSingleDrop(22150, TOTEM, 46.0) // Triol's Believer
+			.addSingleDrop(22151, TOTEM, 62.0) // Triol's Priest
+			.addSingleDrop(22152, TOTEM, 55.0) // Temple Guard
+			.addSingleDrop(22153, TOTEM, 54.0) // Temple Guard Captain
+			.addSingleDrop(22154, TOTEM, 53.0) // Ritual Sacrifice
+			.addSingleDrop(22155, TOTEM, 75.0) // Triol's High Priest
+			.addSingleDrop(22156, TOTEM, 67.0) // Triol's Priest
+			.addSingleDrop(22157, TOTEM, 66.0) // Triol's Priest
+			.addSingleDrop(22158, TOTEM, 67.0) // Triol's Believer
+			.addSingleDrop(22159, TOTEM, 75.0) // Triol's High Priest
+			.addSingleDrop(22160, TOTEM, 67.0) // Triol's Priest
+			.addSingleDrop(22161, TOTEM, 78.0) // Ritual Sacrifice
+			.addSingleDrop(22162, TOTEM, 67.0) // Triol's Believer
+			.addSingleDrop(22163, TOTEM, 87.0) // Triol's High Priest
+			.addSingleDrop(22164, TOTEM, 67.0) // Triol's Believer
+			.addSingleDrop(22165, TOTEM, 66.0) // Triol's Priest
+			.addSingleDrop(22166, TOTEM, 66.0) // Triol's Believer
+			.addSingleDrop(22167, TOTEM, 75.0) // Triol's High Priest
+			.addSingleDrop(22168, TOTEM, 66.0) // Triol's Priest
+			.addSingleDrop(22169, TOTEM, 78.0) // Ritual Sacrifice
+			.addSingleDrop(22170, TOTEM, 67.0) // Triol's Believer
+			.addSingleDrop(22171, TOTEM, 87.0) // Triol's High Priest
+			.addSingleDrop(22172, TOTEM, 78.0) // Ritual Sacrifice
+			.addSingleDrop(22173, TOTEM, 66.0) // Triol's Priest
+			.addSingleDrop(22174, TOTEM, 67.0) // Triol's Priest
+			.addSingleDrop(22175, TOTEM, 3.0) // Andreas' Captain of the Royal Guard
+			.addSingleDrop(22176, TOTEM, 3.0) // Andreas' Royal Guards
+			.addSingleDrop(22188, TOTEM, 3.0) // Andreas' Captain of the Royal Guard
+			.addSingleDrop(22189, TOTEM, 3.0) // Andreas' Royal Guards
+			.addSingleDrop(22190, TOTEM, 3.0) // Ritual Sacrifice
+			.addSingleDrop(22191, TOTEM, 3.0) // Andreas' Captain of the Royal Guard
+			.addSingleDrop(22192, TOTEM, 3.0) // Andreas' Royal Guards
+			.addSingleDrop(22193, TOTEM, 3.0) // Andreas' Royal Guards
+			.addSingleDrop(22194, TOTEM, 3.0) // Penance Guard
+			.addSingleDrop(22195, TOTEM, 3.0) // Ritual Sacrifice
+			.build();
+	private static final QuestDroplist DROPLIST_KEYS = QuestDroplist.builder()
+			.addSingleDrop(22143, CHAPEL_KEY, 1) // Triol's Believer
+			.addSingleDrop(22146, KEY_OF_DARKNESS, 1, 10.0) // Triol's Priest
+			.addSingleDrop(22149, ANTEROOM_KEY, 6) // Ritual Offering
+			.addSingleDrop(22151, KEY_OF_DARKNESS, 1, 10.0) // Triol's Priest
+			.build();
 	
 	public Q00638_SeekersOfTheHolyGrail() {
 		super(638, Q00638_SeekersOfTheHolyGrail.class.getSimpleName(), "Seekers Of The Holy Grail");
 		addStartNpc(INNOCENTIN);
 		addTalkId(INNOCENTIN);
-		addKillId(MOBS_DROP_CHANCES.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(TOTEM);
 	}
 	
@@ -190,10 +165,11 @@ public final class Q00638_SeekersOfTheHolyGrail extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			final DropInfo info = MOBS_DROP_CHANCES.get(npc.getId());
-			if (giveItemRandomly(qs.getPlayer(), npc, info.getId(), 1, 0, info.getChance(), true)) {
-				if ((info.getKeyId() > 0) && (getRandom(100) < info.getKeyChance())) {
-					npc.dropItem(qs.getPlayer(), info.getKeyId(), info.getKeyCount());
+			if (giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)) {
+				QuestDropInfo keyDropInfo = DROPLIST_KEYS.get(npc);
+				if (keyDropInfo != null) {
+					ItemHolder keyItemHolder = keyDropInfo.drop().calculateDrops(npc, qs.getPlayer()).get(0);
+					npc.dropItem(qs.getPlayer(), keyItemHolder.getId(), keyItemHolder.getCount());
 				}
 			}
 		}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00642_APowerfulPrimevalCreature/Q00642_APowerfulPrimevalCreature.java b/src/main/java/com/l2jserver/datapack/quests/Q00642_APowerfulPrimevalCreature/Q00642_APowerfulPrimevalCreature.java
index 639a48b092..19b3f8a144 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00642_APowerfulPrimevalCreature/Q00642_APowerfulPrimevalCreature.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00642_APowerfulPrimevalCreature/Q00642_APowerfulPrimevalCreature.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00642_APowerfulPrimevalCreature;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -33,34 +31,26 @@ import com.l2jserver.gameserver.model.quest.QuestState;
 public class Q00642_APowerfulPrimevalCreature extends Quest {
 	// NPC
 	private static final int DINN = 32105;
+	// Mobs
+	private static final int ANCIENT_EGG = 18344;
 	// Items
 	private static final int DINOSAUR_TISSUE = 8774;
 	private static final int DINOSAUR_EGG = 8775;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.bulkAddSingleDrop(DINOSAUR_TISSUE, 30.9)
+				.withNpcs(22196, 22197, 22198, 22199, 22218, 22223).build() // Velociraptor, Pterosaur
+			.bulkAddSingleDrop(DINOSAUR_TISSUE, 98.8).withNpcs(22215, 22216, 22217).build() // Tyrannosaurus
+			.addSingleDrop(ANCIENT_EGG, DINOSAUR_EGG) // Ancient Egg
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 75;
-	// Mobs
-	private static final int ANCIENT_EGG = 18344;
-	
-	private static final Map<Integer, Double> MOBS_TISSUE = new HashMap<>();
-	
-	static {
-		MOBS_TISSUE.put(22196, 0.309); // Velociraptor
-		MOBS_TISSUE.put(22197, 0.309); // Velociraptor
-		MOBS_TISSUE.put(22198, 0.309); // Velociraptor
-		MOBS_TISSUE.put(22199, 0.309); // Pterosaur
-		MOBS_TISSUE.put(22215, 0.988); // Tyrannosaurus
-		MOBS_TISSUE.put(22216, 0.988); // Tyrannosaurus
-		MOBS_TISSUE.put(22217, 0.988); // Tyrannosaurus
-		MOBS_TISSUE.put(22218, 0.309); // Velociraptor
-		MOBS_TISSUE.put(22223, 0.309); // Velociraptor
-	}
-	
+
 	public Q00642_APowerfulPrimevalCreature() {
 		super(642, Q00642_APowerfulPrimevalCreature.class.getSimpleName(), "A Powerful Primeval Creature");
 		addStartNpc(DINN);
 		addTalkId(DINN);
-		addKillId(ANCIENT_EGG);
-		addKillId(MOBS_TISSUE.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(DINOSAUR_TISSUE, DINOSAUR_EGG);
 	}
 	
@@ -109,17 +99,10 @@ public class Q00642_APowerfulPrimevalCreature extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		
-		if (qs == null) {
-			return null;
-		}
-		
-		int npcId = npc.getId();
-		
-		if (MOBS_TISSUE.containsKey(npcId)) {
-			giveItemRandomly(qs.getPlayer(), npc, DINOSAUR_TISSUE, 1, 0, MOBS_TISSUE.get(npcId), true);
-		} else {
-			giveItemRandomly(qs.getPlayer(), npc, DINOSAUR_EGG, 1, 0, 1.0, true);
+		if (qs != null) {
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
+
 		return super.onKill(npc, killer, isSummon);
 	}
 	
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00643_RiseAndFallOfTheElrokiTribe/Q00643_RiseAndFallOfTheElrokiTribe.java b/src/main/java/com/l2jserver/datapack/quests/Q00643_RiseAndFallOfTheElrokiTribe/Q00643_RiseAndFallOfTheElrokiTribe.java
index 74aafabf35..30f51b4915 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00643_RiseAndFallOfTheElrokiTribe/Q00643_RiseAndFallOfTheElrokiTribe.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00643_RiseAndFallOfTheElrokiTribe/Q00643_RiseAndFallOfTheElrokiTribe.java
@@ -18,15 +18,13 @@
  */
 package com.l2jserver.datapack.quests.Q00643_RiseAndFallOfTheElrokiTribe;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
 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;
-import com.l2jserver.gameserver.util.Util;
 
 /**
  * Rise and Fall of the Elroki Tribe (643)
@@ -38,11 +36,20 @@ public class Q00643_RiseAndFallOfTheElrokiTribe extends Quest {
 	private static final int KARAKAWEI = 32117;
 	// Item
 	private static final int BONES_OF_A_PLAINS_DINOSAUR = 8776;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.bulkAddSingleDrop(BONES_OF_A_PLAINS_DINOSAUR, 111.6)
+				.withNpcs(22200, 22201, 22202, 22219, 22224) // Ornithomimus
+				.withNpcs(22204, 22205, 22220, 22225) // Deinonychus
+				.withNpcs(22208, 22209, 22210, 22221, 22226) // Pachycephalosaurus
+				.withNpcs(22211, 22212, 22213, 22222, 22227).build() // Wild Strider
+			.bulkAddSingleDrop(BONES_OF_A_PLAINS_DINOSAUR, 36.0)
+				.withNpcs(22742, 22744) // Ornithomimus
+				.withNpcs(22743, 22745).build() // Deinonychus
+			.addSingleDrop(22203, BONES_OF_A_PLAINS_DINOSAUR, 55.8) // Deinonychus
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 75;
-	private static final int CHANCE_MOBS1 = 116;
-	private static final int CHANCE_MOBS2 = 360;
-	private static final int CHANCE_DEINO = 558;
 	private boolean isFirstTalk = true;
 	// Rewards
 	private static final int[] PIECE = {
@@ -58,45 +65,12 @@ public class Q00643_RiseAndFallOfTheElrokiTribe extends Quest {
 		8721, // Cabrio's Hand Head
 		8722, // Daimon Crystal Fragment
 	};
-	// Mobs
-	private static final int[] MOBS1 = {
-		22200, // Ornithomimus
-		22201, // Ornithomimus
-		22202, // Ornithomimus
-		22204, // Deinonychus
-		22205, // Deinonychus
-		22208, // Pachycephalosaurus
-		22209, // Pachycephalosaurus
-		22210, // Pachycephalosaurus
-		22211, // Wild Strider
-		22212, // Wild Strider
-		22213, // Wild Strider
-		22219, // Ornithomimus
-		22220, // Deinonychus
-		22221, // Pachycephalosaurus
-		22222, // Wild Strider
-		22224, // Ornithomimus
-		22225, // Deinonychus
-		22226, // Pachycephalosaurus
-		22227, // Wild Strider
-	};
-	
-	private static final int[] MOBS2 = {
-		22742, // Ornithomimus
-		22743, // Deinonychus
-		22744, // Ornithomimus
-		22745, // Deinonychus
-	};
-	
-	private static final int DEINONYCHUS = 22203;
 	
 	public Q00643_RiseAndFallOfTheElrokiTribe() {
 		super(643, Q00643_RiseAndFallOfTheElrokiTribe.class.getSimpleName(), "Rise and Fall of the Elroki Tribe");
 		addStartNpc(SINGSING);
 		addTalkId(SINGSING, KARAKAWEI);
-		addKillId(MOBS1);
-		addKillId(MOBS2);
-		addKillId(DEINONYCHUS);
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(BONES_OF_A_PLAINS_DINOSAUR);
 	}
 	
@@ -162,38 +136,9 @@ public class Q00643_RiseAndFallOfTheElrokiTribe extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember == null) {
-			return super.onKill(npc, player, isSummon);
-		}
-		
-		final QuestState st = getQuestState(partyMember, false);
-		int npcId = npc.getId();
-		
-		if (Util.contains(MOBS1, npcId)) {
-			double chance = CHANCE_MOBS1 * rates().getRateQuestDrop();
-			if (getRandom(1000) < chance) {
-				st.rewardItems(BONES_OF_A_PLAINS_DINOSAUR, 2);
-			} else {
-				st.rewardItems(BONES_OF_A_PLAINS_DINOSAUR, 1);
-			}
-			st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-		}
-		
-		if (Util.contains(MOBS2, npcId)) {
-			double chance = CHANCE_MOBS2 * rates().getRateQuestDrop();
-			if (getRandom(1000) < chance) {
-				st.rewardItems(BONES_OF_A_PLAINS_DINOSAUR, 1);
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
-		}
-		
-		if (npcId == DEINONYCHUS) {
-			double chance = CHANCE_DEINO * rates().getRateQuestDrop();
-			if (getRandom(1000) < chance) {
-				st.rewardItems(BONES_OF_A_PLAINS_DINOSAUR, 1);
-				st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-			}
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00644_GraveRobberAnnihilation/Q00644_GraveRobberAnnihilation.java b/src/main/java/com/l2jserver/datapack/quests/Q00644_GraveRobberAnnihilation/Q00644_GraveRobberAnnihilation.java
index d004a3b2d9..3c33bb79ca 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00644_GraveRobberAnnihilation/Q00644_GraveRobberAnnihilation.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00644_GraveRobberAnnihilation/Q00644_GraveRobberAnnihilation.java
@@ -18,16 +18,18 @@
  */
 package com.l2jserver.datapack.quests.Q00644_GraveRobberAnnihilation;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
+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;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Grave Robber Annihilation (644)
  * @author netvirus
@@ -36,22 +38,21 @@ public final class Q00644_GraveRobberAnnihilation extends Quest {
 	// NPC
 	private static final int KARUDA = 32017;
 	// Item
-	private static final int ORC_GOODS = 8088;
+	private static final QuestItemChanceHolder ORC_GOODS = new QuestItemChanceHolder(8088, 120L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22003, ORC_GOODS, 71.4) // Grave Robber Scout
+			.addSingleDrop(22004, ORC_GOODS, 84.1) // Grave Robber Lookout
+			.addSingleDrop(22005, ORC_GOODS, 77.8) // Grave Robber Ranger
+			.addSingleDrop(22006, ORC_GOODS, 74.6) // Grave Robber Guard
+			.addSingleDrop(22008, ORC_GOODS, 81.0) // Grave Robber Fighter
+			.build();
 	// Misc
 	private static final int MIN_LVL = 20;
 	private static final int ORC_GOODS_REQUIRED_COUNT = 120;
-	// Monsters
-	private static final Map<Integer, Double> MONSTER_DROP_CHANCES = new HashMap<>();
 	// Rewards
 	private static final Map<String, ItemHolder> REWARDS = new HashMap<>();
-	
 	static {
-		MONSTER_DROP_CHANCES.put(22003, 0.714); // Grave Robber Scout
-		MONSTER_DROP_CHANCES.put(22004, 0.841); // Grave Robber Lookout
-		MONSTER_DROP_CHANCES.put(22005, 0.778); // Grave Robber Ranger
-		MONSTER_DROP_CHANCES.put(22006, 0.746); // Grave Robber Guard
-		MONSTER_DROP_CHANCES.put(22008, 0.810); // Grave Robber Fighter
-		
 		REWARDS.put("varnish", new ItemHolder(1865, 30)); // Varnish
 		REWARDS.put("animalskin", new ItemHolder(1867, 40)); // Animal Skin
 		REWARDS.put("animalbone", new ItemHolder(1872, 40)); // Animal Bone
@@ -64,8 +65,8 @@ public final class Q00644_GraveRobberAnnihilation extends Quest {
 		super(644, Q00644_GraveRobberAnnihilation.class.getSimpleName(), "Grave Robber Annihilation");
 		addStartNpc(KARUDA);
 		addTalkId(KARUDA);
-		addKillId(MONSTER_DROP_CHANCES.keySet());
-		registerQuestItems(ORC_GOODS);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(ORC_GOODS.getId());
 	}
 	
 	@Override
@@ -85,7 +86,7 @@ public final class Q00644_GraveRobberAnnihilation extends Quest {
 				break;
 			}
 			case "32017-06.html": {
-				if (st.isCond(2) && (st.getQuestItemsCount(ORC_GOODS) >= ORC_GOODS_REQUIRED_COUNT)) {
+				if (st.isCond(2) && hasItemsAtLimit(st.getPlayer(), ORC_GOODS)) {
 					htmltext = event;
 				}
 				break;
@@ -111,8 +112,8 @@ public final class Q00644_GraveRobberAnnihilation extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, 1, 3, npc);
-		if ((qs != null) && qs.giveItemRandomly(npc, ORC_GOODS, 1, ORC_GOODS_REQUIRED_COUNT, MONSTER_DROP_CHANCES.get(npc.getId()), true)) {
-			qs.setCond(2, true);
+		if ((qs != null) && giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true)) {
+			qs.setCond(2);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
@@ -127,7 +128,7 @@ public final class Q00644_GraveRobberAnnihilation extends Quest {
 				break;
 			}
 			case State.STARTED: {
-				if (st.isCond(2) && (st.getQuestItemsCount(ORC_GOODS) >= ORC_GOODS_REQUIRED_COUNT)) {
+				if (st.isCond(2) && hasItemsAtLimit(st.getPlayer(), ORC_GOODS)) {
 					htmltext = "32017-04.html";
 				} else {
 					htmltext = "32017-05.html";
@@ -137,4 +138,4 @@ public final class Q00644_GraveRobberAnnihilation extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00648_AnIceMerchantsDream/Q00648_AnIceMerchantsDream.java b/src/main/java/com/l2jserver/datapack/quests/Q00648_AnIceMerchantsDream/Q00648_AnIceMerchantsDream.java
index 9ab25ce8f6..27665d23c3 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00648_AnIceMerchantsDream/Q00648_AnIceMerchantsDream.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00648_AnIceMerchantsDream/Q00648_AnIceMerchantsDream.java
@@ -18,14 +18,13 @@
  */
 package com.l2jserver.datapack.quests.Q00648_AnIceMerchantsDream;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00115_TheOtherSideOfTruth.Q00115_TheOtherSideOfTruth;
 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.QuestDroplist.QuestDropInfo;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
 /**
@@ -33,24 +32,6 @@ import com.l2jserver.gameserver.model.quest.QuestState;
  * @author netvirus, Adry_85
  */
 public final class Q00648_AnIceMerchantsDream extends Quest {
-	private static class DropInfo {
-		private final double _firstChance;
-		private final double _secondChance;
-		
-		public DropInfo(double firstChance, double secondChance) {
-			_firstChance = firstChance;
-			_secondChance = secondChance;
-		}
-		
-		public double getFirstChance() {
-			return _firstChance;
-		}
-		
-		public double getSecondChance() {
-			return _secondChance;
-		}
-	}
-	
 	// NPCs
 	private static final int RAFFORTY = 32020;
 	private static final int ICE_SHELF = 32023;
@@ -58,37 +39,36 @@ public final class Q00648_AnIceMerchantsDream extends Quest {
 	private static final int SILVER_HEMOCYTE = 8057;
 	private static final int SILVER_ICE_CRYSTAL = 8077;
 	private static final int BLACK_ICE_CRYSTAL = 8078;
+	// Droplists
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22080, SILVER_ICE_CRYSTAL, 28.5).addSingleDrop(22080, SILVER_HEMOCYTE, 4.8) // Massive Maze Bandersnatch
+			.addSingleDrop(22081, SILVER_ICE_CRYSTAL, 44.3) // Lost Watcher
+			.addSingleDrop(22082, SILVER_ICE_CRYSTAL, 51.0) // Elder Lost Watcher
+			.addSingleDrop(22083, SILVER_ICE_CRYSTAL, 47.7).addSingleDrop(22083, SILVER_HEMOCYTE, 4.9) // Baby Panthera
+			.addSingleDrop(22084, SILVER_ICE_CRYSTAL, 47.7).addSingleDrop(22084, SILVER_HEMOCYTE, 4.9) // Panthera
+			.addSingleDrop(22085, SILVER_ICE_CRYSTAL, 42.0).addSingleDrop(22085, SILVER_HEMOCYTE, 4.3) // Lost Gargoyle
+			.addSingleDrop(22086, SILVER_ICE_CRYSTAL, 49.0).addSingleDrop(22086, SILVER_HEMOCYTE, 5.0) // Lost Gargoyle Youngling
+			.addSingleDrop(22087, SILVER_ICE_CRYSTAL, 78.7).addSingleDrop(22087, SILVER_HEMOCYTE, 8.1) // Pronghorn Spirit
+			.addSingleDrop(22088, SILVER_ICE_CRYSTAL, 48.0).addSingleDrop(22088, SILVER_HEMOCYTE, 4.9) // Pronghorn
+			.addSingleDrop(22089, SILVER_ICE_CRYSTAL, 55.0).addSingleDrop(22089, SILVER_HEMOCYTE, 5.6) // Ice Tarantula
+			.addSingleDrop(22090, SILVER_ICE_CRYSTAL, 57.0).addSingleDrop(22090, SILVER_HEMOCYTE, 5.8) // Frost Tarantula
+			.addSingleDrop(22091, SILVER_ICE_CRYSTAL, 62.3) // Lost Iron Golem
+			.addSingleDrop(22092, SILVER_ICE_CRYSTAL, 62.3) // Frost Iron Golem
+			.addSingleDrop(22093, SILVER_ICE_CRYSTAL, 91.0).addSingleDrop(22093, SILVER_HEMOCYTE, 9.3) // Lost Buffalo
+			.addSingleDrop(22094, SILVER_ICE_CRYSTAL, 55.3).addSingleDrop(22094, SILVER_HEMOCYTE, 5.7) // Frost Buffalo
+			.addSingleDrop(22095, SILVER_ICE_CRYSTAL, 59.3).addSingleDrop(22095, SILVER_HEMOCYTE, 6.1) // Ursus Cub
+			.addSingleDrop(22096, SILVER_ICE_CRYSTAL, 59.3).addSingleDrop(22096, SILVER_HEMOCYTE, 6.1) // Ursus
+			.addSingleDrop(22097, SILVER_ICE_CRYSTAL, 69.3).addSingleDrop(22097, SILVER_HEMOCYTE, 7.1) // Lost Yeti
+			.addSingleDrop(22098, SILVER_ICE_CRYSTAL, 71.7).addSingleDrop(22098, SILVER_HEMOCYTE, 7.4) // Frost Yeti
+			.build();
 	// Misc
 	private static final int MIN_LVL = 53;
-	// Monsters
-	private static final Map<Integer, DropInfo> MONSTERS = new HashMap<>();
-	static {
-		MONSTERS.put(22080, new DropInfo(0.285, 0.048)); // Massive Maze Bandersnatch
-		MONSTERS.put(22081, new DropInfo(0.443, 0.0)); // Lost Watcher
-		MONSTERS.put(22082, new DropInfo(0.510, 0.0)); // Elder Lost Watcher
-		MONSTERS.put(22083, new DropInfo(0.477, 0.049)); // Baby Panthera
-		MONSTERS.put(22084, new DropInfo(0.477, 0.049)); // Panthera
-		MONSTERS.put(22085, new DropInfo(0.420, 0.043)); // Lost Gargoyle
-		MONSTERS.put(22086, new DropInfo(0.490, 0.050)); // Lost Gargoyle Youngling
-		MONSTERS.put(22087, new DropInfo(0.787, 0.081)); // Pronghorn Spirit
-		MONSTERS.put(22088, new DropInfo(0.480, 0.049)); // Pronghorn
-		MONSTERS.put(22089, new DropInfo(0.550, 0.056)); // Ice Tarantula
-		MONSTERS.put(22090, new DropInfo(0.570, 0.058)); // Frost Tarantula
-		MONSTERS.put(22091, new DropInfo(0.623, 0.0)); // Lost Iron Golem
-		MONSTERS.put(22092, new DropInfo(0.623, 0.0)); // Frost Iron Golem
-		MONSTERS.put(22093, new DropInfo(0.910, 0.093)); // Lost Buffalo
-		MONSTERS.put(22094, new DropInfo(0.553, 0.057)); // Frost Buffalo
-		MONSTERS.put(22095, new DropInfo(0.593, 0.061)); // Ursus Cub
-		MONSTERS.put(22096, new DropInfo(0.593, 0.061)); // Ursus
-		MONSTERS.put(22097, new DropInfo(0.693, 0.071)); // Lost Yeti
-		MONSTERS.put(22098, new DropInfo(0.717, 0.074)); // Frost Yeti
-	}
-	
+
 	public Q00648_AnIceMerchantsDream() {
 		super(648, Q00648_AnIceMerchantsDream.class.getSimpleName(), "An Ice Merchants Dream");
 		addStartNpc(RAFFORTY);
 		addTalkId(RAFFORTY, ICE_SHELF);
-		addKillId(MONSTERS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(SILVER_HEMOCYTE, SILVER_ICE_CRYSTAL, BLACK_ICE_CRYSTAL);
 	}
 	
@@ -234,15 +214,15 @@ public final class Q00648_AnIceMerchantsDream extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState st = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (st != null) {
-			final DropInfo info = MONSTERS.get(npc.getId());
 			if (st.getCond() >= 1) {
-				giveItemRandomly(st.getPlayer(), npc, SILVER_ICE_CRYSTAL, 1, 0, info.getFirstChance(), true);
+				giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 			}
-			
-			if (info.getSecondChance() > 0) {
+
+			QuestDropInfo hemocyteDropInfo = DROPLIST.get(npc.getId(), SILVER_HEMOCYTE);
+			if (hemocyteDropInfo != null) {
 				final QuestState st2 = st.getPlayer().getQuestState(Q00115_TheOtherSideOfTruth.class.getSimpleName());
 				if ((st.getCond() >= 2) && (st2 != null) && st2.isCompleted()) {
-					giveItemRandomly(st.getPlayer(), npc, SILVER_HEMOCYTE, 1, 0, info.getSecondChance(), true);
+					giveItemRandomly(st.getPlayer(), npc, hemocyteDropInfo, true);
 				}
 			}
 		}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00654_JourneyToASettlement/Q00654_JourneyToASettlement.java b/src/main/java/com/l2jserver/datapack/quests/Q00654_JourneyToASettlement/Q00654_JourneyToASettlement.java
index c60d22d05d..d559a4cb5c 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00654_JourneyToASettlement/Q00654_JourneyToASettlement.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00654_JourneyToASettlement/Q00654_JourneyToASettlement.java
@@ -18,13 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00654_JourneyToASettlement;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.datapack.quests.Q00119_LastImperialPrince.Q00119_LastImperialPrince;
 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;
 
 /**
@@ -35,23 +34,23 @@ public final class Q00654_JourneyToASettlement extends Quest {
 	// NPC
 	private static final int NAMELESS_SPIRIT = 31453;
 	// Items
-	private static final int ANTELOPE_SKIN = 8072;
 	private static final int FRINTEZZAS_SCROLL = 8073;
+	private static final QuestItemChanceHolder ANTELOPE_SKIN = new QuestItemChanceHolder(8072, 1L);
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21294, ANTELOPE_SKIN, 84.0) // Canyon Antelope
+			.addSingleDrop(21295, ANTELOPE_SKIN, 89.3) // Canyon Antelope Slave
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 74;
-	
-	private static final Map<Integer, Double> MOBS_SKIN = new HashMap<>();
-	static {
-		MOBS_SKIN.put(21294, 0.840); // Canyon Antelope
-		MOBS_SKIN.put(21295, 0.893); // Canyon Antelope Slave
-	}
-	
+
+
 	public Q00654_JourneyToASettlement() {
 		super(654, Q00654_JourneyToASettlement.class.getSimpleName(), "Journey to a Settlement");
 		addStartNpc(NAMELESS_SPIRIT);
 		addTalkId(NAMELESS_SPIRIT);
-		addKillId(MOBS_SKIN.keySet());
-		registerQuestItems(ANTELOPE_SKIN);
+		addKillId(DROPLIST.getNpcIds());
+		registerQuestItems(ANTELOPE_SKIN.getId());
 	}
 	
 	@Override
@@ -77,7 +76,7 @@ public final class Q00654_JourneyToASettlement extends Quest {
 				}
 			}
 			case "31453-07.html": {
-				if (st.isMemoState(2) && st.hasQuestItems(ANTELOPE_SKIN)) {
+				if (st.isMemoState(2) && st.hasQuestItems(ANTELOPE_SKIN.getId())) {
 					giveItems(player, FRINTEZZAS_SCROLL, 1);
 					st.exitQuest(true, true);
 					htmltext = event;
@@ -90,7 +89,7 @@ public final class Q00654_JourneyToASettlement extends Quest {
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState st = getRandomPartyMemberState(player, 2, 3, npc);
-		if ((st != null) && giveItemRandomly(st.getPlayer(), npc, ANTELOPE_SKIN, 1, 1, MOBS_SKIN.get(npc.getId()), true)) {
+		if ((st != null) && giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true)) {
 			st.setCond(3);
 		}
 		return super.onKill(npc, player, isSummon);
@@ -108,7 +107,7 @@ public final class Q00654_JourneyToASettlement extends Quest {
 				st.setCond(2, true);
 				htmltext = "31453-03.html";
 			} else if (st.isMemoState(2)) {
-				htmltext = (hasQuestItems(player, ANTELOPE_SKIN) ? "31453-06.html" : "31453-05.html");
+				htmltext = (hasQuestItems(player, ANTELOPE_SKIN.getId()) ? "31453-06.html" : "31453-05.html");
 			}
 		}
 		return htmltext;
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00659_IdRatherBeCollectingFairyBreath/Q00659_IdRatherBeCollectingFairyBreath.java b/src/main/java/com/l2jserver/datapack/quests/Q00659_IdRatherBeCollectingFairyBreath/Q00659_IdRatherBeCollectingFairyBreath.java
index 3cca06e997..8f5210fd89 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00659_IdRatherBeCollectingFairyBreath/Q00659_IdRatherBeCollectingFairyBreath.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00659_IdRatherBeCollectingFairyBreath/Q00659_IdRatherBeCollectingFairyBreath.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00659_IdRatherBeCollectingFairyBreath;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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;
 
 /**
@@ -35,23 +33,22 @@ public final class Q00659_IdRatherBeCollectingFairyBreath extends Quest {
 	private static final int GALATEA = 30634;
 	// Item
 	private static final int FAIRY_BREATH = 8286;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20078, FAIRY_BREATH, 98.0) // whispering_wind
+			.addSingleDrop(21023, FAIRY_BREATH, 82.0) // sobing_wind
+			.addSingleDrop(21024, FAIRY_BREATH, 86.0) // babbleing_wind
+			.addSingleDrop(21025, FAIRY_BREATH, 90.0) // giggleing_wind
+			.addSingleDrop(21026, FAIRY_BREATH, 96.0) // singing_wind
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 26;
-	// Mobs
-	private static final Map<Integer, Double> MOBS = new HashMap<>();
-	static {
-		MOBS.put(20078, 0.98); // whispering_wind
-		MOBS.put(21023, 0.82); // sobing_wind
-		MOBS.put(21024, 0.86); // babbleing_wind
-		MOBS.put(21025, 0.90); // giggleing_wind
-		MOBS.put(21026, 0.96); // singing_wind
-	}
-	
+
 	public Q00659_IdRatherBeCollectingFairyBreath() {
 		super(659, Q00659_IdRatherBeCollectingFairyBreath.class.getSimpleName(), "I'd Rather Be Collecting Fairy Breath");
 		addStartNpc(GALATEA);
 		addTalkId(GALATEA);
-		addKillId(MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(FAIRY_BREATH);
 	}
 	
@@ -98,7 +95,7 @@ public final class Q00659_IdRatherBeCollectingFairyBreath extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState st = getRandomPartyMemberState(player, -1, 3, npc);
 		if (st != null) {
-			st.giveItemRandomly(npc, FAIRY_BREATH, 1, 0, MOBS.get(npc.getId()), true);
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00660_AidingTheFloranVillage/Q00660_AidingTheFloranVillage.java b/src/main/java/com/l2jserver/datapack/quests/Q00660_AidingTheFloranVillage/Q00660_AidingTheFloranVillage.java
index c4e16fcc88..6a26ef0e36 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00660_AidingTheFloranVillage/Q00660_AidingTheFloranVillage.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00660_AidingTheFloranVillage/Q00660_AidingTheFloranVillage.java
@@ -18,14 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00660_AidingTheFloranVillage;
 
-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.ItemChanceHolder;
 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;
 
@@ -43,6 +40,16 @@ public final class Q00660_AidingTheFloranVillage extends Quest {
 	private static final int WATCHING_EYES = 8074;
 	private static final int ROUGHLY_HEWN_ROCK_GOLEM_SHARD = 8075;
 	private static final int DELU_LIZARDMANS_SCALE = 8076;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21102, WATCHING_EYES, 50.0) // Watchman of the Plains
+			.addSingleDrop(21106, WATCHING_EYES, 63.0) // Cursed Seer
+			.addSingleDrop(21103, ROUGHLY_HEWN_ROCK_GOLEM_SHARD, 52.0) // Roughly Hewn Rock Golem
+			.addSingleDrop(20781, DELU_LIZARDMANS_SCALE, 65.0) // Delu Lizardman Shaman
+			.addSingleDrop(21104, DELU_LIZARDMANS_SCALE, 65.0) // Delu Lizardman Supplier
+			.addSingleDrop(21105, DELU_LIZARDMANS_SCALE, 75.0) // Delu Lizardman Special Agent
+			.addSingleDrop(21107, DELU_LIZARDMANS_SCALE, 133.0) // Delu Lizardman Commander
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 30;
 	private static final int ADENA_REWARD_1 = 13000;
@@ -52,25 +59,12 @@ public final class Q00660_AidingTheFloranVillage extends Quest {
 	private static final int ADENA_REWARD_5 = 45000;
 	private static final int ADENA_REWARD_6 = 5000;
 	private static final int DELU_LIZARDMAN_COMMANDER_DOUBLE_ITEM_CHANCE = 33;
-	// Monsters
-	private static final int DELU_LIZARDMAN_COMMANDER = 21107; // Delu Lizardman Commander
-	
-	private static final Map<Integer, ItemChanceHolder> MONSTERS = new HashMap<>();
-	static {
-		MONSTERS.put(21102, new ItemChanceHolder(WATCHING_EYES, 0.500)); // Watchman of the Plains
-		MONSTERS.put(21106, new ItemChanceHolder(WATCHING_EYES, 0.630)); // Cursed Seer
-		MONSTERS.put(21103, new ItemChanceHolder(ROUGHLY_HEWN_ROCK_GOLEM_SHARD, 0.520)); // Roughly Hewn Rock Golem
-		MONSTERS.put(20781, new ItemChanceHolder(DELU_LIZARDMANS_SCALE, 0.650)); // Delu Lizardman Shaman
-		MONSTERS.put(21104, new ItemChanceHolder(DELU_LIZARDMANS_SCALE, 0.650)); // Delu Lizardman Supplier
-		MONSTERS.put(21105, new ItemChanceHolder(DELU_LIZARDMANS_SCALE, 0.750)); // Delu Lizardman Special Agent
-	}
-	
+
 	public Q00660_AidingTheFloranVillage() {
 		super(660, Q00660_AidingTheFloranVillage.class.getSimpleName(), "Aiding the Floran Village");
 		addStartNpc(MARIA, ALEX);
 		addTalkId(MARIA, ALEX);
-		addKillId(MONSTERS.keySet());
-		addKillId(DELU_LIZARDMAN_COMMANDER);
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(WATCHING_EYES, ROUGHLY_HEWN_ROCK_GOLEM_SHARD, DELU_LIZARDMANS_SCALE);
 	}
 	
@@ -220,17 +214,7 @@ public final class Q00660_AidingTheFloranVillage extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(player, 2, 2, npc);
 		if (qs != null) {
-			final ItemChanceHolder item = MONSTERS.get(npc.getId());
-			if (item != null) {
-				giveItemRandomly(player, npc, item.getId(), item.getCount(), 0, item.getChance(), true);
-			} else {
-				if (getRandom(100) < DELU_LIZARDMAN_COMMANDER_DOUBLE_ITEM_CHANCE) {
-					giveItems(player, DELU_LIZARDMANS_SCALE, 2);
-				} else {
-					giveItems(player, DELU_LIZARDMANS_SCALE, 1);
-				}
-				playSound(player, Sound.ITEMSOUND_QUEST_MIDDLE);
-			}
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00661_MakingTheHarvestGroundsSafe/Q00661_MakingTheHarvestGroundsSafe.java b/src/main/java/com/l2jserver/datapack/quests/Q00661_MakingTheHarvestGroundsSafe/Q00661_MakingTheHarvestGroundsSafe.java
index d025bc9fea..3b578268cb 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00661_MakingTheHarvestGroundsSafe/Q00661_MakingTheHarvestGroundsSafe.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00661_MakingTheHarvestGroundsSafe/Q00661_MakingTheHarvestGroundsSafe.java
@@ -18,13 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00661_MakingTheHarvestGroundsSafe;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
 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;
 
@@ -39,13 +36,12 @@ public final class Q00661_MakingTheHarvestGroundsSafe extends Quest {
 	private static final int BIG_HORNET_STING = 8283;
 	private static final int CLOUD_GEM = 8284;
 	private static final int YOUNG_ARANEID_CLAW = 8285;
-	// Monsters
-	private final Map<Integer, ItemChanceHolder> MONSTER_CHANCES = new HashMap<>();
-	{
-		MONSTER_CHANCES.put(21095, new ItemChanceHolder(BIG_HORNET_STING, 0.508)); // Giant Poison Bee
-		MONSTER_CHANCES.put(21096, new ItemChanceHolder(CLOUD_GEM, 0.5)); // Cloudy Beast
-		MONSTER_CHANCES.put(21097, new ItemChanceHolder(YOUNG_ARANEID_CLAW, 0.516)); // Young Araneid
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(21095, BIG_HORNET_STING, 50.8) // Giant Poison Bee
+			.addSingleDrop(21096, CLOUD_GEM, 50.0) // Cloudy Beast
+			.addSingleDrop(21097, YOUNG_ARANEID_CLAW, 51.6) // Young Araneid
+			.build();
 	// Misc
 	private static final int MIN_LVL = 21;
 	
@@ -53,7 +49,7 @@ public final class Q00661_MakingTheHarvestGroundsSafe extends Quest {
 		super(661, Q00661_MakingTheHarvestGroundsSafe.class.getSimpleName(), "Making the Harvest Grounds Safe");
 		addStartNpc(NORMAN);
 		addTalkId(NORMAN);
-		addKillId(MONSTER_CHANCES.keySet());
+		addKillId(DROPLIST.getNpcIds());
 		registerQuestItems(BIG_HORNET_STING, CLOUD_GEM, YOUNG_ARANEID_CLAW);
 	}
 	
@@ -129,8 +125,7 @@ public final class Q00661_MakingTheHarvestGroundsSafe extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		final QuestState qs = getRandomPartyMemberState(killer, -1, 3, npc);
 		if (qs != null) {
-			final ItemChanceHolder item = MONSTER_CHANCES.get(npc.getId());
-			giveItemRandomly(qs.getPlayer(), npc, item.getId(), item.getCount(), 0, item.getChance(), true);
+			giveItemRandomly(qs.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00662_AGameOfCards/Q00662_AGameOfCards.java b/src/main/java/com/l2jserver/datapack/quests/Q00662_AGameOfCards/Q00662_AGameOfCards.java
index 350a19e459..893a6adb53 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00662_AGameOfCards/Q00662_AGameOfCards.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00662_AGameOfCards/Q00662_AGameOfCards.java
@@ -18,17 +18,12 @@
  */
 package com.l2jserver.datapack.quests.Q00662_AGameOfCards;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 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;
-import com.l2jserver.gameserver.util.Util;
 
 /**
  * A Game of Cards (662)
@@ -40,58 +35,52 @@ public final class Q00662_AGameOfCards extends Quest {
 	// Items
 	private static final int RED_GEM = 8765;
 	private static final int ZIGGOS_GEMSTONE = 8868;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(20672, RED_GEM, 35.7) // Trives
+			.addSingleDrop(20673, RED_GEM, 35.7) // Falibati
+			.addSingleDrop(20674, RED_GEM, 58.3) // Doom Knight
+			.addSingleDrop(20677, RED_GEM, 43.5) // Tulben
+			.addSingleDrop(20955, RED_GEM, 35.8) // Ghostly Warrior
+			.addSingleDrop(20958, RED_GEM, 28.3) // Death Agent
+			.addSingleDrop(20959, RED_GEM, 45.5) // Dark Guard
+			.addSingleDrop(20961, RED_GEM, 36.5) // Bloody Knight
+			.addSingleDrop(20962, RED_GEM, 34.8) // Bloody Priest
+			.addSingleDrop(20965, RED_GEM, 45.7) // Chimera Piece
+			.addSingleDrop(20966, RED_GEM, 49.3) // Changed Creation
+			.addSingleDrop(20968, RED_GEM, 41.8) // Nonexistent Man
+			.addSingleDrop(20972, RED_GEM, 35.0) // Shaman of Ancient Times
+			.addSingleDrop(20973, RED_GEM, 45.3) // Forgotten Ancient People
+			.addSingleDrop(21002, RED_GEM, 31.5) // Doom Scout
+			.addSingleDrop(21004, RED_GEM, 32.0) // Dismal Pole
+			.addSingleDrop(21006, RED_GEM, 33.5) // Doom Servant
+			.addSingleDrop(21008, RED_GEM, 46.2) // Doom Archer
+			.addSingleDrop(21010, RED_GEM, 39.7) // Doom Warrior
+			.addSingleDrop(21109, RED_GEM, 50.7) // Hames Orc Scout
+			.addSingleDrop(21112, RED_GEM, 55.2) // Hames Orc Footman
+			.addSingleDrop(21114, RED_GEM, 58.7) // Cursed Guardian
+			.addSingleDrop(21116, RED_GEM, 81.2) // Hames Orc Overlord
+			.bulkAddSingleDrop(RED_GEM, 48.3).withNpcs(21278, 21279, 21280).build() // Antelope
+			.bulkAddSingleDrop(RED_GEM, 51.5).withNpcs(21286, 21287, 21288).build() // Buffalo
+			.addSingleDrop(21508, RED_GEM, 49.3) // Splinter Stakato
+			.addSingleDrop(21510, RED_GEM, 52.7) // Splinter Stakato Soldier
+			.addSingleDrop(21513, RED_GEM, 56.2) // Needle Stakato
+			.addSingleDrop(21515, RED_GEM, 59.8) // Needle Stakato Soldier
+			.addSingleDrop(21520, RED_GEM, 45.8) // Eye of Splendor
+			.addSingleDrop(21526, RED_GEM, 55.2) // Wisdom of Splendor
+			.addSingleDrop(21530, RED_GEM, 48.8) // Victory of Splendor
+			.addSingleDrop(21535, RED_GEM, 57.3) // Signet of Splendor
+			.addSingleDrop(18001, RED_GEM, 23.2) // Blood Queen
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 61;
 	private static final int REQUIRED_CHIP_COUNT = 50;
-	// Monsters
-	private static final Map<Integer, Integer> MONSTERS = new HashMap<>();
-	
-	static {
-		MONSTERS.put(20672, 357); // Trives
-		MONSTERS.put(20673, 357); // Falibati
-		MONSTERS.put(20674, 583); // Doom Knight
-		MONSTERS.put(20677, 435); // Tulben
-		MONSTERS.put(20955, 358); // Ghostly Warrior
-		MONSTERS.put(20958, 283); // Death Agent
-		MONSTERS.put(20959, 455); // Dark Guard
-		MONSTERS.put(20961, 365); // Bloody Knight
-		MONSTERS.put(20962, 348); // Bloody Priest
-		MONSTERS.put(20965, 457); // Chimera Piece
-		MONSTERS.put(20966, 493); // Changed Creation
-		MONSTERS.put(20968, 418); // Nonexistent Man
-		MONSTERS.put(20972, 350); // Shaman of Ancient Times
-		MONSTERS.put(20973, 453); // Forgotten Ancient People
-		MONSTERS.put(21002, 315); // Doom Scout
-		MONSTERS.put(21004, 320); // Dismal Pole
-		MONSTERS.put(21006, 335); // Doom Servant
-		MONSTERS.put(21008, 462); // Doom Archer
-		MONSTERS.put(21010, 397); // Doom Warrior
-		MONSTERS.put(21109, 507); // Hames Orc Scout
-		MONSTERS.put(21112, 552); // Hames Orc Footman
-		MONSTERS.put(21114, 587); // Cursed Guardian
-		MONSTERS.put(21116, 812); // Hames Orc Overlord
-		MONSTERS.put(21278, 483); // Antelope
-		MONSTERS.put(21279, 483); // Antelope
-		MONSTERS.put(21280, 483); // Antelope
-		MONSTERS.put(21286, 515); // Buffalo
-		MONSTERS.put(21287, 515); // Buffalo
-		MONSTERS.put(21288, 515); // Buffalo
-		MONSTERS.put(21508, 493); // Splinter Stakato
-		MONSTERS.put(21510, 527); // Splinter Stakato Soldier
-		MONSTERS.put(21513, 562); // Needle Stakato
-		MONSTERS.put(21515, 598); // Needle Stakato Soldier
-		MONSTERS.put(21520, 458); // Eye of Splendor
-		MONSTERS.put(21526, 552); // Wisdom of Splendor
-		MONSTERS.put(21530, 488); // Victory of Splendor
-		MONSTERS.put(21535, 573); // Signet of Splendor
-		MONSTERS.put(18001, 232); // Blood Queen
-	}
-	
+
 	public Q00662_AGameOfCards() {
 		super(662, Q00662_AGameOfCards.class.getSimpleName(), "A Game of Cards");
 		addStartNpc(KLUMP);
 		addTalkId(KLUMP);
-		addKillId(MONSTERS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 	}
 	
 	@Override
@@ -536,26 +525,9 @@ public final class Q00662_AGameOfCards extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
-		final List<L2PcInstance> players = new ArrayList<>();
-		players.add(killer);
-		players.add(killer);
-		
-		if (killer.isInParty()) {
-			for (L2PcInstance member : killer.getParty().getMembers()) {
-				if (getQuestState(member, false) != null) {
-					players.add(member);
-				}
-			}
-		}
-		
-		final L2PcInstance player = players.get(getRandom(players.size()));
-		if ((player != null) && Util.checkIfInRange(1500, npc, player, false)) {
-			if (MONSTERS.get(npc.getId()) < getRandom(1000)) {
-				final QuestState st = getQuestState(player, false);
-				if (st != null) {
-					giveItemRandomly(st.getPlayer(), npc, RED_GEM, 1, 0, MONSTERS.get(npc.getId()), true);
-				}
-			}
+		final QuestState st = getRandomPartyMemberState(killer, -1, 3, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00688_DefeatTheElrokianRaiders/Q00688_DefeatTheElrokianRaiders.java b/src/main/java/com/l2jserver/datapack/quests/Q00688_DefeatTheElrokianRaiders/Q00688_DefeatTheElrokianRaiders.java
index e786eb41b2..698cd447e8 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00688_DefeatTheElrokianRaiders/Q00688_DefeatTheElrokianRaiders.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00688_DefeatTheElrokianRaiders/Q00688_DefeatTheElrokianRaiders.java
@@ -18,11 +18,9 @@
  */
 package com.l2jserver.datapack.quests.Q00688_DefeatTheElrokianRaiders;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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;
 import com.l2jserver.gameserver.model.quest.State;
@@ -36,17 +34,16 @@ public class Q00688_DefeatTheElrokianRaiders extends Quest {
 	private static final int ELROKI = 22214;
 	private static final int DINN = 32105;
 	// Item
-	private static final int DINOSAUR_FANG_NECKLACE = 8785;
+	private static final QuestItemChanceHolder DINOSAUR_FANG_NECKLACE = new QuestItemChanceHolder(8785, 44.8);
 	// Misc
 	private static final int MIN_LEVEL = 75;
-	private static final int DROP_RATE = 448;
-	
+
 	public Q00688_DefeatTheElrokianRaiders() {
 		super(688, Q00688_DefeatTheElrokianRaiders.class.getSimpleName(), "Defeat the Elrokian Raiders!");
 		addStartNpc(DINN);
 		addTalkId(DINN);
 		addKillId(ELROKI);
-		registerQuestItems(DINOSAUR_FANG_NECKLACE);
+		registerQuestItems(DINOSAUR_FANG_NECKLACE.getId());
 	}
 	
 	@Override
@@ -69,15 +66,15 @@ public class Q00688_DefeatTheElrokianRaiders extends Quest {
 				break;
 			}
 			case "32105-06.html": {
-				if (st.hasQuestItems(DINOSAUR_FANG_NECKLACE)) {
-					st.giveAdena(3000 * st.getQuestItemsCount(DINOSAUR_FANG_NECKLACE), true);
-					st.takeItems(DINOSAUR_FANG_NECKLACE, -1);
+				if (st.hasQuestItems(DINOSAUR_FANG_NECKLACE.getId())) {
+					st.giveAdena(3000 * st.getQuestItemsCount(DINOSAUR_FANG_NECKLACE.getId()), true);
+					st.takeItems(DINOSAUR_FANG_NECKLACE.getId(), -1);
 					htmltext = event;
 				}
 				break;
 			}
 			case "donation": {
-				if (st.getQuestItemsCount(DINOSAUR_FANG_NECKLACE) < 100) {
+				if (st.getQuestItemsCount(DINOSAUR_FANG_NECKLACE.getId()) < 100) {
 					htmltext = "32105-07.html";
 				} else {
 					if (getRandom(1000) < 500) {
@@ -87,13 +84,13 @@ public class Q00688_DefeatTheElrokianRaiders extends Quest {
 						st.giveAdena(150000, true);
 						htmltext = "32105-09.html";
 					}
-					st.takeItems(DINOSAUR_FANG_NECKLACE, 100);
+					st.takeItems(DINOSAUR_FANG_NECKLACE.getId(), 100);
 				}
 				break;
 			}
 			case "32105-11.html": {
-				if (st.hasQuestItems(DINOSAUR_FANG_NECKLACE)) {
-					st.giveAdena(3000 * st.getQuestItemsCount(DINOSAUR_FANG_NECKLACE), true);
+				if (st.hasQuestItems(DINOSAUR_FANG_NECKLACE.getId())) {
+					st.giveAdena(3000 * st.getQuestItemsCount(DINOSAUR_FANG_NECKLACE.getId()), true);
 				}
 				st.exitQuest(true, true);
 				htmltext = event;
@@ -105,17 +102,9 @@ public class Q00688_DefeatTheElrokianRaiders extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember == null) {
-			return super.onKill(npc, player, isSummon);
-		}
-		
-		final QuestState st = getQuestState(partyMember, false);
-		
-		double chance = (DROP_RATE * rates().getRateQuestDrop());
-		if (getRandom(1000) < chance) {
-			st.rewardItems(DINOSAUR_FANG_NECKLACE, 1);
-			st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DINOSAUR_FANG_NECKLACE, true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
@@ -130,7 +119,7 @@ public class Q00688_DefeatTheElrokianRaiders extends Quest {
 				break;
 			}
 			case State.STARTED: {
-				htmltext = (st.hasQuestItems(DINOSAUR_FANG_NECKLACE)) ? "32105-05.html" : "32105-12.html";
+				htmltext = (st.hasQuestItems(DINOSAUR_FANG_NECKLACE.getId())) ? "32105-05.html" : "32105-12.html";
 				break;
 			}
 		}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00690_JudesRequest/Q00690_JudesRequest.java b/src/main/java/com/l2jserver/datapack/quests/Q00690_JudesRequest/Q00690_JudesRequest.java
index c5614f4b95..968e5259af 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00690_JudesRequest/Q00690_JudesRequest.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00690_JudesRequest/Q00690_JudesRequest.java
@@ -18,12 +18,11 @@
  */
 package com.l2jserver.datapack.quests.Q00690_JudesRequest;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
 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;
 
@@ -38,6 +37,12 @@ public class Q00690_JudesRequest extends Quest {
 	private static final int GREATER_EVIL = 22399;
 	// Items
 	private static final int EVIL_WEAPON = 10327;
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(LESSER_EVIL, EVIL_WEAPON, 17.3)
+			.addSingleDrop(GREATER_EVIL, EVIL_WEAPON, 24.6)
+			.build();
+	// Rewards
 	private static final int[][] REWARDS = {
 		{
 			10373,
@@ -108,27 +113,9 @@ public class Q00690_JudesRequest extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		L2PcInstance partyMember = getRandomPartyMember(player, 1);
-		if (partyMember == null) {
-			return null;
-		}
-		final QuestState st = getQuestState(partyMember, false);
-		
-		final int npcId = npc.getId();
-		int chance = 0;
-		if (npcId == LESSER_EVIL) {
-			chance = 173;
-		} else if (npcId == GREATER_EVIL) {
-			chance = 246;
-		}
-		// Apply the quest drop rate:
-		chance *= rates().getRateQuestDrop();
-		// Normalize
-		chance %= 1000;
-		
-		if (getRandom(1000) <= chance) {
-			st.giveItems(EVIL_WEAPON, Math.max(chance / 1000, 1));
-			st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return null;
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00691_MatrasSuspiciousRequest/Q00691_MatrasSuspiciousRequest.java b/src/main/java/com/l2jserver/datapack/quests/Q00691_MatrasSuspiciousRequest/Q00691_MatrasSuspiciousRequest.java
index c1a2d61cec..be67d3ea41 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00691_MatrasSuspiciousRequest/Q00691_MatrasSuspiciousRequest.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00691_MatrasSuspiciousRequest/Q00691_MatrasSuspiciousRequest.java
@@ -18,15 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00691_MatrasSuspiciousRequest;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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;
 
@@ -40,20 +35,19 @@ public final class Q00691_MatrasSuspiciousRequest extends Quest {
 	// Items
 	private static final int RED_GEM = 10372;
 	private static final int DYNASTY_SOUL_II = 10413;
-	// Reward
-	private static final Map<Integer, Integer> REWARD_CHANCES = new HashMap<>();
-	static {
-		REWARD_CHANCES.put(22363, 890);
-		REWARD_CHANCES.put(22364, 261);
-		REWARD_CHANCES.put(22365, 560);
-		REWARD_CHANCES.put(22366, 560);
-		REWARD_CHANCES.put(22367, 190);
-		REWARD_CHANCES.put(22368, 129);
-		REWARD_CHANCES.put(22369, 210);
-		REWARD_CHANCES.put(22370, 787);
-		REWARD_CHANCES.put(22371, 257);
-		REWARD_CHANCES.put(22372, 656);
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.addSingleDrop(22363, RED_GEM, 89.0)
+			.addSingleDrop(22364, RED_GEM, 26.1)
+			.addSingleDrop(22365, RED_GEM, 56.0)
+			.addSingleDrop(22366, RED_GEM, 56.0)
+			.addSingleDrop(22367, RED_GEM, 19.0)
+			.addSingleDrop(22368, RED_GEM, 12.9)
+			.addSingleDrop(22369, RED_GEM, 21.0)
+			.addSingleDrop(22370, RED_GEM, 78.7)
+			.addSingleDrop(22371, RED_GEM, 25.7)
+			.addSingleDrop(22372, RED_GEM, 65.6)
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 76;
 	
@@ -61,7 +55,7 @@ public final class Q00691_MatrasSuspiciousRequest extends Quest {
 		super(691, Q00691_MatrasSuspiciousRequest.class.getSimpleName(), "Matras' Suspicious Request");
 		addStartNpc(MATRAS);
 		addTalkId(MATRAS);
-		addKillId(REWARD_CHANCES.keySet());
+		addKillId(DROPLIST.getNpcIds());
 	}
 	
 	@Override
@@ -116,18 +110,9 @@ public final class Q00691_MatrasSuspiciousRequest extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance pl = getRandomPartyMember(player, 1);
-		if (pl == null) {
-			return super.onKill(npc, player, isSummon);
-		}
-		
-		final QuestState st = getQuestState(pl, false);
-		int chance = (int) (rates().getRateQuestDrop() * REWARD_CHANCES.get(npc.getId()));
-		int numItems = Math.max((chance / 1000), 1);
-		chance = chance % 1000;
-		if (getRandom(1000) <= chance) {
-			st.giveItems(RED_GEM, numItems);
-			st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
+		QuestState st = getRandomPartyMemberState(player, 1, 1, npc);
+		if (st != null) {
+			giveItemRandomly(st.getPlayer(), npc, DROPLIST.get(npc), true);
 		}
 		return super.onKill(npc, player, isSummon);
 	}
@@ -152,4 +137,4 @@ public final class Q00691_MatrasSuspiciousRequest extends Quest {
 		}
 		return htmltext;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q00692_HowtoOpposeEvil/Q00692_HowtoOpposeEvil.java b/src/main/java/com/l2jserver/datapack/quests/Q00692_HowtoOpposeEvil/Q00692_HowtoOpposeEvil.java
index ed94468a66..0e62b22b35 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q00692_HowtoOpposeEvil/Q00692_HowtoOpposeEvil.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q00692_HowtoOpposeEvil/Q00692_HowtoOpposeEvil.java
@@ -18,16 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q00692_HowtoOpposeEvil;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
-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.ItemHolder;
 import com.l2jserver.gameserver.model.quest.Quest;
+import com.l2jserver.gameserver.model.quest.QuestDroplist;
 import com.l2jserver.gameserver.model.quest.QuestState;
 
 /**
@@ -35,76 +29,40 @@ import com.l2jserver.gameserver.model.quest.QuestState;
  * @author Gigiikun
  */
 public final class Q00692_HowtoOpposeEvil extends Quest {
+	// NPCs
 	private static final int DILIOS = 32549;
 	private static final int KIRKLAN = 32550;
+	// Items
 	private static final int LEKONS_CERTIFICATE = 13857;
+	private static final int FREED_SOUL_FRAGMENT = 13863;
+	private static final int DRAGONKIN_CHARM_FRAGMENT = 13865;
+	private static final int SPIRIT_STONE_DUST = 15536;
 	private static final int[] QUEST_ITEMS = {
-		13863,
-		13864,
-		13865,
-		13866,
-		13867,
-		15535,
-		15536
+			FREED_SOUL_FRAGMENT,
+			13864, // Seal of Tiat
+			DRAGONKIN_CHARM_FRAGMENT,
+			13866, // Restless Soul
+			13867, // Tiat Charm
+			15535, // Concentrated Spirit Energy
+			SPIRIT_STONE_DUST
 	};
-	
-	private static final Map<Integer, ItemHolder> QUEST_MOBS = new HashMap<>();
-	static {
-		// Seed of Infinity
-		QUEST_MOBS.put(22509, new ItemHolder(13863, 500));
-		QUEST_MOBS.put(22510, new ItemHolder(13863, 500));
-		QUEST_MOBS.put(22511, new ItemHolder(13863, 500));
-		QUEST_MOBS.put(22512, new ItemHolder(13863, 500));
-		QUEST_MOBS.put(22513, new ItemHolder(13863, 500));
-		QUEST_MOBS.put(22514, new ItemHolder(13863, 500));
-		QUEST_MOBS.put(22515, new ItemHolder(13863, 500));
-		// Seed of Destruction
-		QUEST_MOBS.put(22537, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22538, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22539, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22540, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22541, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22542, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22543, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22544, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22546, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22547, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22548, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22549, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22550, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22551, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22552, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22593, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22596, new ItemHolder(13865, 250));
-		QUEST_MOBS.put(22597, new ItemHolder(13865, 250));
-		// Seed of Annihilation
-		QUEST_MOBS.put(22746, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22747, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22748, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22749, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22750, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22751, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22752, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22753, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22754, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22755, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22756, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22757, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22758, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22759, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22760, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22761, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22762, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22763, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22764, new ItemHolder(15536, 125));
-		QUEST_MOBS.put(22765, new ItemHolder(15536, 125));
-	}
+	// Droplist
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.bulkAddSingleDrop(FREED_SOUL_FRAGMENT, 50.0) // Seed of Infinity
+				.withNpcs(22509, 22510, 22511, 22512, 22513, 22514, 22515).build()
+			.bulkAddSingleDrop(DRAGONKIN_CHARM_FRAGMENT, 25.0) // Seed of Destruction
+				.withNpcs(22537, 22538, 22539, 22540, 22541, 22542, 22543, 22544, 22546)
+				.withNpcs(22547, 22548, 22549, 22550, 22551, 22552, 22593, 22596, 22597).build()
+			.bulkAddSingleDrop(SPIRIT_STONE_DUST, 12.5) // Seed of Annihilation
+				.withNpcs(22746, 22747, 22748, 22749, 22750, 22751, 22752, 22753, 22754, 22755)
+				.withNpcs(22756, 22757, 22758, 22759, 22760, 22761, 22762, 22763, 22764, 22765).build()
+			.build();
 	
 	public Q00692_HowtoOpposeEvil() {
 		super(692, Q00692_HowtoOpposeEvil.class.getSimpleName(), "How to Oppose Evil");
 		addStartNpc(DILIOS);
 		addTalkId(DILIOS, KIRKLAN);
-		addKillId(QUEST_MOBS.keySet());
+		addKillId(DROPLIST.getNpcIds());
 	}
 	
 	@Override
@@ -118,7 +76,7 @@ public final class Q00692_HowtoOpposeEvil extends Quest {
 		} else if (event.equalsIgnoreCase("32550-04.htm")) {
 			st.setCond(3);
 		} else if (event.equalsIgnoreCase("32550-07.htm")) {
-			if (!giveReward(st, 13863, 5, 13796, 1)) {
+			if (!giveReward(st, FREED_SOUL_FRAGMENT, 5, 13796, 1)) {
 				return "32550-08.htm";
 			}
 		} else if (event.equalsIgnoreCase("32550-09.htm")) {
@@ -126,7 +84,7 @@ public final class Q00692_HowtoOpposeEvil extends Quest {
 				return "32550-10.htm";
 			}
 		} else if (event.equalsIgnoreCase("32550-12.htm")) {
-			if (!giveReward(st, 13865, 5, 13841, 1)) {
+			if (!giveReward(st, DRAGONKIN_CHARM_FRAGMENT, 5, 13841, 1)) {
 				return "32550-13.htm";
 			}
 		} else if (event.equalsIgnoreCase("32550-14.htm")) {
@@ -134,7 +92,7 @@ public final class Q00692_HowtoOpposeEvil extends Quest {
 				return "32550-15.htm";
 			}
 		} else if (event.equalsIgnoreCase("32550-17.htm")) {
-			if (!giveReward(st, 15536, 5, 15486, 1)) {
+			if (!giveReward(st, SPIRIT_STONE_DUST, 5, 15486, 1)) {
 				return "32550-18.htm";
 			}
 		} else if (event.equalsIgnoreCase("32550-19.htm")) {
@@ -147,23 +105,9 @@ public final class Q00692_HowtoOpposeEvil extends Quest {
 	
 	@Override
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
-		final L2PcInstance partyMember = getRandomPartyMember(player, 3);
-		if (partyMember == null) {
-			return null;
-		}
-		final QuestState st = getQuestState(partyMember, false);
-		final int npcId = npc.getId();
-		if ((st != null) && QUEST_MOBS.containsKey(npcId)) {
-			int chance = (int) (QUEST_MOBS.get(npcId).getCount() * rates().getRateQuestDrop());
-			int numItems = chance / 1000;
-			chance = chance % 1000;
-			if (getRandom(1000) < chance) {
-				numItems++;
-			}
-			if (numItems > 0) {
-				st.giveItems(QUEST_MOBS.get(npcId).getId(), numItems);
-				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 null;
 	}
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q10272_LightFragment/Q10272_LightFragment.java b/src/main/java/com/l2jserver/datapack/quests/Q10272_LightFragment/Q10272_LightFragment.java
index 0e64868076..2dab163ef5 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q10272_LightFragment/Q10272_LightFragment.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q10272_LightFragment/Q10272_LightFragment.java
@@ -18,12 +18,10 @@
  */
 package com.l2jserver.datapack.quests.Q10272_LightFragment;
 
-import static com.l2jserver.gameserver.config.Configuration.rates;
-
 import com.l2jserver.datapack.quests.Q10271_TheEnvelopingDarkness.Q10271_TheEnvelopingDarkness;
-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.itemcontainer.Inventory;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
@@ -34,11 +32,17 @@ import com.l2jserver.gameserver.model.quest.State;
  * @author Gladicek
  */
 public class Q10272_LightFragment extends Quest {
+	// NPCs
 	private static final int ORBYU = 32560;
 	private static final int ARTIUS = 32559;
 	private static final int GINBY = 32566;
 	private static final int LELRIKIA = 32567;
 	private static final int LEKON = 32557;
+	// Items
+	private static final int LIGHT_FRAGMENT_POWDER = 13854;
+	private static final int LIGHT_FRAGMENT = 13855;
+	private static final QuestItemChanceHolder FRAGMENT_POWDER = new QuestItemChanceHolder(13853, 60.0, 100L);
+	// Monsters
 	private static final int[] MOBS = {
 		22536, // Royal Guard Captain
 		22537, // Dragon Steed Troop Grand Magician
@@ -53,20 +57,15 @@ public class Q10272_LightFragment extends Quest {
 		22550, // Savage Warrior
 		22551, // Priest of Darkness
 		22552, // Mutation Drake
-		22596
-		// White Dragon Leader
+		22596 // White Dragon Leader
 	};
-	private static final int FRAGMENT_POWDER = 13853;
-	private static final int LIGHT_FRAGMENT_POWDER = 13854;
-	private static final int LIGHT_FRAGMENT = 13855;
-	private static final double DROP_CHANCE = 60;
-	
+
 	public Q10272_LightFragment() {
 		super(10272, Q10272_LightFragment.class.getSimpleName(), "Light Fragment");
 		addStartNpc(ORBYU);
 		addTalkId(ORBYU, ARTIUS, GINBY, LELRIKIA, LEKON);
 		addKillId(MOBS);
-		registerQuestItems(FRAGMENT_POWDER, LIGHT_FRAGMENT_POWDER);
+		registerQuestItems(FRAGMENT_POWDER.getId(), LIGHT_FRAGMENT_POWDER);
 	}
 	
 	@Override
@@ -125,24 +124,7 @@ public class Q10272_LightFragment extends Quest {
 	public final String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState st = getQuestState(player, false);
 		if ((st != null) && st.isCond(5)) {
-			final long count = st.getQuestItemsCount(FRAGMENT_POWDER);
-			if (count < 100) {
-				int chance = (int) (rates().getRateQuestDrop() * DROP_CHANCE);
-				int numItems = chance / 100;
-				chance = chance % 100;
-				if (getRandom(100) < chance) {
-					numItems++;
-				}
-				if (numItems > 0) {
-					if ((count + numItems) > 100) {
-						numItems = 100 - (int) count;
-					}
-					if (numItems > 0) {
-						st.giveItems(FRAGMENT_POWDER, numItems);
-						st.playSound(Sound.ITEMSOUND_QUEST_ITEMGET);
-					}
-				}
-			}
+			giveItemRandomly(player, npc, FRAGMENT_POWDER, true);
 		}
 		return null;
 	}
@@ -188,11 +170,11 @@ public class Q10272_LightFragment extends Quest {
 							htmltext = "32559-10.html";
 							break;
 						case 5:
-							if (st.getQuestItemsCount(FRAGMENT_POWDER) >= 100) {
+							if (hasItemsAtLimit(st.getPlayer(), FRAGMENT_POWDER)) {
 								htmltext = "32559-15.html";
 								st.setCond(6, true);
 							} else {
-								htmltext = st.hasQuestItems(FRAGMENT_POWDER) ? "32559-14.html" : "32559-13.html";
+								htmltext = st.hasQuestItems(FRAGMENT_POWDER.getId()) ? "32559-14.html" : "32559-13.html";
 							}
 							break;
 						case 6:
diff --git a/src/main/java/com/l2jserver/datapack/quests/Q10292_SevenSignsGirlOfDoubt/Q10292_SevenSignsGirlOfDoubt.java b/src/main/java/com/l2jserver/datapack/quests/Q10292_SevenSignsGirlOfDoubt/Q10292_SevenSignsGirlOfDoubt.java
index 67ad8caffb..2d96f25228 100644
--- a/src/main/java/com/l2jserver/datapack/quests/Q10292_SevenSignsGirlOfDoubt/Q10292_SevenSignsGirlOfDoubt.java
+++ b/src/main/java/com/l2jserver/datapack/quests/Q10292_SevenSignsGirlOfDoubt/Q10292_SevenSignsGirlOfDoubt.java
@@ -21,10 +21,11 @@ package com.l2jserver.datapack.quests.Q10292_SevenSignsGirlOfDoubt;
 import com.l2jserver.datapack.quests.Q00198_SevenSignsEmbryo.Q00198_SevenSignsEmbryo;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
+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.util.Util;
 
 /**
  * Seven Signs, Girl of Doubt (10292)
@@ -38,7 +39,13 @@ public final class Q10292_SevenSignsGirlOfDoubt extends Quest {
 	private static final int FRANZ = 32597;
 	private static final int ELCADIA = 32784;
 	// Item
-	private static final ItemHolder ELCADIAS_MARK = new ItemHolder(17226, 10);
+	private static final QuestItemChanceHolder ELCADIAS_MARK = new QuestItemChanceHolder(17226, 70.0, 10L);
+	private static final QuestDroplist DROPLIST = QuestDroplist.builder()
+			.bulkAddSingleDrop(ELCADIAS_MARK)
+				.withNpcs(22801, 22802, 22803) // Cruel Pincer Golem
+				.withNpcs(22804, 22805, 22806) // Horrifying Jackhammer Golem
+				.build()
+			.build();
 	// Misc
 	private static final int MIN_LEVEL = 81;
 	// Variables
@@ -46,21 +53,13 @@ public final class Q10292_SevenSignsGirlOfDoubt extends Quest {
 	// Monster
 	private static final int CREATURE_OF_THE_DUSK1 = 27422;
 	private static final int CREATURE_OF_THE_DUSK2 = 27424;
-	private static final int[] MOBS = {
-		22801, // Cruel Pincer Golem
-		22802, // Cruel Pincer Golem
-		22803, // Cruel Pincer Golem
-		22804, // Horrifying Jackhammer Golem
-		22805, // Horrifying Jackhammer Golem
-		22806, // Horrifying Jackhammer Golem
-	};
-	
+
 	public Q10292_SevenSignsGirlOfDoubt() {
 		super(10292, Q10292_SevenSignsGirlOfDoubt.class.getSimpleName(), "Seven Signs, Girl of Doubt");
 		addStartNpc(WOOD);
 		addSpawnId(ELCADIA);
 		addTalkId(WOOD, FRANZ, ELCADIA, HARDIN);
-		addKillId(MOBS);
+		addKillId(DROPLIST.getNpcIds());
 		addKillId(CREATURE_OF_THE_DUSK1, CREATURE_OF_THE_DUSK2);
 		registerQuestItems(ELCADIAS_MARK.getId());
 	}
@@ -169,10 +168,9 @@ public final class Q10292_SevenSignsGirlOfDoubt extends Quest {
 	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon) {
 		final QuestState st = getRandomPartyMemberState(player, -1, 3, npc);
 		if (st != null) {
-			if (Util.contains(MOBS, npc.getId())) {
-				if (giveItemRandomly(st.getPlayer(), npc, ELCADIAS_MARK.getId(), 1, ELCADIAS_MARK.getCount(), 0.7, true) && st.isMemoState(3)) {
-					st.setCond(4, true);
-				}
+			QuestDropInfo markDropInfo = DROPLIST.get(npc);
+			if (markDropInfo != null && giveItemRandomly(st.getPlayer(), npc, markDropInfo, true) && st.isMemoState(3)) {
+				st.setCond(4);
 			} else {
 				int killCount = st.getInt("killCount");
 				st.set("killCount", ++killCount);
@@ -227,10 +225,10 @@ public final class Q10292_SevenSignsGirlOfDoubt extends Quest {
 							break;
 						}
 						case 3: {
-							if (!hasItem(player, ELCADIAS_MARK)) {
+							if (!hasItemsAtLimit(player, ELCADIAS_MARK)) {
 								htmltext = "32784-03.html";
 							} else {
-								takeItem(player, ELCADIAS_MARK);
+								takeItems(player, ELCADIAS_MARK.getId(), -1);
 								st.setMemoState(4);
 								st.setCond(4, true);
 								htmltext = "32784-04.html";
-- 
GitLab