/** * Manage the Cast Intention : Stop current Attack, Init the AI in order to cast and Launch Think * Event.<br> * <br> * <B><U> Actions</U> : </B><br> * <br> * <li>Set the AI cast target * <li>Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop * (broadcast) * <li>Cancel action client side by sending Server->Client packet ActionFailed to the L2Player * actor * <li>Set the AI skill used by INTENTION_CAST * <li>Set the Intention of this AI to AI_INTENTION_CAST * <li>Launch the Think Event <br> * <br> */ @Override protected void onIntentionCast(SkillUsageRequest request) { final L2Skill skill = request.getSkill(); if (getIntention() == AI_INTENTION_REST && skill.isMagic()) { clientActionFailed(); return; } // Stop actions client-side to cast the skill if (skill.getHitTime() > 50) { // Abort the attack of the L2Character and send Server->Client ActionFailed packet _actor.abortAttack(); // Cancel action client side by sending Server->Client packet ActionFailed to the L2Player // actor // no need for second ActionFailed packet, abortAttack() already sent it // clientActionFailed(); } final L2Object target = request.getSkill().getFirstOfTargetList(_actor); // Change the Intention of this AbstractAI to AI_INTENTION_CAST changeIntention(AI_INTENTION_CAST, request, target); final Point3D p = request.getSkillWorldPosition(); if (p != null) { // normally magicskilluse packet turns char client side but for these skills, it doesn't (even // with correct target) _actor.setHeading( Util.calculateHeadingFrom(_actor.getX(), _actor.getY(), p.getX(), p.getY())); _actor.broadcastPacket(new ValidateLocation(_actor)); } // Launch the Think Event notifyEvent(CtrlEvent.EVT_THINK, null); }
protected void init(L2Character actor) { switch (((L2NpcTemplate) actor.getTemplate()).getAI()) { case FIGHTER: isFighter = true; break; case MAGE: isMage = true; break; case CORPSE: case BALANCED: isBalanced = true; break; case ARCHER: isArcher = true; break; case HEALER: isHealer = true; break; default: isFighter = true; break; } // water movement analysis if (actor instanceof L2Npc) { switch (((L2Npc) actor).getNpcId()) { case 20314: // Great White Shark case 20849: // Light Worm cannotMoveOnLand = true; break; default: cannotMoveOnLand = false; break; } } final ArrayList<L2Skill> generalSkills0 = L2Collections.newArrayList(); final ArrayList<L2Skill> buffSkills0 = L2Collections.newArrayList(); final ArrayList<L2Skill> debuffSkills0 = L2Collections.newArrayList(); final ArrayList<L2Skill> cancelSkills0 = L2Collections.newArrayList(); final ArrayList<L2Skill> healSkills0 = L2Collections.newArrayList(); // final ArrayList<L2Skill> trickSkills0 = L2Collections.newArrayList(); final ArrayList<L2Skill> generalDisablers0 = L2Collections.newArrayList(); final ArrayList<L2Skill> sleepSkills0 = L2Collections.newArrayList(); final ArrayList<L2Skill> rootSkills0 = L2Collections.newArrayList(); final ArrayList<L2Skill> muteSkills0 = L2Collections.newArrayList(); final ArrayList<L2Skill> resurrectSkills0 = L2Collections.newArrayList(); // skill analysis for (L2Skill sk : actor.getAllSkills()) { if (sk.isPassive()) continue; int castRange = sk.getCastRange(); boolean hasLongRangeDamageSkill = false; switch (sk.getSkillType()) { case HEAL: case HEAL_PERCENT: case HEAL_STATIC: case BALANCE_LIFE: case HOT: healSkills0.add(sk); hasHealOrResurrect = true; continue; // won't be considered something for fighting case BUFF: buffSkills0.add(sk); continue; // won't be considered something for fighting case PARALYZE: case STUN: // hardcoding petrification until improvements are made to // EffectTemplate... petrification is totally different for // AI than paralyze switch (sk.getId()) { case 367: case 4111: case 4383: case 4616: case 4578: sleepSkills0.add(sk); break; default: generalDisablers0.add(sk); break; } break; case MUTE: muteSkills0.add(sk); break; case SLEEP: sleepSkills0.add(sk); break; case ROOT: rootSkills0.add(sk); break; case FEAR: // could be used as an alternative for healing? case CONFUSION: // trickSkills.add(sk); case DEBUFF: debuffSkills0.add(sk); break; case CANCEL: case MAGE_BANE: case WARRIOR_BANE: case NEGATE: cancelSkills0.add(sk); break; case RESURRECT: resurrectSkills0.add(sk); hasHealOrResurrect = true; break; case NOTDONE: case COREDONE: continue; // won't be considered something for fighting default: generalSkills0.add(sk); hasLongRangeDamageSkill = true; break; } if (castRange > 70) { hasLongRangeSkills = true; if (hasLongRangeDamageSkill) hasLongRangeDamageSkills = true; } if (castRange > maxCastRange) maxCastRange = castRange; } // Because of missing skills, some mages/balanced cannot play like mages if (!hasLongRangeDamageSkills && isMage) { isBalanced = true; isMage = false; isFighter = false; } if (!hasLongRangeSkills && (isMage || isBalanced)) { isBalanced = false; isMage = false; isFighter = true; } if (generalSkills0.isEmpty() && isMage) { isBalanced = true; isMage = false; } generalSkills = convert(generalSkills0); buffSkills = convert(buffSkills0); debuffSkills = convert(debuffSkills0); cancelSkills = convert(cancelSkills0); healSkills = convert(healSkills0); // this.trickSkills = convert(trickSkills0); generalDisablers = convert(generalDisablers0); sleepSkills = convert(sleepSkills0); rootSkills = convert(rootSkills0); muteSkills = convert(muteSkills0); resurrectSkills = convert(resurrectSkills0); }