Skip to content
Snippets Groups Projects
Commit 0cdaa3b5 authored by Noe Caratini's avatar Noe Caratini
Browse files

fix(dwd): Added correct drops to Dark Water Dragon mobs + small cleanup

parent 43281da7
No related branches found
No related tags found
No related merge requests found
...@@ -18,18 +18,20 @@ ...@@ -18,18 +18,20 @@
*/ */
package com.l2jserver.datapack.ai.individual; package com.l2jserver.datapack.ai.individual;
import java.util.Map; import com.l2jserver.commons.util.Rnd;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.l2jserver.datapack.ai.npc.AbstractNpcAI; import com.l2jserver.datapack.ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention; 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.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character; import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc; import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; 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. * Dark Water Dragon's AI.
*/ */
...@@ -41,8 +43,14 @@ public final class DarkWaterDragon extends AbstractNpcAI { ...@@ -41,8 +43,14 @@ public final class DarkWaterDragon extends AbstractNpcAI {
private static final int DETRACTOR1 = 22270; private static final int DETRACTOR1 = 22270;
private static final int DETRACTOR2 = 22271; 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 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 // Items
private static Map<Integer, L2PcInstance> ID_MAP = new ConcurrentHashMap<>(); // Used to track instances of npcs 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() { public DarkWaterDragon() {
super(DarkWaterDragon.class.getSimpleName(), "ai/individual"); super(DarkWaterDragon.class.getSimpleName(), "ai/individual");
...@@ -64,32 +72,23 @@ public final class DarkWaterDragon extends AbstractNpcAI { ...@@ -64,32 +72,23 @@ public final class DarkWaterDragon extends AbstractNpcAI {
@Override @Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) { public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) {
if (npc != null) { 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 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 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 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 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); 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); 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); 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); 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("fafurion_poison", npc, null);
cancelQuestTimer("1", npc, null); cancelQuestTimer("1", npc, null);
cancelQuestTimer("2", npc, null); cancelQuestTimer("2", npc, null);
...@@ -99,12 +98,12 @@ public final class DarkWaterDragon extends AbstractNpcAI { ...@@ -99,12 +98,12 @@ public final class DarkWaterDragon extends AbstractNpcAI {
MY_TRACKING_SET.remove(npc.getObjectId()); MY_TRACKING_SET.remove(npc.getObjectId());
player = ID_MAP.remove(npc.getObjectId()); player = ID_MAP.remove(npc.getObjectId());
if (player != null) { 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(); 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) { if (npc.getCurrentHp() <= 500) {
cancelQuestTimer("fafurion_despawn", npc, null); cancelQuestTimer("fafurion_despawn", npc, null);
cancelQuestTimer("first_spawn", npc, null); cancelQuestTimer("first_spawn", npc, null);
...@@ -129,11 +128,10 @@ public final class DarkWaterDragon extends AbstractNpcAI { ...@@ -129,11 +128,10 @@ public final class DarkWaterDragon extends AbstractNpcAI {
int npcId = npc.getId(); int npcId = npc.getId();
int npcObjId = npc.getObjectId(); int npcObjId = npc.getObjectId();
if (npcId == DRAGON) { 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); MY_TRACKING_SET.add(npcObjId);
// Spawn first 5 shades on first attack on Dark Water Dragon // 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, SHADE1, npc.getX() + 100, npc.getY() + 100, npc.getZ());
spawnShade(originalAttacker, SHADE2, 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()); spawnShade(originalAttacker, SHADE1, npc.getX() - 100, npc.getY() + 100, npc.getZ());
...@@ -142,7 +140,6 @@ public final class DarkWaterDragon extends AbstractNpcAI { ...@@ -142,7 +140,6 @@ public final class DarkWaterDragon extends AbstractNpcAI {
} else if ((npc.getCurrentHp() < (npc.getMaxHp() / 2.0)) && !(SECOND_SPAWN.contains(npcObjId))) { } else if ((npc.getCurrentHp() < (npc.getMaxHp() / 2.0)) && !(SECOND_SPAWN.contains(npcObjId))) {
SECOND_SPAWN.add(npcObjId); SECOND_SPAWN.add(npcObjId);
// Spawn second 5 shades on half hp of on Dark Water Dragon // 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, SHADE2, npc.getX() + 100, npc.getY() + 100, npc.getZ());
spawnShade(originalAttacker, SHADE1, 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()); spawnShade(originalAttacker, SHADE2, npc.getX() - 100, npc.getY() + 100, npc.getZ());
...@@ -157,28 +154,49 @@ public final class DarkWaterDragon extends AbstractNpcAI { ...@@ -157,28 +154,49 @@ public final class DarkWaterDragon extends AbstractNpcAI {
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) { public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
int npcId = npc.getId(); int npcId = npc.getId();
int npcObjId = npc.getObjectId(); int npcObjId = npc.getObjectId();
if (npcId == DRAGON) { switch (npcId) {
MY_TRACKING_SET.remove(npcObjId); case DRAGON -> {
SECOND_SPAWN.remove(npcObjId); MY_TRACKING_SET.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 SECOND_SPAWN.remove(npcObjId);
ID_MAP.put(faf.getObjectId(), killer); L2Attackable faf = (L2Attackable) addSpawn(FAFURION, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0); // spawns Fafurion Kindred when Dard Water Dragon is dead
} else if (npcId == FAFURION) { ID_MAP.put(faf.getObjectId(), killer);
cancelQuestTimer("fafurion_poison", npc, null); calculateDrop(npc, killer, RED_SEED_OF_EVIL, 77.0);
cancelQuestTimer("fafurion_despawn", npc, null); }
cancelQuestTimer("first_spawn", npc, null); case FAFURION -> {
cancelQuestTimer("second_spawn", npc, null); cancelQuestTimer("fafurion_poison", npc, null);
cancelQuestTimer("third_spawn", npc, null); cancelQuestTimer("fafurion_despawn", npc, null);
cancelQuestTimer("fourth_spawn", npc, null); cancelQuestTimer("first_spawn", npc, null);
cancelQuestTimer("1", npc, null); cancelQuestTimer("second_spawn", npc, null);
cancelQuestTimer("2", npc, null); cancelQuestTimer("third_spawn", npc, null);
cancelQuestTimer("3", npc, null); cancelQuestTimer("fourth_spawn", npc, null);
cancelQuestTimer("4", npc, null); cancelQuestTimer("1", npc, null);
MY_TRACKING_SET.remove(npcObjId); cancelQuestTimer("2", npc, null);
ID_MAP.remove(npcObjId); 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); 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 @Override
public String onSpawn(L2Npc npc) { public String onSpawn(L2Npc npc) {
int npcId = npc.getId(); int npcId = npc.getId();
...@@ -204,7 +222,7 @@ public final class DarkWaterDragon extends AbstractNpcAI { ...@@ -204,7 +222,7 @@ public final class DarkWaterDragon extends AbstractNpcAI {
return super.onSpawn(npc); 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); final L2Npc shade = addSpawn(npcId, x, y, z, 0, false, 0);
shade.setRunning(); shade.setRunning();
((L2Attackable) shade).addDamageHate(attacker, 0, 999); ((L2Attackable) shade).addDamageHate(attacker, 0, 999);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment