/*
OrpheusMS: MapleStory Private Server based on OdinMS
Copyright (C) 2012 Aaron Weiss <aaron@deviant-core.net>
Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server.handlers.channel;
import client.ISkill;
import client.MapleBuffStat;
import client.MapleCharacter;
import client.MapleCharacter.CancelCooldownAction;
import client.MapleClient;
import client.MapleJob;
import client.MapleStat;
import client.SkillFactory;
import constants.skills.Crusader;
import constants.skills.DawnWarrior;
import constants.skills.DragonKnight;
import constants.skills.Hero;
import constants.skills.NightWalker;
import constants.skills.Rogue;
import constants.skills.WindArcher;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import server.MapleBuffStatDelta;
import server.MapleStatEffect;
import server.TimerManager;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
private boolean isFinisher(int skillId) {
return skillId > 1111002 && skillId < 1111007 || skillId == 11111002 || skillId == 11111003;
}
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter player = c.getPlayer();
AttackInfo attack = parseDamage(slea, player, false);
player.getMap().broadcastMessage(player, MaplePacketCreator.closeRangeAttack(player, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, attack.speed, attack.direction, attack.display), false, true);
int numFinisherOrbs = 0;
Integer comboBuff = player.getBuffedValue(MapleBuffStat.COMBO);
if (isFinisher(attack.skill)) {
if (comboBuff != null) {
numFinisherOrbs = comboBuff.intValue() - 1;
}
player.handleOrbconsume();
} else if (attack.numAttacked > 0) {
if (attack.skill != 1111008 && comboBuff != null) {
int orbcount = player.getBuffedValue(MapleBuffStat.COMBO);
int oid = player.isCygnus() ? DawnWarrior.COMBO : Crusader.COMBO;
int advcomboid = player.isCygnus() ? DawnWarrior.ADVANCED_COMBO : Hero.ADVANCED_COMBO;
ISkill combo = SkillFactory.getSkill(oid);
ISkill advcombo = SkillFactory.getSkill(advcomboid);
MapleStatEffect ceffect = null;
int advComboSkillLevel = player.getSkillLevel(advcombo);
if (advComboSkillLevel > 0) {
ceffect = advcombo.getEffect(advComboSkillLevel);
} else {
ceffect = combo.getEffect(player.getSkillLevel(combo));
}
if (orbcount < ceffect.getX() + 1) {
int neworbcount = orbcount + 1;
if (advComboSkillLevel > 0 && ceffect.makeChanceResult()) {
if (neworbcount <= ceffect.getX()) {
neworbcount++;
}
}
int duration = combo.getEffect(player.getSkillLevel(oid)).getDuration();
List<MapleBuffStatDelta> stat = Collections.singletonList(new MapleBuffStatDelta(MapleBuffStat.COMBO, neworbcount));
player.setBuffedValue(MapleBuffStat.COMBO, neworbcount);
duration -= (int) (System.currentTimeMillis() - player.getBuffedStarttime(MapleBuffStat.COMBO));
c.announce(MaplePacketCreator.giveBuff(oid, duration, stat));
player.getMap().broadcastMessage(player, MaplePacketCreator.giveForeignBuff(player.getId(), stat), false);
}
} else if (player.getSkillLevel(player.isCygnus() ? SkillFactory.getSkill(15100004) : SkillFactory.getSkill(5110001)) > 0 && (player.getJob().isA(MapleJob.MARAUDER) || player.getJob().isA(MapleJob.THUNDERBREAKER2))) {
for (int i = 0; i < attack.numAttacked; i++) {
player.handleEnergyChargeGain();
}
}
}
if (attack.numAttacked > 0 && attack.skill == DragonKnight.SACRIFICE) {
int totDamageToOneMonster = 0; // sacrifice attacks only 1 mob with
// 1 attack
final Iterator<List<Integer>> dmgIt = attack.allDamage.values().iterator();
if (dmgIt.hasNext()) {
totDamageToOneMonster = dmgIt.next().get(0).intValue();
}
int remainingHP = player.getHp() - totDamageToOneMonster * attack.getAttackEffect(player, null).getX() / 100;
if (remainingHP > 1) {
player.setHp(remainingHP);
} else {
player.setHp(1);
}
player.updateSingleStat(MapleStat.HP, player.getHp());
player.checkBerserk();
}
if (attack.numAttacked > 0 && attack.skill == 1211002) {
boolean advcharge_prob = false;
int advcharge_level = player.getSkillLevel(SkillFactory.getSkill(1220010));
if (advcharge_level > 0) {
advcharge_prob = SkillFactory.getSkill(1220010).getEffect(advcharge_level).makeChanceResult();
}
if (!advcharge_prob) {
player.cancelEffectFromBuffStat(MapleBuffStat.WK_CHARGE);
}
}
int attackCount = 1;
if (attack.skill != 0) {
attackCount = attack.getAttackEffect(player, null).getAttackCount();
}
if (numFinisherOrbs == 0 && isFinisher(attack.skill)) {
return;
}
if (attack.skill > 0) {
ISkill skill = SkillFactory.getSkill(attack.skill);
MapleStatEffect effect_ = skill.getEffect(player.getSkillLevel(skill));
if (effect_.getCooldown() > 0) {
if (player.skillisCooling(attack.skill)) {
return;
} else {
c.announce(MaplePacketCreator.skillCooldown(attack.skill, effect_.getCooldown()));
player.addCooldown(attack.skill, System.currentTimeMillis(), effect_.getCooldown() * 1000, TimerManager.getInstance().schedule(new CancelCooldownAction(player, attack.skill), effect_.getCooldown() * 1000));
}
}
}
if ((player.getSkillLevel(SkillFactory.getSkill(NightWalker.VANISH)) > 0 || player.getSkillLevel(SkillFactory.getSkill(WindArcher.WIND_WALK)) > 0 || player.getSkillLevel(SkillFactory.getSkill(Rogue.DARK_SIGHT)) > 0) && player.getBuffedValue(MapleBuffStat.DARKSIGHT) != null) {// &&
// player.getBuffSource(MapleBuffStat.DARKSIGHT)
// !=
// 9101004
player.cancelEffectFromBuffStat(MapleBuffStat.DARKSIGHT);
player.cancelBuffStats(MapleBuffStat.DARKSIGHT);
}
applyAttack(attack, player, attackCount);
}
}