From 7d865f41ac4e9988615e3ef73a75c98f3acc7327 Mon Sep 17 00:00:00 2001 From: Maneco2 <maneco_1@hotmail.com> Date: Wed, 3 Nov 2021 11:41:46 -0300 Subject: [PATCH] Rework Orfen AI Minion help Orfen bellow 1/2 HP, retail like. RandomTarget for minions is missing at: https://www.l2jserver.com/forum/viewtopic.php?f=86&t=33133 Fixed issue #226 --- .../datapack/ai/individual/Orfen.java | 400 +++++++++--------- 1 file changed, 202 insertions(+), 198 deletions(-) diff --git a/src/main/java/com/l2jserver/datapack/ai/individual/Orfen.java b/src/main/java/com/l2jserver/datapack/ai/individual/Orfen.java index d1abc36fea..9b012ef260 100644 --- a/src/main/java/com/l2jserver/datapack/ai/individual/Orfen.java +++ b/src/main/java/com/l2jserver/datapack/ai/individual/Orfen.java @@ -21,273 +21,277 @@ package com.l2jserver.datapack.ai.individual; import static com.l2jserver.gameserver.config.Configuration.grandBoss; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; import com.l2jserver.datapack.ai.npc.AbstractNpcAI; -import com.l2jserver.gameserver.ai.CtrlIntention; import com.l2jserver.gameserver.enums.audio.Music; import com.l2jserver.gameserver.instancemanager.GrandBossManager; import com.l2jserver.gameserver.model.L2Object; -import com.l2jserver.gameserver.model.L2Spawn; import com.l2jserver.gameserver.model.Location; import com.l2jserver.gameserver.model.StatsSet; 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.L2GrandBossInstance; +import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; import com.l2jserver.gameserver.model.holders.SkillHolder; import com.l2jserver.gameserver.model.skills.Skill; +import com.l2jserver.gameserver.model.zone.L2ZoneType; import com.l2jserver.gameserver.model.zone.type.L2BossZone; import com.l2jserver.gameserver.network.NpcStringId; import com.l2jserver.gameserver.network.clientpackets.Say2; -import com.l2jserver.gameserver.network.serverpackets.NpcSay; /** - * Orfen's AI + * Orfen AI * @author Emperorc + * @author Maneco2 */ public final class Orfen extends AbstractNpcAI { - private static final Location[] POS = { - new Location(43728, 17220, -4342), - new Location(55024, 17368, -5412), - new Location(53504, 21248, -5486), - new Location(53248, 24576, -5262) - }; - - private static final NpcStringId[] TEXT = { - NpcStringId.S1_STOP_KIDDING_YOURSELF_ABOUT_YOUR_OWN_POWERLESSNESS, - NpcStringId.S1_ILL_MAKE_YOU_FEEL_WHAT_TRUE_FEAR_IS, - NpcStringId.YOURE_REALLY_STUPID_TO_HAVE_CHALLENGED_ME_S1_GET_READY, - NpcStringId.S1_DO_YOU_THINK_THATS_GOING_TO_WORK - }; - + // NPCs private static final int ORFEN = 29014; - // private static final int RAIKEL = 29015; + private static final int RAIKEL = 29015; private static final int RAIKEL_LEOS = 29016; - // private static final int RIBA = 29017; private static final int RIBA_IREN = 29018; - - private static boolean _IsTeleported; - private static final List<L2Attackable> MINIONS = new CopyOnWriteArrayList<>(); - private static L2BossZone ZONE; - - private static final byte ALIVE = 0; - private static final byte DEAD = 1; - + // Orfen Location + private static final Location ORFEN_LOC_1 = new Location(43728, 17220, -4342, 0); + private static final Location ORFEN_LOC_2 = new Location(55024, 17368, -5412, 0); + private static final Location ORFEN_LOC_3 = new Location(53504, 21248, -5486, 0); + private static final Location ORFEN_LOC_4 = new Location(53248, 24576, -5262, 0); + // Zone + private static final int ZONE = 12013; // Skills - private static final SkillHolder PARALYSIS = new SkillHolder(4064); - private static final SkillHolder NPC_MORTAL_BLOW = new SkillHolder(4067, 4); - private static final SkillHolder ORFEN_HEAL = new SkillHolder(4516); + private static final SkillHolder ORFEN_STRIKE = new SkillHolder(4063); + private static final SkillHolder ORFEN_DISPEL = new SkillHolder(4064); + private static final SkillHolder S_NPC_BLOW4 = new SkillHolder(4067, 4); + private static final SkillHolder S_ORFEN_HEAL = new SkillHolder(4516); + // Variables + private boolean isAttacked = false; + private boolean isDefensive = false; + private static L2BossZone _zone; + private L2GrandBossInstance _orfen = null; + private L2Npc _riba = null; + // Status + private static final int ALIVE = 0; + private static final int DEAD = 1; public Orfen() { super(Orfen.class.getSimpleName(), "ai/individual"); - int[] mobs = { - ORFEN, - RAIKEL_LEOS, - RIBA_IREN - }; - registerMobs(mobs); - _IsTeleported = false; - ZONE = GrandBossManager.getInstance().getZone(POS[0]); + addKillId(ORFEN); + addSpawnId(ORFEN, RIBA_IREN); + addExitZoneId(ZONE); + addSkillSeeId(ORFEN); + addTeleportId(ORFEN); + addAttackId(ORFEN, RAIKEL_LEOS, RAIKEL, RIBA_IREN); + _zone = GrandBossManager.getInstance().getZone(43728, 17220, -4342); StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN); - int status = GrandBossManager.getInstance().getBossStatus(ORFEN); - if (status == DEAD) { - // load the unlock date and time for Orfen from DB - long temp = info.getLong("respawn_time") - System.currentTimeMillis(); - // if Orfen is locked until a certain time, mark it so and start the unlock timer - // the unlock time has not yet expired. - if (temp > 0) { - startQuestTimer("orfen_unlock", temp, null, null); + if (GrandBossManager.getInstance().getBossStatus(ORFEN) == DEAD) { + final long remain = info.getLong("respawn_time") - System.currentTimeMillis(); + if (remain > 0) { + startQuestTimer("ORFEN_UNLOCK", remain, null, null); } else { - // the time has already expired while the server was offline. Immediately spawn Orfen. - int i = getRandom(10); - Location loc; - if (i < 4) { - loc = POS[1]; - } else if (i < 7) { - loc = POS[2]; - } else { - loc = POS[3]; - } - L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc, false, 0); - GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE); - spawnBoss(orfen); + notifyEvent("ORFEN_UNLOCK", null, null); } } else { - int loc_x = info.getInt("loc_x"); - int loc_y = info.getInt("loc_y"); - int loc_z = info.getInt("loc_z"); - int heading = info.getInt("heading"); - int hp = info.getInt("currentHP"); - int mp = info.getInt("currentMP"); - L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc_x, loc_y, loc_z, heading, false, 0); - orfen.setCurrentHpMp(hp, mp); - spawnBoss(orfen); + notifyEvent("ORFEN_UNLOCK", null, null); } } - public void setSpawnPoint(L2Npc npc, int index) { - ((L2Attackable) npc).clearAggroList(); - npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null); - L2Spawn spawn = npc.getSpawn(); - spawn.setLocation(POS[index]); - npc.teleToLocation(POS[index], false); - } - - public void spawnBoss(L2GrandBossInstance npc) { - GrandBossManager.getInstance().addBoss(npc); - npc.broadcastPacket(Music.BS01_A_7000.getPacket()); - startQuestTimer("check_orfen_pos", 10000, npc, null, true); - // Spawn minions - int x = npc.getX(); - int y = npc.getY(); - L2Attackable mob; - mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y + 100, npc.getZ(), 0, false, 0); - mob.setIsRaidMinion(true); - MINIONS.add(mob); - mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y - 100, npc.getZ(), 0, false, 0); - mob.setIsRaidMinion(true); - MINIONS.add(mob); - mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y + 100, npc.getZ(), 0, false, 0); - mob.setIsRaidMinion(true); - MINIONS.add(mob); - mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y - 100, npc.getZ(), 0, false, 0); - mob.setIsRaidMinion(true); - MINIONS.add(mob); - startQuestTimer("check_minion_loc", 10000, npc, null, true); - } - @Override public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) { - if (event.equalsIgnoreCase("orfen_unlock")) { - int i = getRandom(10); - Location loc; - if (i < 4) { - loc = POS[1]; - } else if (i < 7) { - loc = POS[2]; - } else { - loc = POS[3]; - } - L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc, false, 0); - GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE); - spawnBoss(orfen); - } else if (event.equalsIgnoreCase("check_orfen_pos")) { - if ((_IsTeleported && (npc.getCurrentHp() > (npc.getMaxHp() * 0.95))) || (!ZONE.isInsideZone(npc) && !_IsTeleported)) { - setSpawnPoint(npc, getRandom(3) + 1); - _IsTeleported = false; - } else if (_IsTeleported && !ZONE.isInsideZone(npc)) { - setSpawnPoint(npc, 0); - } - } else if (event.equalsIgnoreCase("check_minion_loc")) { - for (L2Attackable mob : MINIONS) { - if (!npc.isInsideRadius(mob, 3000, false, false)) { - mob.teleToLocation(npc.getLocation()); + switch (event) { + case "CORE_AI": { + if (npc != null) { ((L2Attackable) npc).clearAggroList(); - npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null); + npc.disableCoreAI(false); } + break; } - } else if (event.equalsIgnoreCase("despawn_minions")) { - for (L2Attackable mob : MINIONS) { - if (mob != null) { - mob.decayMe(); + case "ORFEN_UNLOCK": { + StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN); + int hp = info.getInt("currentHP"); + int mp = info.getInt("currentMP"); + if (getRandom(100) < 40) { + _orfen = (L2GrandBossInstance) addSpawn(ORFEN, 55024, 17368, -5412, 0, false, 0); + } else if (getRandom(100) < 30) { + _orfen = (L2GrandBossInstance) addSpawn(ORFEN, 53504, 21248, -5486, 0, false, 0); + } else { + _orfen = (L2GrandBossInstance) addSpawn(ORFEN, 53248, 24576, -5262, 0, false, 0); + } + _orfen.setCurrentHpMp(hp, mp); + + if (GrandBossManager.getInstance().getBossStatus(ORFEN) == DEAD) { + GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE); } + spawnBoss(_orfen); + break; + } + case "CHECK_ZONE": { + if (npc != null) { + if (npc.getCurrentHp() > (npc.getMaxHp() * 0.95)) { + if ((isDefensive) && (!isAttacked)) { + isAttacked = true; + npc.disableCoreAI(true); + if (getRandom(100) < 33) { + npc.teleToLocation(ORFEN_LOC_2); + npc.getSpawn().setLocation(ORFEN_LOC_2); + } else if (getRandom(100) < 66) { + npc.teleToLocation(ORFEN_LOC_3); + npc.getSpawn().setLocation(ORFEN_LOC_3); + } else { + npc.teleToLocation(ORFEN_LOC_4); + npc.getSpawn().setLocation(ORFEN_LOC_4); + } + + if (isDefensive) { + isDefensive = false; + } + } + } else { + if ((npc.getCurrentHp()) < (npc.getMaxHp() / 2)) { + if (!isDefensive) { + isDefensive = true; + npc.disableCoreAI(true); + npc.teleToLocation(ORFEN_LOC_1); + npc.getSpawn().setLocation(ORFEN_LOC_1); + if (isAttacked) { + isAttacked = false; + } + } + } + } + } + break; } - MINIONS.clear(); - } else if (event.equalsIgnoreCase("spawn_minion")) { - L2Attackable mob = (L2Attackable) addSpawn(RAIKEL_LEOS, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0); - mob.setIsRaidMinion(true); - MINIONS.add(mob); } return super.onAdvEvent(event, npc, player); } @Override - public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, List<L2Object> targets, boolean isSummon) { - if (npc.getId() == ORFEN) { - L2Character originalCaster = isSummon ? caster.getSummon() : caster; - if ((skill.getEffectPoint() > 0) && (getRandom(5) == 0) && npc.isInsideRadius(originalCaster, 1000, false, false)) { - NpcSay packet = new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), TEXT[getRandom(4)]); - packet.addStringParameter(caster.getName().toString()); - npc.broadcastPacket(packet); - originalCaster.teleToLocation(npc.getLocation()); - npc.setTarget(originalCaster); - npc.doCast(PARALYSIS); + public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon) { + if ((npc != null) && (!npc.isCastingNow()) && (!npc.isCoreAIDisabled())) { + switch (npc.getId()) { + case ORFEN: { + if ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2)) { + if (!isDefensive) { + isDefensive = true; + npc.disableCoreAI(true); + npc.teleToLocation(ORFEN_LOC_1); + npc.getSpawn().setLocation(ORFEN_LOC_1); + if (isAttacked) { + isAttacked = false; + } + } + if (getRandom(100) < 90) { + _riba.setTarget(attacker); + _riba.doCast(S_ORFEN_HEAL); + } else if (getRandom(100) < 10) { + _riba.setTarget(attacker); + _riba.doCast(S_ORFEN_HEAL); + } + } + if ((npc.calculateDistance(attacker, false, false) > 300) && (npc.calculateDistance(attacker, false, false) < 1000) && (getRandom(100) < 10)) { + if (getRandom(100) < 33) { + broadcastNpcSay(npc, Say2.ALL, NpcStringId.S1_STOP_KIDDING_YOURSELF_ABOUT_YOUR_OWN_POWERLESSNESS); + } else if (getRandom(100) < 66) { + broadcastNpcSay(npc, Say2.ALL, NpcStringId.S1_ILL_MAKE_YOU_FEEL_WHAT_TRUE_FEAR_IS); + } else { + broadcastNpcSay(npc, Say2.ALL, NpcStringId.YOURE_REALLY_STUPID_TO_HAVE_CHALLENGED_ME_S1_GET_READY); + } + + attacker.teleToLocation(npc.getLocation()); + addSkillCastDesire(npc, attacker, ORFEN_STRIKE, 1000000L); + } else if (getRandom(100) < 20) { + addSkillCastDesire(npc, attacker, ORFEN_DISPEL, 1000000L); + } + } + case RAIKEL_LEOS: { + if (getRandom(100) < 5) { + addSkillCastDesire(npc, attacker, S_NPC_BLOW4, 1000000L); + } + } + case RAIKEL: + case RIBA_IREN: { + if ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2)) { + npc.setTarget(npc); + npc.doCast(S_ORFEN_HEAL); + } + } } } - return super.onSkillSee(npc, caster, skill, targets, isSummon); + return super.onAttack(npc, attacker, damage, isSummon); } @Override - public String onFactionCall(L2Npc npc, L2Npc caller, L2PcInstance attacker, boolean isSummon) { - if ((caller == null) || (npc == null) || npc.isCastingNow()) { - return super.onFactionCall(npc, caller, attacker, isSummon); - } - int npcId = npc.getId(); - int callerId = caller.getId(); - if ((npcId == RAIKEL_LEOS) && (getRandom(20) == 0)) { - npc.setTarget(attacker); - npc.doCast(NPC_MORTAL_BLOW); - } else if (npcId == RIBA_IREN) { - int chance = 1; - if (callerId == ORFEN) { - chance = 9; - } - if ((callerId != RIBA_IREN) && (caller.getCurrentHp() < (caller.getMaxHp() / 2.0)) && (getRandom(10) < chance)) { - npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null); - npc.setTarget(caller); - npc.doCast(ORFEN_HEAL); + public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, List<L2Object> targets, boolean isSummon) { + if (npc.getId() == ORFEN) { + final L2Character originalCaster = isSummon ? caster.getSummon() : caster; + if ((skill.getEffectPoint() > 0) && (getRandom(100) < 20) && (npc.calculateDistance(originalCaster, false, false) < 1000)) { + if (getRandom(100) < 25) { + broadcastNpcSay(npc, Say2.ALL, NpcStringId.S1_STOP_KIDDING_YOURSELF_ABOUT_YOUR_OWN_POWERLESSNESS); + } else if (getRandom(100) < 50) { + broadcastNpcSay(npc, Say2.ALL, NpcStringId.S1_ILL_MAKE_YOU_FEEL_WHAT_TRUE_FEAR_IS); + } else if (getRandom(100) < 75) { + broadcastNpcSay(npc, Say2.ALL, NpcStringId.YOURE_REALLY_STUPID_TO_HAVE_CHALLENGED_ME_S1_GET_READY); + } else { + broadcastNpcSay(npc, Say2.ALL, NpcStringId.S1_DO_YOU_THINK_THATS_GOING_TO_WORK); + } + + originalCaster.teleToLocation(npc.getLocation()); + addSkillCastDesire(npc, caster, ORFEN_DISPEL, 1000000L); } } - return super.onFactionCall(npc, caller, attacker, isSummon); + return super.onSkillSee(npc, caster, skill, targets, isSummon); } @Override - public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon) { - int npcId = npc.getId(); - if (npcId == ORFEN) { - if (!_IsTeleported && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2))) { - _IsTeleported = true; - setSpawnPoint(npc, 0); - } else if (npc.isInsideRadius(attacker, 1000, false, false) && !npc.isInsideRadius(attacker, 300, false, false) && (getRandom(10) == 0)) { - NpcSay packet = new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npcId, TEXT[getRandom(3)]); - packet.addStringParameter(attacker.getName().toString()); - npc.broadcastPacket(packet); - attacker.teleToLocation(npc.getLocation()); - npc.setTarget(attacker); - npc.doCast(PARALYSIS); + public String onSpawn(L2Npc npc) { + switch (npc.getId()) { + case ORFEN: { + notifyEvent("CHECK_ZONE", npc, null); + startQuestTimer("CHECK_ZONE", 10000, npc, null, true); } - } else if (npcId == RIBA_IREN) { - if (!npc.isCastingNow() && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2.0))) { - npc.setTarget(attacker); - npc.doCast(ORFEN_HEAL); + case RIBA_IREN: { + _riba = npc; + break; } } - return super.onAttack(npc, attacker, damage, isSummon); + + return super.onSpawn(npc); } @Override public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) { if (npc.getId() == ORFEN) { + cancelQuestTimers("CHECK_ZONE"); npc.broadcastPacket(Music.BS02_D_7000.getPacket()); GrandBossManager.getInstance().setBossStatus(ORFEN, DEAD); - // Calculate Min and Max respawn times randomly. - long respawnTime = grandBoss().getIntervalOfOrfenSpawn() + getRandom(-grandBoss().getRandomOfOrfenSpawn(), grandBoss().getRandomOfOrfenSpawn()); - respawnTime *= 3600000; - startQuestTimer("orfen_unlock", respawnTime, null, null); - // also save the respawn time so that the info is maintained past reboots - StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN); - info.set("respawn_time", System.currentTimeMillis() + respawnTime); - GrandBossManager.getInstance().setStatsSet(ORFEN, info); - cancelQuestTimer("check_minion_loc", npc, null); - cancelQuestTimer("check_orfen_pos", npc, null); - startQuestTimer("despawn_minions", 20000, null, null); - cancelQuestTimers("spawn_minion"); - } else if ((GrandBossManager.getInstance().getBossStatus(ORFEN) == ALIVE) && (npc.getId() == RAIKEL_LEOS)) { - MINIONS.remove(npc); - startQuestTimer("spawn_minion", 360000, npc, null); + final long respawnTime = (grandBoss().getIntervalOfOrfenSpawn() + getRandom(-grandBoss().getRandomOfOrfenSpawn(), grandBoss().getRandomOfOrfenSpawn())) * 3600000; + GrandBossManager.getInstance().getStatsSet(ORFEN).set("respawn_time", (System.currentTimeMillis() + respawnTime)); + startQuestTimer("ORFEN_UNLOCK", respawnTime, null, null); + _orfen = null; + _riba = null; } return super.onKill(npc, killer, isSummon); } + + @Override + public String onExitZone(L2Character character, L2ZoneType zone) { + if ((character.isAttackable()) && (character.isRaid()) && (!_zone.isInsideZone(_orfen)) && (_orfen != null)) { + _orfen.disableCoreAI(true); + _orfen.teleToLocation(_orfen.getSpawn().getLocation()); + startQuestTimer("CORE_AI", 100, _orfen, null); + } + return super.onExitZone(character, zone); + } + + @Override + protected void onTeleport(L2Npc npc) { + startQuestTimer("CORE_AI", 100, npc, null); + } + + public void spawnBoss(L2GrandBossInstance npc) { + GrandBossManager.getInstance().addBoss(npc); + npc.broadcastPacket(Music.BS01_A_7000.getPacket()); + _orfen = npc; + } } -- GitLab