From 0cdaa3b517aed2165f9aaebd0b0294a6556154fa Mon Sep 17 00:00:00 2001
From: Noe Caratini <caratinin@gmail.com>
Date: Tue, 7 Jun 2022 13:01:41 +0100
Subject: [PATCH] fix(dwd): Added correct drops to Dark Water Dragon mobs +
 small cleanup

---
 .../ai/individual/DarkWaterDragon.java        | 120 ++++++++++--------
 1 file changed, 69 insertions(+), 51 deletions(-)

diff --git a/src/main/java/com/l2jserver/datapack/ai/individual/DarkWaterDragon.java b/src/main/java/com/l2jserver/datapack/ai/individual/DarkWaterDragon.java
index e56725db8b..24a6e43c48 100644
--- a/src/main/java/com/l2jserver/datapack/ai/individual/DarkWaterDragon.java
+++ b/src/main/java/com/l2jserver/datapack/ai/individual/DarkWaterDragon.java
@@ -18,18 +18,20 @@
  */
 package com.l2jserver.datapack.ai.individual;
 
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
+import com.l2jserver.commons.util.Rnd;
 import com.l2jserver.datapack.ai.npc.AbstractNpcAI;
 import com.l2jserver.gameserver.ai.CtrlIntention;
-import com.l2jserver.gameserver.data.xml.impl.NpcData;
 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 java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.l2jserver.gameserver.config.Configuration.rates;
+
 /**
  * Dark Water Dragon's AI.
  */
@@ -41,8 +43,14 @@ public final class DarkWaterDragon extends AbstractNpcAI {
 	private static final int DETRACTOR1 = 22270;
 	private static final int DETRACTOR2 = 22271;
 	private static final Set<Integer> SECOND_SPAWN = ConcurrentHashMap.newKeySet(); // Used to track if second Shades were already spawned
-	private static Set<Integer> MY_TRACKING_SET = ConcurrentHashMap.newKeySet(); // Used to track instances of npcs
-	private static Map<Integer, L2PcInstance> ID_MAP = new ConcurrentHashMap<>(); // Used to track instances of npcs
+	// Items
+	private static final int BLUE_SEED_OF_EVIL = 9595;
+	private static final int RED_SEED_OF_EVIL = 9596;
+	private static final int WATER_DRAGON_SCALE = 9691;
+	private static final int WATER_DRAGON_CLAW = 9700;
+	private static final int SPIRIT_OF_THE_LAKE = 9689;
+	private static final Set<Integer> MY_TRACKING_SET = ConcurrentHashMap.newKeySet(); // Used to track instances of npcs
+	private static final Map<Integer, L2PcInstance> ID_MAP = new ConcurrentHashMap<>(); // Used to track instances of npcs
 	
 	public DarkWaterDragon() {
 		super(DarkWaterDragon.class.getSimpleName(), "ai/individual");
@@ -64,32 +72,23 @@ public final class DarkWaterDragon extends AbstractNpcAI {
 	@Override
 	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) {
 		if (npc != null) {
-			if (event.equalsIgnoreCase("first_spawn")) // timer to start timer "1"
-			{
+			if (event.equalsIgnoreCase("first_spawn")) { // timer to start timer "1"
 				startQuestTimer("1", 40000, npc, null, true); // spawns detractor every 40 seconds
-			} else if (event.equalsIgnoreCase("second_spawn")) // timer to start timer "2"
-			{
+			} else if (event.equalsIgnoreCase("second_spawn")) { // timer to start timer "2"
 				startQuestTimer("2", 40000, npc, null, true); // spawns detractor every 40 seconds
-			} else if (event.equalsIgnoreCase("third_spawn")) // timer to start timer "3"
-			{
+			} else if (event.equalsIgnoreCase("third_spawn")) { // timer to start timer "3"
 				startQuestTimer("3", 40000, npc, null, true); // spawns detractor every 40 seconds
-			} else if (event.equalsIgnoreCase("fourth_spawn")) // timer to start timer "4"
-			{
+			} else if (event.equalsIgnoreCase("fourth_spawn")) { // timer to start timer "4"
 				startQuestTimer("4", 40000, npc, null, true); // spawns detractor every 40 seconds
-			} else if (event.equalsIgnoreCase("1")) // spawns a detractor
-			{
+			} else if (event.equalsIgnoreCase("1")) { // spawns a detractor
 				addSpawn(DETRACTOR1, (npc.getX() + 100), (npc.getY() + 100), npc.getZ(), 0, false, 40000);
-			} else if (event.equalsIgnoreCase("2")) // spawns a detractor
-			{
+			} else if (event.equalsIgnoreCase("2")) { // spawns a detractor
 				addSpawn(DETRACTOR2, (npc.getX() + 100), (npc.getY() - 100), npc.getZ(), 0, false, 40000);
-			} else if (event.equalsIgnoreCase("3")) // spawns a detractor
-			{
+			} else if (event.equalsIgnoreCase("3")) { // spawns a detractor
 				addSpawn(DETRACTOR1, (npc.getX() - 100), (npc.getY() + 100), npc.getZ(), 0, false, 40000);
-			} else if (event.equalsIgnoreCase("4")) // spawns a detractor
-			{
+			} else if (event.equalsIgnoreCase("4")) { // spawns a detractor
 				addSpawn(DETRACTOR2, (npc.getX() - 100), (npc.getY() - 100), npc.getZ(), 0, false, 40000);
-			} else if (event.equalsIgnoreCase("fafurion_despawn")) // Fafurion Kindred disappears and drops reward
-			{
+			} else if (event.equalsIgnoreCase("fafurion_despawn")) { // Fafurion Kindred disappears and drops reward
 				cancelQuestTimer("fafurion_poison", npc, null);
 				cancelQuestTimer("1", npc, null);
 				cancelQuestTimer("2", npc, null);
@@ -99,12 +98,12 @@ public final class DarkWaterDragon extends AbstractNpcAI {
 				MY_TRACKING_SET.remove(npc.getObjectId());
 				player = ID_MAP.remove(npc.getObjectId());
 				if (player != null) {
-					((L2Attackable) npc).doItemDrop(NpcData.getInstance().getTemplate(18485), player);
+					calculateDrop(npc, player, WATER_DRAGON_SCALE, 100.0);
+					calculateDrop(npc, player, WATER_DRAGON_CLAW, 33.0);
 				}
 				
 				npc.deleteMe();
-			} else if (event.equalsIgnoreCase("fafurion_poison")) // Reduces Fafurions hp like it is poisoned
-			{
+			} else if (event.equalsIgnoreCase("fafurion_poison")) { // Reduces Fafurions hp like it is poisoned
 				if (npc.getCurrentHp() <= 500) {
 					cancelQuestTimer("fafurion_despawn", npc, null);
 					cancelQuestTimer("first_spawn", npc, null);
@@ -129,11 +128,10 @@ public final class DarkWaterDragon extends AbstractNpcAI {
 		int npcId = npc.getId();
 		int npcObjId = npc.getObjectId();
 		if (npcId == DRAGON) {
-			if (!MY_TRACKING_SET.contains(npcObjId)) // this allows to handle multiple instances of npc
-			{
+			final L2Character originalAttacker = isSummon ? attacker.getSummon() : attacker;
+			if (!MY_TRACKING_SET.contains(npcObjId)) { // this allows to handle multiple instances of npc
 				MY_TRACKING_SET.add(npcObjId);
 				// Spawn first 5 shades on first attack on Dark Water Dragon
-				L2Character originalAttacker = isSummon ? attacker.getSummon() : attacker;
 				spawnShade(originalAttacker, SHADE1, npc.getX() + 100, npc.getY() + 100, npc.getZ());
 				spawnShade(originalAttacker, SHADE2, npc.getX() + 100, npc.getY() - 100, npc.getZ());
 				spawnShade(originalAttacker, SHADE1, npc.getX() - 100, npc.getY() + 100, npc.getZ());
@@ -142,7 +140,6 @@ public final class DarkWaterDragon extends AbstractNpcAI {
 			} else if ((npc.getCurrentHp() < (npc.getMaxHp() / 2.0)) && !(SECOND_SPAWN.contains(npcObjId))) {
 				SECOND_SPAWN.add(npcObjId);
 				// Spawn second 5 shades on half hp of on Dark Water Dragon
-				L2Character originalAttacker = isSummon ? attacker.getSummon() : attacker;
 				spawnShade(originalAttacker, SHADE2, npc.getX() + 100, npc.getY() + 100, npc.getZ());
 				spawnShade(originalAttacker, SHADE1, npc.getX() + 100, npc.getY() - 100, npc.getZ());
 				spawnShade(originalAttacker, SHADE2, npc.getX() - 100, npc.getY() + 100, npc.getZ());
@@ -157,28 +154,49 @@ public final class DarkWaterDragon extends AbstractNpcAI {
 	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
 		int npcId = npc.getId();
 		int npcObjId = npc.getObjectId();
-		if (npcId == DRAGON) {
-			MY_TRACKING_SET.remove(npcObjId);
-			SECOND_SPAWN.remove(npcObjId);
-			L2Attackable faf = (L2Attackable) addSpawn(FAFURION, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0); // spawns Fafurion Kindred when Dard Water Dragon is dead
-			ID_MAP.put(faf.getObjectId(), killer);
-		} else if (npcId == FAFURION) {
-			cancelQuestTimer("fafurion_poison", npc, null);
-			cancelQuestTimer("fafurion_despawn", npc, null);
-			cancelQuestTimer("first_spawn", npc, null);
-			cancelQuestTimer("second_spawn", npc, null);
-			cancelQuestTimer("third_spawn", npc, null);
-			cancelQuestTimer("fourth_spawn", npc, null);
-			cancelQuestTimer("1", npc, null);
-			cancelQuestTimer("2", npc, null);
-			cancelQuestTimer("3", npc, null);
-			cancelQuestTimer("4", npc, null);
-			MY_TRACKING_SET.remove(npcObjId);
-			ID_MAP.remove(npcObjId);
+		switch (npcId) {
+			case DRAGON -> {
+				MY_TRACKING_SET.remove(npcObjId);
+				SECOND_SPAWN.remove(npcObjId);
+				L2Attackable faf = (L2Attackable) addSpawn(FAFURION, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0); // spawns Fafurion Kindred when Dard Water Dragon is dead
+				ID_MAP.put(faf.getObjectId(), killer);
+				calculateDrop(npc, killer, RED_SEED_OF_EVIL, 77.0);
+			}
+			case FAFURION -> {
+				cancelQuestTimer("fafurion_poison", npc, null);
+				cancelQuestTimer("fafurion_despawn", npc, null);
+				cancelQuestTimer("first_spawn", npc, null);
+				cancelQuestTimer("second_spawn", npc, null);
+				cancelQuestTimer("third_spawn", npc, null);
+				cancelQuestTimer("fourth_spawn", npc, null);
+				cancelQuestTimer("1", npc, null);
+				cancelQuestTimer("2", npc, null);
+				cancelQuestTimer("3", npc, null);
+				cancelQuestTimer("4", npc, null);
+				MY_TRACKING_SET.remove(npcObjId);
+				ID_MAP.remove(npcObjId);
+			}
+			case SHADE1 -> calculateDrop(npc, killer, BLUE_SEED_OF_EVIL, 9.87);
+			case SHADE2 -> calculateDrop(npc, killer, BLUE_SEED_OF_EVIL, 9.95);
+			case DETRACTOR1, DETRACTOR2 -> {
+				calculateDrop(npc, killer, SPIRIT_OF_THE_LAKE, 100.0);
+				calculateDrop(npc, killer, BLUE_SEED_OF_EVIL, 10.08);
+			}
 		}
 		return super.onKill(npc, killer, isSummon);
 	}
 	
+	private void calculateDrop(final L2Npc npc, final L2PcInstance killer, final int itemId, final double dropRate) {
+		final int finalRate = (int) ((dropRate * 100) * rates().getDeathDropChanceMultiplier());
+		if (Rnd.get(10000) <= finalRate) {
+			int finalAmount = rates().getDeathDropAmountMultiplier().intValue();
+			if (finalRate > 10000) {
+				finalAmount *= finalRate / 10000 + (Rnd.get(10000) <= finalRate % 10000 ? 1 : 0);
+			}
+			npc.dropItem(killer, itemId, finalAmount);
+		}
+	}
+	
 	@Override
 	public String onSpawn(L2Npc npc) {
 		int npcId = npc.getId();
@@ -204,7 +222,7 @@ public final class DarkWaterDragon extends AbstractNpcAI {
 		return super.onSpawn(npc);
 	}
 	
-	public void spawnShade(L2Character attacker, int npcId, int x, int y, int z) {
+	private void spawnShade(L2Character attacker, int npcId, int x, int y, int z) {
 		final L2Npc shade = addSpawn(npcId, x, y, z, 0, false, 0);
 		shade.setRunning();
 		((L2Attackable) shade).addDamageHate(attacker, 0, 999);
-- 
GitLab