/* * 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 . */ package handlers.skillhandlers; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import com.l2jserver.Config; import com.l2jserver.gameserver.handler.ISkillHandler; import com.l2jserver.gameserver.model.L2Object; import com.l2jserver.gameserver.model.ShotType; import com.l2jserver.gameserver.model.actor.L2Character; import com.l2jserver.gameserver.model.effects.L2Effect; import com.l2jserver.gameserver.model.skills.L2Skill; import com.l2jserver.gameserver.model.skills.L2SkillType; import com.l2jserver.gameserver.model.stats.Env; import com.l2jserver.gameserver.model.stats.Formulas; import com.l2jserver.gameserver.network.SystemMessageId; import com.l2jserver.gameserver.network.serverpackets.SystemMessage; public class Mdam implements ISkillHandler { protected static final Logger _log = Logger.getLogger(Mdam.class.getName()); private static final Logger _logDamage = Logger.getLogger("damage"); private static final L2SkillType[] SKILL_IDS = { L2SkillType.MDAM, L2SkillType.DEATHLINK }; @Override public void useSkill(L2Character activeChar, L2Skill skill, L2Object[] targets) { if (activeChar.isAlikeDead()) { return; } boolean ss = skill.isPhysical() && activeChar.isChargedShot(ShotType.SOULSHOTS); boolean sps = skill.isMagic() && activeChar.isChargedShot(ShotType.SPIRITSHOTS); boolean bss = skill.isMagic() && activeChar.isChargedShot(ShotType.BLESSED_SPIRITSHOTS); for (L2Character target : (L2Character[]) targets) { if (activeChar.isPlayer() && target.isPlayer() && target.getActingPlayer().isFakeDeath()) { target.stopFakeDeath(true); } else if (target.isDead()) { continue; } final boolean mcrit = Formulas.calcMCrit(activeChar.getMCriticalHit(target, skill)); final byte shld = Formulas.calcShldUse(activeChar, target, skill); final byte reflect = Formulas.calcSkillReflect(target, skill); int damage = skill.isStaticDamage() ? (int) skill.getPower() : (int) Formulas.calcMagicDam(activeChar, target, skill, shld, sps, bss, mcrit); // Curse of Divinity Formula (each buff increase +30%) if (!skill.isStaticDamage() && skill.getDependOnTargetBuff()) { damage *= (((target.getBuffCount() * 0.3) + 1.3) / 4); } if (!skill.isStaticDamage() && skill.getMaxSoulConsumeCount() > 0 && activeChar.isPlayer()) { switch (activeChar.getActingPlayer().getSouls()) { case 0: break; case 1: damage *= 1.10; break; case 2: damage *= 1.12; break; case 3: damage *= 1.15; break; case 4: damage *= 1.18; break; default: damage *= 1.20; break; } } // Possibility of a lethal strike Formulas.calcLethalHit(activeChar, target, skill); if (damage > 0) { // Manage attack or cast break of the target (calculating rate, sending message...) if (!target.isRaid() && Formulas.calcAtkBreak(target, damage)) { target.breakAttack(); target.breakCast(); } // vengeance reflected damage // DS: because only skill using vengeanceMdam is Shield Deflect Magic // and for this skill no damage should pass to target, just hardcode it for now if ((reflect & Formulas.SKILL_REFLECT_VENGEANCE) != 0) { activeChar.reduceCurrentHp(damage, target, skill); } else { activeChar.sendDamageMessage(target, damage, mcrit, false, false); target.reduceCurrentHp(damage, activeChar, skill); } if (skill.hasEffects()) { if ((reflect & Formulas.SKILL_REFLECT_SUCCEED) != 0) // reflect skill effects { activeChar.stopSkillEffects(skill.getId()); skill.getEffects(target, activeChar); SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT); sm.addSkillName(skill); activeChar.sendPacket(sm); } else { // activate attacked effects, if any target.stopSkillEffects(skill.getId()); if (Formulas.calcSkillSuccess(activeChar, target, skill, shld, ss, sps, bss)) { skill.getEffects(activeChar, target, new Env(shld, ss, sps, bss)); } else { SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_RESISTED_YOUR_S2); sm.addCharName(target); sm.addSkillName(skill); activeChar.sendPacket(sm); } } } // Logging damage if (Config.LOG_GAME_DAMAGE && activeChar.isPlayable() && damage > Config.LOG_GAME_DAMAGE_THRESHOLD) { LogRecord record = new LogRecord(Level.INFO, ""); record.setParameters(new Object[] { activeChar, " did damage ", damage, skill, " to ", target }); record.setLoggerName("mdam"); _logDamage.log(record); } } } // self Effect :] if (skill.hasSelfEffects()) { final L2Effect effect = activeChar.getFirstEffect(skill.getId()); if (effect != null && effect.isSelfEffect()) { // Replace old effect with new one. effect.exit(); } skill.getEffectsSelf(activeChar); } activeChar.setChargedShot(bss ? ShotType.BLESSED_SPIRITSHOTS : ShotType.SPIRITSHOTS, false); if (skill.isSuicideAttack()) { activeChar.doDie(activeChar); } } @Override public L2SkillType[] getSkillIds() { return SKILL_IDS; } }