/** * Check if the skill can be used * * @return True if the skill can be used */ public boolean canUseSkill() { Properties properties = skillTemplate.getProperties(); if (properties != null && !properties.validate(this)) { log.debug("properties failed"); return false; } if (!preCastCheck()) return false; // check for counter skill if (effector instanceof Player) { Player player = (Player) effector; if (this.skillTemplate.getCounterSkill() != null) { long time = player.getLastCounterSkill(skillTemplate.getCounterSkill()); if ((time + 5000) < System.currentTimeMillis()) { log.debug("chain skill failed, too late"); return false; } } if (skillMethod == SkillMethod.ITEM && duration > 0 && player.getMoveController().isInMove()) { PacketSendUtility.sendPacket( player, SM_SYSTEM_MESSAGE.STR_ITEM_CANCELED(new DescriptionId(getItemTemplate().getNameId()))); return false; } } if (!validateEffectedList()) return false; return true; }
/** Apply effects and perform actions specified in skill template */ protected void endCast() { if (!effector.isCasting() || isCancelled) return; // if target out of range if (skillTemplate == null) return; // Check if target is out of skill range Properties properties = skillTemplate.getProperties(); if (properties != null && !properties.endCastValidate(this)) { effector.getController().cancelCurrentSkill(); return; } if (!validateEffectedList()) { effector.getController().cancelCurrentSkill(); return; } if (!preUsageCheck()) { return; } effector.setCasting(null); if (this.getSkillTemplate().isDeityAvatar() && effector instanceof Player) { AbyssService.rankerSkillAnnounce((Player) effector, this.getSkillTemplate().getNameId()); } /** try removing item, if its not possible return to prevent exploits */ if (effector instanceof Player && skillMethod == SkillMethod.ITEM) { Item item = ((Player) effector).getInventory().getItemByObjId(this.itemObjectId); if (item == null) return; if (item.getActivationCount() > 1) { item.setActivationCount(item.getActivationCount() - 1); } else { if (!((Player) effector) .getInventory() .decreaseByObjectId(item.getObjectId(), 1, ItemUpdateType.DEC_USE)) return; } } /** Create effects and precalculate result */ int spellStatus = 0; int dashStatus = 0; int resistCount = 0; boolean blockedChain = false; boolean blockedStance = false; final List<Effect> effects = new ArrayList<Effect>(); if (skillTemplate.getEffects() != null) { boolean blockAOESpread = false; for (Creature effected : effectedList) { Effect effect = new Effect(this, effected, 0, itemTemplate); if (effected instanceof Player) { if (effect.getEffectResult() == EffectResult.CONFLICT) blockedStance = true; } // Force RESIST status if AOE spell spread must be blocked if (blockAOESpread) effect.setAttackStatus(AttackStatus.RESIST); effect.initialize(); final int worldId = effector.getWorldId(); final int instanceId = effector.getInstanceId(); effect.setWorldPosition(worldId, instanceId, x, y, z); effects.add(effect); spellStatus = effect.getSpellStatus().getId(); dashStatus = effect.getDashStatus().getId(); // Block AOE propagation if firstTarget resists the spell if ((!blockAOESpread) && (effect.getAttackStatus() == AttackStatus.RESIST) && (isTargetAOE())) blockAOESpread = true; if (effect.getAttackStatus() == AttackStatus.RESIST || effect.getAttackStatus() == AttackStatus.DODGE) { resistCount++; } } if (resistCount == effectedList.size()) { blockedChain = true; blockedPenaltySkill = true; } // exception for point point skills(example Ice Sheet) if (effectedList.isEmpty() && this.isPointPointSkill()) { Effect effect = new Effect(this, null, 0, itemTemplate); effect.initialize(); final int worldId = effector.getWorldId(); final int instanceId = effector.getInstanceId(); effect.setWorldPosition(worldId, instanceId, x, y, z); effects.add(effect); spellStatus = effect.getSpellStatus().getId(); } } if (effector instanceof Player && skillMethod == SkillMethod.CAST) { Player playerEffector = (Player) effector; if (playerEffector.getController().isUnderStance()) { playerEffector.getController().stopStance(); } if (skillTemplate.isStance() && !blockedStance) { playerEffector.getController().startStance(skillTemplate.getSkillId()); } } boolean setCooldowns = true; if (effector instanceof Player) { if (this.isMulticast() && ((Player) effector) .getChainSkills() .getChainCount((Player) effector, this.getSkillTemplate(), this.chainCategory) != 0) { setCooldowns = false; } } // Check Chain Skill Trigger Rate if (CustomConfig.SKILL_CHAIN_TRIGGERRATE) { int chainProb = skillTemplate.getChainSkillProb(); if (this.chainCategory != null && !blockedChain) { this.chainSuccess = Rnd.get(90) < chainProb; } } else { this.chainSuccess = true; } /** set variables for chaincondition check */ if (effector instanceof Player && this.chainSuccess && this.chainCategory != null) { ((Player) effector).getChainSkills().addChainSkill(this.chainCategory, this.isMulticast()); } /** Perform necessary actions (use mp,dp items etc) */ Actions skillActions = skillTemplate.getActions(); if (skillActions != null) { for (Action action : skillActions.getActions()) { if (!action.act(this)) return; } } if (effector instanceof Player) { QuestEnv env = new QuestEnv(effector.getTarget(), (Player) effector, 0, 0); QuestEngine.getInstance().onUseSkill(env, skillTemplate.getSkillId()); } if (setCooldowns) this.setCooldowns(); if (hitTime == 0) applyEffect(effects); else { ThreadPoolManager.getInstance() .schedule( new Runnable() { @Override public void run() { applyEffect(effects); } }, hitTime); } if (skillMethod == SkillMethod.CAST || skillMethod == SkillMethod.ITEM || skillMethod == SkillMethod.CHARGE) sendCastspellEnd(spellStatus, dashStatus, effects); endCondCheck(); if (effector instanceof Npc) SkillAttackManager.afterUseSkill((NpcAI2) ((Npc) effector).getAi2()); }