/* * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If * not, see <http://www.gnu.org/licenses/>. */ package silentium.gameserver.ai; import static silentium.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK; import java.util.List; import silentium.gameserver.instancemanager.DimensionalRiftManager; import silentium.gameserver.model.L2Object; import silentium.gameserver.model.L2Skill; import silentium.gameserver.model.actor.L2Attackable; import silentium.gameserver.model.actor.L2Character; import silentium.gameserver.model.actor.L2Npc; import silentium.gameserver.model.actor.instance.L2MonsterInstance; import silentium.gameserver.model.actor.instance.L2PcInstance; import silentium.gameserver.model.actor.instance.L2RiftInvaderInstance; import silentium.gameserver.model.quest.Quest; import silentium.gameserver.tables.NpcTable; import silentium.gameserver.templates.chars.L2NpcTemplate; import silentium.gameserver.utils.Util; /** * Overarching Superclass for all mob AI * * @author Fulminus */ public class DefaultMonsterAI extends Quest { /** * This is used to register all monsters contained in mobs for a particular script<BR> * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method register ID for all QuestEventTypes<BR> * Do not use for group_template AIs</B></FONT><BR> * * @param mobs * @see #registerMobs(int[], QuestEventType...) */ public void registerMobs(int[] mobs) { for (int id : mobs) { addEventId(id, QuestEventType.ON_ATTACK); addEventId(id, QuestEventType.ON_KILL); addEventId(id, QuestEventType.ON_SPAWN); addEventId(id, QuestEventType.ON_SPELL_FINISHED); addEventId(id, QuestEventType.ON_SKILL_SEE); addEventId(id, QuestEventType.ON_FACTION_CALL); addEventId(id, QuestEventType.ON_AGGRO_RANGE_ENTER); } } /** * This is used to register all monsters contained in mobs for a particular script event types defined in types. * * @param mobs * @param types */ public void registerMobs(int[] mobs, QuestEventType... types) { for (int id : mobs) { for (QuestEventType type : types) addEventId(id, type); } } public DefaultMonsterAI(int questId, String name, String dname, String path) { super(questId, name, dname, path); } @Override public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) { return null; } @Override public String onSpellFinished(L2Npc npc, L2PcInstance player, L2Skill skill) { return null; } @Override public String onSkillSee(L2Npc npc, L2PcInstance caster, L2Skill skill, L2Object[] targets, boolean isPet) { if (caster == null) return null; if (!(npc instanceof L2Attackable)) return null; L2Attackable attackable = (L2Attackable) npc; int skillAggroPoints = skill.getAggroPoints(); if (caster.getPet() != null) { if (targets.length == 1 && Util.contains(targets, caster.getPet())) skillAggroPoints = 0; } if (skillAggroPoints > 0) { if (attackable.hasAI() && (attackable.getAI().getIntention() == AI_INTENTION_ATTACK)) { L2Object npcTarget = attackable.getTarget(); for (L2Object skillTarget : targets) { if (npcTarget == skillTarget || npc == skillTarget) { L2Character originalCaster = isPet ? caster.getPet() : caster; attackable.addDamageHate(originalCaster, 0, (skillAggroPoints * 150) / (attackable.getLevel() + 7)); } } } } return null; } @Override public String onFactionCall(L2Npc npc, L2Npc caller, L2PcInstance attacker, boolean isPet) { if (attacker == null) return null; L2Character originalAttackTarget = (isPet ? attacker.getPet() : attacker); if (attacker.isInParty() && attacker.getParty().isInDimensionalRift()) { byte riftType = attacker.getParty().getDimensionalRift().getType(); byte riftRoom = attacker.getParty().getDimensionalRift().getCurrentRoom(); if (caller instanceof L2RiftInvaderInstance && !DimensionalRiftManager.getInstance().getRoom(riftType, riftRoom).checkIfInZone(npc.getX(), npc.getY(), npc.getZ())) return null; } // By default, when a faction member calls for help, attack the caller's attacker. // Notify the AI with EVT_AGGRESSION npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, originalAttackTarget, 1); return null; } @Override public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isPet) { if (player == null) return null; ((L2Attackable) npc).addDamageHate(isPet ? player.getPet() : player, 0, 1); return null; } @Override public String onSpawn(L2Npc npc) { return null; } @Override public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet) { if ((attacker != null) && (npc instanceof L2Attackable)) { L2Attackable attackable = (L2Attackable) npc; L2Character originalAttacker = isPet ? attacker.getPet() : attacker; attackable.getAI().notifyEvent(CtrlEvent.EVT_ATTACKED, originalAttacker); attackable.addDamageHate(originalAttacker, damage, (damage * 100) / (attackable.getLevel() + 7)); } return null; } @Override public String onKill(L2Npc npc, L2PcInstance killer, boolean isPet) { if (npc instanceof L2MonsterInstance) { final L2MonsterInstance mob = (L2MonsterInstance) npc; if (mob.getLeader() != null) mob.getLeader().getMinionList().onMinionDie(mob, -1); if (mob.hasMinions()) mob.getMinionList().onMasterDie(false); } return null; } public static void initialize() { final DefaultMonsterAI ai = new DefaultMonsterAI(-1, "DefaultMonsterAI", "", "DefaultMonsterAI"); // register all mobs here... for (int level = 1; level < 100; level++) { final List<L2NpcTemplate> templates = NpcTable.getInstance().getAllOfLevel(level); for (L2NpcTemplate t : templates) { try { if (L2Attackable.class.isAssignableFrom(Class.forName("silentium.gameserver.model.actor.instance." + t.getType() + "Instance"))) { ai.addEventId(t.getNpcId(), QuestEventType.ON_ATTACK); ai.addEventId(t.getNpcId(), QuestEventType.ON_KILL); ai.addEventId(t.getNpcId(), QuestEventType.ON_SPAWN); ai.addEventId(t.getNpcId(), QuestEventType.ON_SKILL_SEE); ai.addEventId(t.getNpcId(), QuestEventType.ON_FACTION_CALL); ai.addEventId(t.getNpcId(), QuestEventType.ON_AGGRO_RANGE_ENTER); } } catch (ClassNotFoundException ex) { _log.info("Class not found: " + t.getType() + "Instance"); } } } } }