diff --git a/L2J_DataPack_BETA/dist/game/data/scripts/ai/group_template/DragonValley.java b/L2J_DataPack_BETA/dist/game/data/scripts/ai/group_template/DragonValley.java index 15bac678bdf6806d1fa3cefaa8f8b66824354661..3477b972a28f6b4eb2fe428e1ea55935cd2fecc3 100644 --- a/L2J_DataPack_BETA/dist/game/data/scripts/ai/group_template/DragonValley.java +++ b/L2J_DataPack_BETA/dist/game/data/scripts/ai/group_template/DragonValley.java @@ -18,6 +18,8 @@ */ package ai.group_template; +import java.util.EnumMap; + import ai.npc.AbstractNpcAI; import com.l2jserver.gameserver.ai.CtrlIntention; @@ -27,6 +29,7 @@ import com.l2jserver.gameserver.model.actor.L2Attackable; import com.l2jserver.gameserver.model.actor.L2Npc; import com.l2jserver.gameserver.model.actor.L2Playable; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; +import com.l2jserver.gameserver.model.base.ClassId; import com.l2jserver.gameserver.model.holders.SkillHolder; import com.l2jserver.gameserver.util.Util; @@ -40,7 +43,21 @@ public final class DragonValley extends AbstractNpcAI private static final int NECROMANCER_OF_THE_VALLEY = 22858; private static final int EXPLODING_ORC_GHOST = 22818; private static final int WRATHFUL_ORC_GHOST = 22819; - private static final int[] HERB_DROP = + private static final int DRAKOS_ASSASSIN = 22823; + private static final int[] SUMMON_NPC = + { + 22822, // Drakos Warrior + 22824, // Drakos Guardian + 22862, // Drakos Hunter + }; + private static final int[] SPAWN_ANIMATION = + { + 22826, // Scorpion Bones + 22823, // Drakos Assassin + 22828, // Parasitic Leech + + }; + private static final int[] SPOIL_REACT_MONSTER = { 22822, // Drakos Warrior 22823, // Drakos Assassin @@ -60,19 +77,72 @@ public final class DragonValley extends AbstractNpcAI 22862, // Drakos Hunter }; - // Skill - private static SkillHolder SELF_DESTRUCTION = new SkillHolder(6850, 1); + // Items + private static final int GREATER_HERB_OF_MANA = 8604; + private static final int SUPERIOR_HERB_OF_MANA = 8605; + + // Skills + private static final SkillHolder SELF_DESTRUCTION = new SkillHolder(6850, 1); + private static final SkillHolder MORALE_BOOST1 = new SkillHolder(6885, 1); + private static final SkillHolder MORALE_BOOST2 = new SkillHolder(6885, 2); + private static final SkillHolder MORALE_BOOST3 = new SkillHolder(6885, 3); + + // Misc + private static final int MIN_DISTANCE = 1500; + private static final int MIN_MEMBERS = 3; + private static final int MIN_LVL = 80; + private static final int CLASS_LVL = 3; + private static final EnumMap<ClassId, Double> CLASS_POINTS = new EnumMap<>(ClassId.class); + { + CLASS_POINTS.put(ClassId.adventurer, 0.2); + CLASS_POINTS.put(ClassId.arcanaLord, 1.5); + CLASS_POINTS.put(ClassId.archmage, 0.3); + CLASS_POINTS.put(ClassId.cardinal, -0.6); + CLASS_POINTS.put(ClassId.dominator, 0.2); + CLASS_POINTS.put(ClassId.doombringer, 0.2); + CLASS_POINTS.put(ClassId.doomcryer, 0.1); + CLASS_POINTS.put(ClassId.dreadnought, 0.7); + CLASS_POINTS.put(ClassId.duelist, 0.2); + CLASS_POINTS.put(ClassId.elementalMaster, 1.4); + CLASS_POINTS.put(ClassId.evaSaint, -0.6); + CLASS_POINTS.put(ClassId.evaTemplar, 0.8); + CLASS_POINTS.put(ClassId.femaleSoulhound, 0.4); + CLASS_POINTS.put(ClassId.fortuneSeeker, 0.9); + CLASS_POINTS.put(ClassId.ghostHunter, 0.2); + CLASS_POINTS.put(ClassId.ghostSentinel, 0.2); + CLASS_POINTS.put(ClassId.grandKhavatari, 0.2); + CLASS_POINTS.put(ClassId.hellKnight, 0.6); + CLASS_POINTS.put(ClassId.hierophant, 0.0); + CLASS_POINTS.put(ClassId.judicator, 0.1); + CLASS_POINTS.put(ClassId.moonlightSentinel, 0.2); + CLASS_POINTS.put(ClassId.maestro, 0.7); + CLASS_POINTS.put(ClassId.maleSoulhound, 0.4); + CLASS_POINTS.put(ClassId.mysticMuse, 0.3); + CLASS_POINTS.put(ClassId.phoenixKnight, 0.6); + CLASS_POINTS.put(ClassId.sagittarius, 0.2); + CLASS_POINTS.put(ClassId.shillienSaint, -0.6); + CLASS_POINTS.put(ClassId.shillienTemplar, 0.8); + CLASS_POINTS.put(ClassId.soultaker, 0.3); + CLASS_POINTS.put(ClassId.spectralDancer, 0.4); + CLASS_POINTS.put(ClassId.spectralMaster, 1.4); + CLASS_POINTS.put(ClassId.stormScreamer, 0.3); + CLASS_POINTS.put(ClassId.swordMuse, 0.4); + CLASS_POINTS.put(ClassId.titan, 0.3); + CLASS_POINTS.put(ClassId.trickster, 0.5); + CLASS_POINTS.put(ClassId.windRider, 0.2); + } private DragonValley() { super(DragonValley.class.getSimpleName(), "ai/group_template"); addAttackId(NECROMANCER_OF_THE_VALLEY); + addAttackId(SUMMON_NPC); addKillId(NECROMANCER_OF_THE_VALLEY); - addKillId(HERB_DROP); + addKillId(SPOIL_REACT_MONSTER); addSpawnId(EXPLODING_ORC_GHOST); - addSpawnId(HERB_DROP); + addSpawnId(SPOIL_REACT_MONSTER); - for (int npcId : HERB_DROP) + for (int npcId : SPOIL_REACT_MONSTER) { for (L2Spawn spawn : SpawnTable.getInstance().getSpawns(npcId)) { @@ -89,7 +159,7 @@ public final class DragonValley extends AbstractNpcAI @Override public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) { - if (event.equalsIgnoreCase("SelfDestruction") && !npc.isDead()) + if (event.equals("SelfDestruction") && (npc != null) && !npc.isDead()) { npc.abortAttack(); npc.disableCoreAI(true); @@ -100,25 +170,42 @@ public final class DragonValley extends AbstractNpcAI } @Override - public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) + public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon) { - L2Attackable mob = (L2Attackable) npc; - if (Util.contains(HERB_DROP, npc.getId()) && mob.isSweepActive()) + if (npc.getId() == NECROMANCER_OF_THE_VALLEY) { - npc.dropItem(killer, getRandom(8604, 8605), 1); + spawnGhost(npc, attacker, isSummon, 1); } - else if (npc.getId() == NECROMANCER_OF_THE_VALLEY) + else { - spawnGhost(npc, killer, isSummon, 20); + if ((npc.getCurrentHp() < (npc.getMaxHp() / 2)) && (getRandom(100) < 5) && npc.isScriptValue(0)) + { + npc.setScriptValue(1); + final int rnd = getRandom(3, 5); + for (int i = 0; i < rnd; i++) + { + final L2Playable playable = isSummon ? attacker.getSummon() : attacker; + final L2Attackable minion = (L2Attackable) addSpawn(DRAKOS_ASSASSIN, npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), true, 0, true); + attackPlayer(minion, playable); + } + } } - return super.onKill(npc, killer, isSummon); + return super.onAttack(npc, attacker, damage, isSummon); } @Override - public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon) + public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) { - spawnGhost(npc, attacker, isSummon, 1); - return super.onAttack(npc, attacker, damage, isSummon); + if (npc.getId() == NECROMANCER_OF_THE_VALLEY) + { + spawnGhost(npc, killer, isSummon, 20); + } + else if (((L2Attackable) npc).isSweepActive()) + { + npc.dropItem(killer, getRandom(GREATER_HERB_OF_MANA, SUPERIOR_HERB_OF_MANA), 1); + manageMoraleBoost(killer, npc); + } + return super.onKill(npc, killer, isSummon); } @Override @@ -129,9 +216,62 @@ public final class DragonValley extends AbstractNpcAI { startQuestTimer("SelfDestruction", 3000, npc, null); } + else if (Util.contains(SPAWN_ANIMATION, npc.getId())) + { + npc.setShowSummonAnimation(true); + } return super.onSpawn(npc); } + private void manageMoraleBoost(L2PcInstance player, L2Npc npc) + { + double points = 0; + int moraleBoostLv = 0; + + if (player.isInParty() && (player.getParty().getMemberCount() >= MIN_MEMBERS) && (npc != null)) + { + for (L2PcInstance member : player.getParty().getMembers()) + { + if ((member.getLevel() >= MIN_LVL) && (member.getClassId().level() >= CLASS_LVL) && (Util.calculateDistance(npc, member, true, false) < MIN_DISTANCE)) + { + points += CLASS_POINTS.get(member.getClassId()); + } + } + + if (points >= 3) + { + moraleBoostLv = 3; + } + else if (points >= 2) + { + moraleBoostLv = 2; + } + else if (points >= 1) + { + moraleBoostLv = 1; + } + + for (L2PcInstance member : player.getParty().getMembers()) + { + if (Util.calculateDistance(npc, member, true, false) < MIN_DISTANCE) + { + switch (moraleBoostLv) + { + case 1: + MORALE_BOOST1.getSkill().applyEffects(member, member); + break; + case 2: + MORALE_BOOST2.getSkill().applyEffects(member, member); + break; + case 3: + MORALE_BOOST3.getSkill().applyEffects(member, member); + break; + } + } + } + } + } + private void spawnGhost(L2Npc npc, L2PcInstance player, boolean isSummon, int chance) { if ((npc.getScriptValue() < 2) && (getRandom(100) < chance))