/*
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 java.awt.Point;
import java.util.concurrent.ScheduledFuture;
import client.ISkill;
import client.MapleCharacter;
import client.MapleCharacter.CancelCooldownAction;
import client.MapleClient;
import client.MapleStat;
import client.SkillFactory;
import constants.skills.Brawler;
import constants.skills.Buccaneer;
import constants.skills.Corsair;
import constants.skills.DarkKnight;
import constants.skills.Hero;
import constants.skills.Paladin;
import constants.skills.Priest;
import net.AbstractMaplePacketHandler;
import net.server.Channel;
import net.server.MapleParty;
import net.server.MaplePartyCharacter;
import net.server.Server;
import server.MapleStatEffect;
import server.TimerManager;
import server.life.MapleMonster;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer();
chr.getAutobanManager().setTimestamp(4, slea.readInt());
int skillid = slea.readInt();
Point pos = null;
int __skillLevel = slea.readByte();
ISkill skill = SkillFactory.getSkill(skillid);
int skillLevel = chr.getSkillLevel(skill);
if (skillid % 10000000 == 1010 || skillid % 10000000 == 1011) {
skillLevel = 1;
chr.setDojoEnergy(0);
c.announce(MaplePacketCreator.getEnergy("energy", 0));
}
if (skillLevel == 0 || skillLevel != __skillLevel)
return;
MapleStatEffect effect = skill.getEffect(skillLevel);
if (effect.getCooldown() > 0) {
if (chr.skillisCooling(skillid)) {
return;
} else if (skillid != Corsair.BATTLE_SHIP) {
c.announce(MaplePacketCreator.skillCooldown(skillid, effect.getCooldown()));
ScheduledFuture<?> timer = TimerManager.getInstance().schedule(new CancelCooldownAction(c.getPlayer(), skillid), effect.getCooldown() * 1000);
chr.addCooldown(skillid, System.currentTimeMillis(), effect.getCooldown() * 1000, timer);
}
}
if (skillid == Hero.MONSTER_MAGNET || skillid == Paladin.MONSTER_MAGNET || skillid == DarkKnight.MONSTER_MAGNET) { // Monster
// Magnet
int num = slea.readInt();
int mobId;
byte success;
for (int i = 0; i < num; i++) {
mobId = slea.readInt();
success = slea.readByte();
chr.getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showMagnet(mobId, success), false);
MapleMonster monster = chr.getMap().getMonsterByOid(mobId);
if (monster != null) {
monster.switchController(c.getPlayer(), monster.isControllerHasAggro());
}
}
byte direction = slea.readByte();
chr.getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showBuffeffect(chr.getId(), skillid, chr.getSkillLevel(skillid), direction), false);
c.announce(MaplePacketCreator.enableActions());
return;
} else if (skillid == Buccaneer.TIME_LEAP) { // Timeleap
MapleParty p = chr.getParty();
if (p != null) {
for (MaplePartyCharacter mpc : p.getMembers()) {
for (Channel cserv : Server.getInstance().getChannelsFromWorld(c.getWorld())) {
if (cserv.getPlayerStorage().getCharacterById(mpc.getId()) != null) {
cserv.getPlayerStorage().getCharacterById(mpc.getId()).removeAllCooldownsExcept(5121010);
}
}
}
}
chr.removeAllCooldownsExcept(Buccaneer.TIME_LEAP);
} else if (skillid == Brawler.MP_RECOVERY) {// MP Recovery
ISkill s = SkillFactory.getSkill(skillid);
MapleStatEffect ef = s.getEffect(chr.getSkillLevel(s));
int lose = chr.getMaxHp() / ef.getX();
chr.setHp(chr.getHp() - lose);
chr.updateSingleStat(MapleStat.HP, chr.getHp());
int gain = lose * (ef.getY() / 100);
chr.setMp(chr.getMp() + gain);
chr.updateSingleStat(MapleStat.MP, chr.getMp());
} else if (skillid % 10000000 == 1004) {
slea.readShort();
}
if (slea.available() == 5) {
pos = new Point(slea.readShort(), slea.readShort());
}
if (chr.isAlive()) {
if (skill.getId() != Priest.MYSTIC_DOOR || chr.canDoor()) {
skill.getEffect(skillLevel).applyTo(c.getPlayer(), pos);
} else {
chr.message("Please wait 5 seconds before casting Mystic Door again");
c.announce(MaplePacketCreator.enableActions());
}
} else {
c.announce(MaplePacketCreator.enableActions());
}
}
}