package handling.channel.handler;
import client.MapleBuffStat;
import client.MapleCharacter;
import client.MapleQuestStatus;
import client.MonsterStatus;
import client.MonsterStatusEffect;
import client.PlayerStats;
import client.Skill;
import client.SkillFactory;
import client.anticheat.CheatTracker;
import client.anticheat.CheatingOffense;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import com.sun.media.sound.SF2Modulator;
import constants.GameConstants;
import constants.ServerConstants;
import handling.world.World;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import server.MapleStatEffect;
import server.Randomizer;
import server.life.Element;
import server.life.ElementalEffectiveness;
import server.life.MapleMonster;
import server.life.MapleMonsterStats;
import server.maps.MapleMap;
import server.maps.MapleMapItem;
import server.maps.MapleMapObject;
import server.maps.MapleMapObjectType;
import server.quest.MapleQuest;
import tools.AttackPair;
import static tools.HexTool.getByteArrayFromHexString;
import tools.Pair;
import tools.Triple;
import tools.data.LittleEndianAccessor;
import tools.packet.CField;
import tools.packet.CWvsContext;
public class DamageParse {
@SuppressWarnings("empty-statement")
public static void applyAttack(AttackInfo attack, Skill theSkill, MapleCharacter player, int attackCount, double maxDamagePerMonster, MapleStatEffect effect, AttackType attack_type) {
if (!player.isAlive()) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACKING_WHILE_DEAD);
return;
}
if ((attack.real) && (GameConstants.getAttackDelay(attack.skill, theSkill) >= 100)) {
player.getCheatTracker().checkAttack(attack.skill, attack.lastAttackTickCount);
}
if (attack.skill != 0) {
if (effect == null) {
player.getClient().getSession().write(CWvsContext.enableActions());
return;
}
if (GameConstants.isMulungSkill(attack.skill)) {
if (player.getMapId() / 10000 != 92502) {
return;
}
if (player.getMulungEnergy() < 10000) {
return;
}
player.mulung_EnergyModify(false);
} else if (GameConstants.isPyramidSkill(attack.skill)) {
if (player.getMapId() / 1000000 != 926) {
return;
}
if ((player.getPyramidSubway() != null) && (player.getPyramidSubway().onSkillUse(player)));
} else if (GameConstants.isInflationSkill(attack.skill)) {
if (player.getBuffedValue(MapleBuffStat.GIANT_POTION) != null);
} else if ((attack.targets > effect.getMobCount()) && (attack.skill != 1211002) && (attack.skill != 1220010)) {
player.getCheatTracker().registerOffense(CheatingOffense.MISMATCHING_BULLETCOUNT);
return;
}
}
if (player.getClient().getChannelServer().isAdminOnly()) {
player.dropMessage(-1, new StringBuilder().append("Animation: ").append(Integer.toHexString((attack.display & 0x8000) != 0 ? attack.display - 32768 : attack.display)).toString());
}
boolean useAttackCount = (attack.skill != 4211006) && (attack.skill != 3221007) && (attack.skill != 23121003) && ((attack.skill != 1311001) || (player.getJob() != 132)) && (attack.skill != 3211006);
if ((attack.hits > 0) && (attack.targets > 0)) {
if (!player.getStat().checkEquipDurabilitys(player, -1)) {
player.dropMessage(5, "An item has run out of durability but has no inventory room to go to.");
return;
}
}
int totDamage = 0;
MapleMap map = player.getMap();
if (attack.skill == 4211006) {
for (AttackPair oned : attack.allDamage) {
if (oned.attack == null) {
MapleMapObject mapobject = map.getMapObject(oned.objectid, MapleMapObjectType.ITEM);
if (mapobject != null) {
MapleMapItem mapitem = (MapleMapItem) mapobject;
mapitem.getLock().lock();
try {
if (mapitem.getMeso() > 0) {
if (mapitem.isPickedUp()) {
return;
}
map.removeMapObject(mapitem);
map.broadcastMessage(CField.explodeDrop(mapitem.getObjectId()));
mapitem.setPickedUp(true);
} else {
player.getCheatTracker().registerOffense(CheatingOffense.ETC_EXPLOSION);
return;
}
} finally {
mapitem.getLock().unlock();
}
} else {
player.getCheatTracker().registerOffense(CheatingOffense.EXPLODING_NONEXISTANT);
return;
}
}
}
}
int totDamageToOneMonster = 0;
long hpMob = 0L;
PlayerStats stats = player.getStat();
int CriticalDamage = stats.passive_sharpeye_percent();
int ShdowPartnerAttackPercentage = 0;
if ((attack_type == AttackType.RANGED_WITH_SHADOWPARTNER) || (attack_type == AttackType.NON_RANGED_WITH_MIRROR)) {
MapleStatEffect shadowPartnerEffect = player.getStatForBuff(MapleBuffStat.SHADOWPARTNER);
if (shadowPartnerEffect != null) {
ShdowPartnerAttackPercentage += shadowPartnerEffect.getX();
}
attackCount /= 2;
}
ShdowPartnerAttackPercentage *= (CriticalDamage + 100) / 100;
if (attack.skill == 4221001) {
ShdowPartnerAttackPercentage *= 10;
}
double maxDamagePerHit = 0.0D;
int antiKS = 0;
for (AttackPair oned : attack.allDamage) {
MapleMonster monster = map.getMonsterByOid(oned.objectid);
if (ServerConstants.AntiKS) {
MapleQuestStatus statt = player.getQuestNoAdd(MapleQuest.getInstance(732648172));
boolean antiks;
if (statt == null || statt.getCustomData() == null) {
antiks = false;
statt.setCustomData(antiks + ";" + 0);
} else {
String[] statss = statt.getCustomData().split(";");
try {
antiks = Boolean.parseBoolean(statss[0]);
} catch (Exception ex) {
antiks = false;
}
if (monster.getBelongsToSomeone() && monster.getBelongsTo() != player.getId()
&& (player.getParty() == null
|| player.getParty().getMemberById(monster.getBelongsTo()) == null)
&& !player.isGM()) {
monster.setBelongsTo(player);
antiKS++;
statt.setCustomData(antiks + ";" + (Integer.parseInt(statss[1]) + 1));
}
}
if (monster.getBelongsToSomeone()) {
if (monster.getBelongsTo() != player.getId() && !player.isGM()) {
player.dropMessage(5, "You cannot hit this monster because it belongs to someone else.");
continue;
}
if (player.isGM()) {
player.dropMessage(5, "You are attacking a monster who was marked by another player.");
}
}
}
if ((monster != null) && (monster.getLinkCID() <= 0)) {
totDamageToOneMonster = 0;
hpMob = monster.getMobMaxHp();
MapleMonsterStats monsterstats = monster.getStats();
int fixeddmg = monsterstats.getFixedDamage();
boolean Tempest = (monster.getStatusSourceID(MonsterStatus.FREEZE) == 21120006) || (attack.skill == 21120006) || (attack.skill == 1221011);
if ((!Tempest) && (!player.isGM())) {
if (((player.getJob() >= 3200) && (player.getJob() <= 3212) && (!monster.isBuffed(MonsterStatus.DAMAGE_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.MAGIC_DAMAGE_REFLECT))) || (attack.skill == 3221007) || (attack.skill == 23121003) || (((player.getJob() < 3200) || (player.getJob() > 3212)) && (!monster.isBuffed(MonsterStatus.DAMAGE_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.WEAPON_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.WEAPON_DAMAGE_REFLECT)))) {
maxDamagePerHit = CalculateMaxWeaponDamagePerHit(player, monster, attack, theSkill, effect, maxDamagePerMonster, Integer.valueOf(CriticalDamage));
} else {
maxDamagePerHit = 1.0D;
}
}
byte overallAttackCount = 0;
int criticals = 0;
for (Pair eachde : oned.attack) {
Integer eachd = (Integer) eachde.left;
overallAttackCount = (byte) (overallAttackCount + 1);
if (((Boolean) eachde.right).booleanValue()) {
criticals++;
}
if ((useAttackCount) && (overallAttackCount - 1 == attackCount)) {
maxDamagePerHit = maxDamagePerHit / 100.0D * (ShdowPartnerAttackPercentage * (monsterstats.isBoss() ? stats.bossdam_r : stats.dam_r) / 100.0D);
}
if (fixeddmg != -1) {
if (monsterstats.getOnlyNoramlAttack()) {
eachd = Integer.valueOf(attack.skill != 0 ? 0 : fixeddmg);
} else {
eachd = Integer.valueOf(fixeddmg);
}
} else if (monsterstats.getOnlyNoramlAttack()) {
eachd = Integer.valueOf(attack.skill != 0 ? 0 : Math.min(eachd.intValue(), (int) maxDamagePerHit));
} else if (!player.isGM()) {
if (Tempest) {
if (eachd.intValue() > monster.getMobMaxHp()) {
eachd = Integer.valueOf((int) Math.min(monster.getMobMaxHp(), 2147483647L));
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE);
}
} else if (((player.getJob() >= 3200) && (player.getJob() <= 3212) && (!monster.isBuffed(MonsterStatus.DAMAGE_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.MAGIC_DAMAGE_REFLECT))) || (attack.skill == 23121003) || (((player.getJob() < 3200) || (player.getJob() > 3212)) && (!monster.isBuffed(MonsterStatus.DAMAGE_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.WEAPON_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.WEAPON_DAMAGE_REFLECT)))) {
if (eachd.intValue() > maxDamagePerHit) {
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE, new StringBuilder().append("[Damage: ").append(eachd).append(", Expected: ").append(maxDamagePerHit).append(", Mob: ").append(monster.getId()).append("] [Job: ").append(player.getJob()).append(", Level: ").append(player.getLevel()).append(", Skill: ").append(attack.skill).append("]").toString());
if (attack.real) {
player.getCheatTracker().checkSameDamage(eachd.intValue(), maxDamagePerHit);
}
if (eachd.intValue() > maxDamagePerHit * 2.0D) {
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_2, new StringBuilder().append("[Damage: ").append(eachd).append(", Expected: ").append(maxDamagePerHit).append(", Mob: ").append(monster.getId()).append("] [Job: ").append(player.getJob()).append(", Level: ").append(player.getLevel()).append(", Skill: ").append(attack.skill).append("]").toString());
eachd = Integer.valueOf((int) (maxDamagePerHit * 2.0D));
if (eachd.intValue() >= 2499999) {
player.getClient().getSession().close();
}
}
}
} else if (eachd.intValue() > maxDamagePerHit) {
eachd = Integer.valueOf((int) maxDamagePerHit);
}
}
if (player == null) {
return;
}
totDamageToOneMonster += eachd.intValue();
if (((eachd.intValue() == 0) || (monster.getId() == 9700021)) && (player.getPyramidSubway() != null)) {
player.getPyramidSubway().onMiss(player);
}
}
totDamage += totDamageToOneMonster;
player.checkMonsterAggro(monster);
if ((GameConstants.getAttackDelay(attack.skill, theSkill) >= 100) && (!GameConstants.isNoDelaySkill(attack.skill)) && (attack.skill != 3101005) && (!monster.getStats().isBoss()) && (player.getTruePosition().distanceSq(monster.getTruePosition()) > GameConstants.getAttackRange(effect, player.getStat().defRange))) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACK_FARAWAY_MONSTER, new StringBuilder().append("[Distance: ").append(player.getTruePosition().distanceSq(monster.getTruePosition())).append(", Expected Distance: ").append(GameConstants.getAttackRange(effect, player.getStat().defRange)).append(" Job: ").append(player.getJob()).append("]").toString());
}
if (player.getSkillLevel(36110005) > 0) {
Skill skill = SkillFactory.getSkill(36110005);
MapleStatEffect eff = skill.getEffect(player.getSkillLevel(skill));
if (player.getLastCombo() + 5000 < System.currentTimeMillis()) {
monster.setTriangulation(0);
//player.clearDamageMeters();
}
if (eff.makeChanceResult()) {
player.setLastCombo(System.currentTimeMillis());
if (monster.getTriangulation() < 3) {
monster.setTriangulation(monster.getTriangulation() + 1);
}
monster.applyStatus(player, new MonsterStatusEffect(MonsterStatus.DARKNESS, eff.getX(), eff.getSourceId(), null, false), false, eff.getY() * 1000, true, eff);
monster.applyStatus(player, new MonsterStatusEffect(MonsterStatus.TRIANGULATION, monster.getTriangulation(), eff.getSourceId(), null, false), false, eff.getY() * 1000, true, eff);
}
}
if (player.getBuffedValue(MapleBuffStat.PICKPOCKET) != null) {
switch (attack.skill) {
case 0:
case 4001334:
case 4201005:
case 4211002:
case 4211004:
case 4221003:
case 4221007:
handlePickPocket(player, monster, oned);
}
}
if ((totDamageToOneMonster > 0) || (attack.skill == 1221011) || (attack.skill == 21120006)) {
if (GameConstants.isDemonSlayer(player.getJob())) {
player.handleForceGain(monster.getObjectId(), attack.skill);
}
if ((GameConstants.isPhantom(player.getJob())) && (attack.skill != 24120002) && (attack.skill != 24100003)) {
player.handleCardStack();
}
if (GameConstants.isKaiser(player.getJob())) {
player.handleKaiserCombo();
}
if (attack.skill != 1221011) {
monster.damage(player, totDamageToOneMonster, true, attack.skill);
} else {
monster.damage(player, monster.getStats().isBoss() ? 500000L : monster.getHp() - 1L, true, attack.skill);
}
if (monster.isBuffed(MonsterStatus.WEAPON_DAMAGE_REFLECT)) {
player.addHP(-(7000 + Randomizer.nextInt(8000)));
}
player.onAttack(monster.getMobMaxHp(), monster.getMobMaxMp(), attack.skill, monster.getObjectId(), totDamage, 0);
switch (attack.skill) {
case 4001002:
case 4001334:
case 4001344:
case 4111005:
case 4121007:
case 4201005:
case 4211002:
case 4221001:
case 4221007:
case 4301001:
case 4311002:
case 4311003:
case 4331000:
case 4331004:
case 4331005:
case 4331006:
case 4341002:
case 4341004:
case 4341005:
case 4341009:
case 14001004:
case 14111002:
case 14111005:
int[] skills = {4120005, 4220005, 4340001, 14110004};
for (int i : skills) {
Skill skill = SkillFactory.getSkill(i);
if (player.getTotalSkillLevel(skill) > 0) {
MapleStatEffect venomEffect = skill.getEffect(player.getTotalSkillLevel(skill));
if (!venomEffect.makeChanceResult()) {
break;
}
monster.applyStatus(player, new MonsterStatusEffect(MonsterStatus.POISON, Integer.valueOf(1), i, null, false), true, venomEffect.getDuration(), true, venomEffect);
break;
}
}
break;
case 4201004:
monster.handleSteal(player);
break;
case 21000002:
case 21100001:
case 21100002:
case 21100004:
case 21110002:
case 21110003:
case 21110004:
case 21110006:
case 21110007:
case 21110008:
case 21120002:
case 21120005:
case 21120006:
case 21120009:
case 21120010:
if ((player.getBuffedValue(MapleBuffStat.WK_CHARGE) != null) && (!monster.getStats().isBoss())) {
MapleStatEffect eff = player.getStatForBuff(MapleBuffStat.WK_CHARGE);
if (eff != null) {
monster.applyStatus(player, new MonsterStatusEffect(MonsterStatus.SPEED, Integer.valueOf(eff.getX()), eff.getSourceId(), null, false), false, eff.getY() * 1000, true, eff);
}
}
if ((player.getBuffedValue(MapleBuffStat.BODY_PRESSURE) != null) && (!monster.getStats().isBoss())) {
MapleStatEffect eff = player.getStatForBuff(MapleBuffStat.BODY_PRESSURE);
if ((eff != null) && (eff.makeChanceResult()) && (!monster.isBuffed(MonsterStatus.NEUTRALISE))) {
monster.applyStatus(player, new MonsterStatusEffect(MonsterStatus.NEUTRALISE, Integer.valueOf(1), eff.getSourceId(), null, false), false, eff.getX() * 1000, true, eff);
}
}
break;
}
// int randomDMG = Randomizer.nextInt(player.getDamage2() - player.getReborns() + 1) + player.getReborns();
// monster.damage(player, randomDMG, true, attack.skill);
// if (player.getshowdamage() == 1)
// player.dropMessage(5, new StringBuilder().append("You have done ").append(randomDMG).append(" extra RB damage! (disable/enable this with @dmgnotice)").toString());
// }
//else {
// if (player.getDamage() > 2147483647L) {
// long randomDMG = player.getDamage();
// monster.damage(player, monster.getMobMaxHp(), true, attack.skill);
// if (player.getshowdamage() == 1) {
// player.dropMessage(5, new StringBuilder().append("You have done ").append(randomDMG).append(" extra RB damage! (disable/enable this with @dmgnotice)").toString());
// }
// }
if (totDamageToOneMonster > 0) {
Item weapon_ = player.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -11);
if (weapon_ != null) {
MonsterStatus stat = GameConstants.getStatFromWeapon(weapon_.getItemId());
if ((stat != null) && (Randomizer.nextInt(100) < GameConstants.getStatChance())) {
MonsterStatusEffect monsterStatusEffect = new MonsterStatusEffect(stat, Integer.valueOf(GameConstants.getXForStat(stat)), GameConstants.getSkillForStat(stat), null, false);
monster.applyStatus(player, monsterStatusEffect, false, 10000L, false, null);
}
}
if (player.getBuffedValue(MapleBuffStat.BLIND) != null) {
MapleStatEffect eff = player.getStatForBuff(MapleBuffStat.BLIND);
if ((eff != null) && (eff.makeChanceResult())) {
MonsterStatusEffect monsterStatusEffect = new MonsterStatusEffect(MonsterStatus.ACC, Integer.valueOf(eff.getX()), eff.getSourceId(), null, false);
monster.applyStatus(player, monsterStatusEffect, false, eff.getY() * 1000, true, eff);
}
}
if (player.getBuffedValue(MapleBuffStat.HAMSTRING) != null) {
MapleStatEffect eff = player.getStatForBuff(MapleBuffStat.HAMSTRING);
if ((eff != null) && (eff.makeChanceResult())) {
MonsterStatusEffect monsterStatusEffect = new MonsterStatusEffect(MonsterStatus.SPEED, Integer.valueOf(eff.getX()), 3121007, null, false);
monster.applyStatus(player, monsterStatusEffect, false, eff.getY() * 1000, true, eff);
}
}
if ((player.getJob() == 121) || (player.getJob() == 122)) {
Skill skill = SkillFactory.getSkill(1211006);
if (player.isBuffFrom(MapleBuffStat.WK_CHARGE, skill)) {
MapleStatEffect eff = skill.getEffect(player.getTotalSkillLevel(skill));
MonsterStatusEffect monsterStatusEffect = new MonsterStatusEffect(MonsterStatus.FREEZE, Integer.valueOf(1), skill.getId(), null, false);
monster.applyStatus(player, monsterStatusEffect, false, eff.getY() * 2000, true, eff);
}
}
}
if ((effect != null) && (effect.getMonsterStati().size() > 0) && (effect.makeChanceResult())) {
for (Map.Entry z : effect.getMonsterStati().entrySet()) {
monster.applyStatus(player, new MonsterStatusEffect((MonsterStatus) z.getKey(), (Integer) z.getValue(), theSkill.getId(), null, false), effect.isPoison(), effect.getDuration(), true, effect);
}
}
}
}
}
if (GameConstants.isLuminous(player.getJob())) {
if (player.getBuffedValue(MapleBuffStat.DARK_CRESCENDO) != 1); {
MapleStatEffect crescendo = SkillFactory.getSkill(27121005).getEffect(player.getSkillLevel(27121005));
if (crescendo != null) {
if (crescendo.makeChanceResult()) {
player.setLastCombo(System.currentTimeMillis());
if (player.acaneAim <= 29) {
player.acaneAim++;
crescendo.applyTo(player);
}
}
}
}
}
if (player.getJob() >= 1500 && player.getJob() <= 1512) {
MapleStatEffect crescendo = SkillFactory.getSkill(15001022).getEffect(player.getSkillLevel(15001022));
if (crescendo != null) {
if (crescendo.makeChanceResult()) {
player.setLastCombo(System.currentTimeMillis());
if (player.acaneAim <= 3) {
player.acaneAim++;
crescendo.applyTo(player);
}
}
}
}
if (player.getJob() >= 420 && player.getJob() <= 422) {
MapleStatEffect crescendo = SkillFactory.getSkill(4200013).getEffect(player.getSkillLevel(4200013));
if (crescendo != null) {
if (crescendo.makeChanceResult()) {
player.setLastCombo(System.currentTimeMillis());
if (player.acaneAim <= 30) {
player.acaneAim++;
crescendo.applyTo(player);
}
}
}
}
if ((attack.skill == 4331003) && ((hpMob <= 0L) || (totDamageToOneMonster < hpMob))) {
return;
}
if ((hpMob > 0L) && (totDamageToOneMonster > 0)) {
player.afterAttack(attack.targets, attack.hits, attack.skill);
}
if ((attack.skill != 0) && ((attack.targets > 0) || ((attack.skill != 4331003) && (attack.skill != 4341002))) && (!GameConstants.isNoDelaySkill(attack.skill))) {
boolean applyTo = effect.applyTo(player, attack.position);
}
if ((totDamage > 1) && (GameConstants.getAttackDelay(attack.skill, theSkill) >= 100)) {
CheatTracker tracker = player.getCheatTracker();
tracker.setAttacksWithoutHit(true);
if (tracker.getAttacksWithoutHit() > 1000) {
tracker.registerOffense(CheatingOffense.ATTACK_WITHOUT_GETTING_HIT, Integer.toString(tracker.getAttacksWithoutHit()));
}
}
if (player.getSkillLevel(4100011) > 0) { //마크 오브 어쌔신
MapleStatEffect eff = SkillFactory.getSkill(4100011).getEffect(player.getSkillLevel(4100011));
if (eff.makeChanceResult()) {
for (Map.Entry z : effect.getMonsterStati().entrySet()) {
for (AttackPair ap : attack.allDamage) {
final MapleMonster monster = player.getMap().getMonsterByOid(ap.objectid);
// monster.applyStatus(player, new MonsterStatusEffect((MonsterStatus)z.getKey(), (Integer)z.getValue(), theSkill.getId(), null, false), effect.isPoison(), effect.getDuration(), true, effect);
// }
//MonsterStatusEffect monsterStatusEffect = new MonsterStatusEffect(Collections.singletonMap(MonsterStatus.POISON, eff.getSkillStats().getStats("dot")), SkillFactory.getSkill(4100011), null, false);
//monsterStatusEffect.setOwnerId(player.getId()); //cid가 맞아야 보이므로
// monster.applyStatus(player, new MonsterStatusEffect(Collections.singletonMap(MonsterStatus.POISON, eff.getourceId().getStats("dot")), SkillFactory.getSkill(4100011), null, false), true, eff.getDuration(), false);
// monster.applyStatus(player, new MonsterStatusEffect(MonsterStatus.POISON, Integer.valueOf(eff.getX()), eff.getSourceId(), null, false), false, eff.getY() * 1000, true, eff);
monster.applyStatus(player, new MonsterStatusEffect((MonsterStatus)z.getKey(), (Integer)z.getValue(), theSkill.getId(), null, false), effect.isPoison(), effect.getDuration(), true, effect);
}
}}
int bulletCount = eff.getBulletCount();
for (AttackPair ap : attack.allDamage) {
final MapleMonster source = player.getMap().getMonsterByOid(ap.objectid);
//source.get
final MonsterStatusEffect check = source.getBuff(MonsterStatus.POISON);
// if (check != null && check.getSkill().getId() == 4100011 && check.getOwnerId() == player.getId()) {
if (check != null && check.getSkill() == 4100011 && check.getOwnerId() == player.getId()) { //:3
// player.message("조건 진입");
final List<MapleMapObject> objs = player.getMap().getMapObjectsInRange(player.getPosition(), 500000, Arrays.asList(MapleMapObjectType.MONSTER));
final List<MapleMonster> monsters = new ArrayList<>();
for (int i = 0; i < bulletCount; i++) {
int rand = Randomizer.rand(0, objs.size() - 1);
if (objs.size() < bulletCount) {
if (i < objs.size()) {
monsters.add((MapleMonster) objs.get(i));
}
} else {
monsters.add((MapleMonster) objs.get(rand));
objs.remove(rand);
}
}
if (monsters.size() <= 0) {
CWvsContext.enableActions();
return;
}
final List<Point> points = new ArrayList<>();
for (MapleMonster mob : monsters) {
points.add(mob.getPosition());
}
// player.dropMessage(monsters.size());
// player.dropMessage("시작" + monsters.size());
player.getMap().broadcastMessage(CWvsContext.giveMarkOfTheif(player.getId(), source.getObjectId(), 4100012, monsters, player.getPosition(), monsters.get(0).getPosition(), 2070005));
// player.message("종료");
}
}
}
}
@SuppressWarnings("empty-statement")
public static final void applyAttackMagic(AttackInfo attack, Skill theSkill, MapleCharacter player, MapleStatEffect effect, double maxDamagePerHit) {
if (!player.isAlive()) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACKING_WHILE_DEAD);
return;
}
if ((attack.real) && (GameConstants.getAttackDelay(attack.skill, theSkill) >= 100)) {
player.getCheatTracker().checkAttack(attack.skill, attack.lastAttackTickCount);
}
if (effect.getBulletCount() > 1) {
if ((attack.hits > effect.getBulletCount()) || (attack.targets > effect.getMobCount())) {
player.getCheatTracker().registerOffense(CheatingOffense.MISMATCHING_BULLETCOUNT);
}
} else if (((attack.hits > effect.getAttackCount()) && (effect.getAttackCount() != 0)) || (attack.targets > effect.getMobCount())) {
player.getCheatTracker().registerOffense(CheatingOffense.MISMATCHING_BULLETCOUNT);
return;
}
if ((attack.hits > 0) && (attack.targets > 0) && (!player.getStat().checkEquipDurabilitys(player, -1))) {
player.dropMessage(5, "An item has run out of durability but has no inventory room to go to.");
return;
}
if (GameConstants.isMulungSkill(attack.skill)) {
if (player.getMapId() / 10000 != 92502) {
return;
}
if (player.getMulungEnergy() < 10000) {
return;
}
player.mulung_EnergyModify(false);
} else if (GameConstants.isPyramidSkill(attack.skill)) {
if (player.getMapId() / 1000000 != 926) {
return;
}
if ((player.getPyramidSubway() != null) && (player.getPyramidSubway().onSkillUse(player)));
} else if ((GameConstants.isInflationSkill(attack.skill)) && (player.getBuffedValue(MapleBuffStat.GIANT_POTION) == null)) {
return;
}
if (player.getClient().getChannelServer().isAdminOnly()) {
player.dropMessage(-1, new StringBuilder().append("Animation: ").append(Integer.toHexString((attack.display & 0x8000) != 0 ? attack.display - 32768 : attack.display)).toString());
}
PlayerStats stats = player.getStat();
Element element = player.getBuffedValue(MapleBuffStat.ELEMENT_RESET) != null ? Element.NEUTRAL : theSkill.getElement();
double MaxDamagePerHit = 0.0D;
int totDamage = 0;
int CriticalDamage = stats.passive_sharpeye_percent();
Skill eaterSkill = SkillFactory.getSkill(GameConstants.getMPEaterForJob(player.getJob()));
int eaterLevel = player.getTotalSkillLevel(eaterSkill);
MapleMap map = player.getMap();
int antiKS = 0;
for (AttackPair oned : attack.allDamage) {
MapleMonster monster = map.getMonsterByOid(oned.objectid);
if (ServerConstants.AntiKS) {
MapleQuestStatus statt = player.getQuestNoAdd(MapleQuest.getInstance(732648172));
boolean antiks;
if (statt == null || statt.getCustomData() == null) {
antiks = false;
statt.setCustomData(antiks + ";" + 0);
} else {
String[] statss = statt.getCustomData().split(";");
try {
antiks = Boolean.parseBoolean(statss[0]);
} catch (Exception ex) {
antiks = false;
}
if (monster.getBelongsToSomeone() && monster.getBelongsTo() != player.getId()
&& (player.getParty() == null
|| player.getParty().getMemberById(monster.getBelongsTo()) == null)
&& !player.isGM()) {
monster.setBelongsTo(player);
antiKS++;
statt.setCustomData(antiks + ";" + (Integer.parseInt(statss[1]) + 1));
}
}
if (monster.getBelongsToSomeone()) {
if (monster.getBelongsTo() != player.getId() && !player.isGM()) {
player.dropMessage(5, "You cannot hit this monster because it belongs to someone else.");
continue;
}
if (player.isGM()) {
player.dropMessage(5, "You are attacking a monster who was marked by another player.");
}
}
}
if ((monster != null) && (monster.getLinkCID() <= 0)) {
boolean Tempest = (monster.getStatusSourceID(MonsterStatus.FREEZE) == 21120006) && (!monster.getStats().isBoss());
int totDamageToOneMonster = 0;
MapleMonsterStats monsterstats = monster.getStats();
int fixeddmg = monsterstats.getFixedDamage();
if ((!Tempest) && (!player.isGM())) {
if ((!monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.MAGIC_DAMAGE_REFLECT))) {
MaxDamagePerHit = CalculateMaxMagicDamagePerHit(player, theSkill, monster, monsterstats, stats, element, Integer.valueOf(CriticalDamage), maxDamagePerHit, effect);
} else {
MaxDamagePerHit = 1.0D;
}
}
byte overallAttackCount = 0;
for (Pair eachde : oned.attack) {
Integer eachd = (Integer) eachde.left;
overallAttackCount = (byte) (overallAttackCount + 1);
if (fixeddmg != -1) {
eachd = Integer.valueOf(monsterstats.getOnlyNoramlAttack() ? 0 : fixeddmg);
} else if (monsterstats.getOnlyNoramlAttack()) {
eachd = Integer.valueOf(0);
} else if (!player.isGM()) {
if (Tempest) {
if (eachd.intValue() > monster.getMobMaxHp()) {
eachd = Integer.valueOf((int) Math.min(monster.getMobMaxHp(), 2147483647L));
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_MAGIC);
}
} else if ((!monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) && (!monster.isBuffed(MonsterStatus.MAGIC_DAMAGE_REFLECT))) {
if (eachd.intValue() > MaxDamagePerHit) {
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_MAGIC, new StringBuilder().append("[Damage: ").append(eachd).append(", Expected: ").append(MaxDamagePerHit).append(", Mob: ").append(monster.getId()).append("] [Job: ").append(player.getJob()).append(", Level: ").append(player.getLevel()).append(", Skill: ").append(attack.skill).append("]").toString());
if (attack.real) {
player.getCheatTracker().checkSameDamage(eachd.intValue(), MaxDamagePerHit);
}
if (eachd.intValue() > MaxDamagePerHit * 2.0D) {
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_MAGIC_2, new StringBuilder().append("[Damage: ").append(eachd).append(", Expected: ").append(MaxDamagePerHit).append(", Mob: ").append(monster.getId()).append("] [Job: ").append(player.getJob()).append(", Level: ").append(player.getLevel()).append(", Skill: ").append(attack.skill).append("]").toString());
eachd = Integer.valueOf((int) (MaxDamagePerHit * 2.0D));
if (eachd.intValue() >= 2499999) {
player.getClient().getSession().close();
}
}
}
} else if (eachd.intValue() > MaxDamagePerHit) {
eachd = Integer.valueOf((int) MaxDamagePerHit);
}
}
totDamageToOneMonster += eachd.intValue();
}
totDamage += totDamageToOneMonster;
player.checkMonsterAggro(monster);
if ((GameConstants.getAttackDelay(attack.skill, theSkill) >= 100) && (!GameConstants.isNoDelaySkill(attack.skill)) && (!monster.getStats().isBoss()) && (player.getTruePosition().distanceSq(monster.getTruePosition()) > GameConstants.getAttackRange(effect, player.getStat().defRange))) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACK_FARAWAY_MONSTER, new StringBuilder().append("[Distance: ").append(player.getTruePosition().distanceSq(monster.getTruePosition())).append(", Expected Distance: ").append(GameConstants.getAttackRange(effect, player.getStat().defRange)).append(" Job: ").append(player.getJob()).append("]").toString());
}
if ((attack.skill == 2301002) && (!monsterstats.getUndead())) {
player.getCheatTracker().registerOffense(CheatingOffense.HEAL_ATTACKING_UNDEAD);
return;
}
if (GameConstants.isLuminous(player.getJob())) {
player.handleLuminous(attack.skill);
}
monster.damage(player, totDamage, true, attack.skill);
}
// else if (player.getDamage() > 2147483647L) {
// long randomDMG = player.getDamage();
// monster.damage(player, monster.getMobMaxHp(), true, attack.skill);
// if (player.getshowdamage() == 1) {
// player.dropMessage(5, new StringBuilder().append("You have done ").append(randomDMG).append(" extra damage! (disable/enable this with @dmgnotice)").toString());
// }
// int totDamageToOneMonster1 = 0;
// if (totDamageToOneMonster1 > 0) {
// monster.damage(player, totDamageToOneMonster1, true, attack.skill);
// if (monster.isBuffed(MonsterStatus.MAGIC_DAMAGE_REFLECT)) {
// player.addHP(-(7000 + Randomizer.nextInt(8000)));
// }
// if (player.getBuffedValue(MapleBuffStat.SLOW) != null) {
// MapleStatEffect eff = player.getStatForBuff(MapleBuffStat.SLOW);
//
// if ((eff != null) && (eff.makeChanceResult()) && (!monster.isBuffed(MonsterStatus.SPEED))) {
// monster.applyStatus(player, new MonsterStatusEffect(MonsterStatus.SPEED, Integer.valueOf(eff.getX()), eff.getSourceId(), null, false), false, eff.getY() * 1000, true, eff);
// }
//
// }
//
// player.onAttack(monster.getMobMaxHp(), monster.getMobMaxMp(), attack.skill, monster.getObjectId(), totDamage, 0);
//
// switch (attack.skill) {
// case 2221003:
// monster.setTempEffectiveness(Element.ICE, effect.getDuration());
// break;
// case 2121003:
// monster.setTempEffectiveness(Element.FIRE, effect.getDuration());
// }
//
// if ((effect != null) && (effect.getMonsterStati().size() > 0) && (effect.makeChanceResult()))
// {
// for (Map.Entry z : effect.getMonsterStati().entrySet()) {
// monster.applyStatus(player, new MonsterStatusEffect((MonsterStatus)z.getKey(), (Integer)z.getValue(), theSkill.getId(), null, false), effect.isPoison(), effect.getDuration(), true, effect);
// }
// }
//
// if (eaterLevel > 0) {
// eaterSkill.getEffect(eaterLevel).applyPassive(player, monster);
// }
// }
// }
if (attack.skill != 2301002) {
effect.applyTo(player);
}
if ((totDamage > 1) && (GameConstants.getAttackDelay(attack.skill, theSkill) >= 100)) {
CheatTracker tracker = player.getCheatTracker();
tracker.setAttacksWithoutHit(true);
if (tracker.getAttacksWithoutHit() > 1000) {
tracker.registerOffense(CheatingOffense.ATTACK_WITHOUT_GETTING_HIT, Integer.toString(tracker.getAttacksWithoutHit()));
}
}
}
}
private static double CalculateMaxMagicDamagePerHit(MapleCharacter chr, Skill skill, MapleMonster monster, MapleMonsterStats mobstats, PlayerStats stats, Element elem, Integer sharpEye, double maxDamagePerMonster, MapleStatEffect attackEffect) {
int dLevel = Math.max(mobstats.getLevel() - chr.getLevel(), 0) * 2;
int HitRate = Math.min((int) Math.floor(Math.sqrt(stats.getAccuracy())) - (int) Math.floor(Math.sqrt(mobstats.getEva())) + 100, 100);
if (dLevel > HitRate) {
HitRate = dLevel;
}
HitRate -= dLevel;
if ((HitRate <= 0) && ((!GameConstants.isBeginnerJob(skill.getId() / 10000)) || (skill.getId() % 10000 != 1000))) {
return 0.0D;
}
int CritPercent = sharpEye.intValue();
ElementalEffectiveness ee = monster.getEffectiveness(elem);
double elemMaxDamagePerMob;
switch (ee) {
case IMMUNE:
elemMaxDamagePerMob = 1.0D;
break;
default:
elemMaxDamagePerMob = ElementalStaffAttackBonus(elem, maxDamagePerMonster * ee.getValue(), stats);
}
int MDRate = monster.getStats().getMDRate();
MonsterStatusEffect pdr = monster.getBuff(MonsterStatus.MDEF);
if (pdr != null) {
MDRate += pdr.getX().intValue();
}
elemMaxDamagePerMob -= elemMaxDamagePerMob * (Math.max(MDRate - stats.ignoreTargetDEF - attackEffect.getIgnoreMob(), 0) / 100.0D);
elemMaxDamagePerMob += elemMaxDamagePerMob / 100.0D * CritPercent;
elemMaxDamagePerMob *= (monster.getStats().isBoss() ? chr.getStat().bossdam_r : chr.getStat().dam_r) / 100.0D;
MonsterStatusEffect imprint = monster.getBuff(MonsterStatus.IMPRINT);
if (imprint != null) {
elemMaxDamagePerMob += elemMaxDamagePerMob * imprint.getX().intValue() / 100.0D;
}
elemMaxDamagePerMob += elemMaxDamagePerMob * chr.getDamageIncrease(monster.getObjectId()) / 100.0D;
if (GameConstants.isBeginnerJob(skill.getId() / 10000)) {
switch (skill.getId() % 10000) {
case 1000:
elemMaxDamagePerMob = 40.0D;
break;
case 1020:
elemMaxDamagePerMob = 1.0D;
break;
case 1009:
elemMaxDamagePerMob = monster.getStats().isBoss() ? monster.getMobMaxHp() / 30L * 100L : monster.getMobMaxHp();
}
}
switch (skill.getId()) {
case 32001000:
case 32101000:
case 32111002:
case 32121002:
elemMaxDamagePerMob *= 1.5D;
}
if (elemMaxDamagePerMob > 999999.0D) {
elemMaxDamagePerMob = 999999.0D;
} else if (elemMaxDamagePerMob <= 0.0D) {
elemMaxDamagePerMob = 1.0D;
}
return elemMaxDamagePerMob;
}
private static double ElementalStaffAttackBonus(Element elem, double elemMaxDamagePerMob, PlayerStats stats) {
switch (elem) {
case FIRE:
return elemMaxDamagePerMob / 100.0D * (stats.element_fire + stats.getElementBoost(elem));
case ICE:
return elemMaxDamagePerMob / 100.0D * (stats.element_ice + stats.getElementBoost(elem));
case LIGHTING:
return elemMaxDamagePerMob / 100.0D * (stats.element_light + stats.getElementBoost(elem));
case POISON:
return elemMaxDamagePerMob / 100.0D * (stats.element_psn + stats.getElementBoost(elem));
}
return elemMaxDamagePerMob / 100.0D * (stats.def + stats.getElementBoost(elem));
}
private static void handlePickPocket(MapleCharacter player, MapleMonster mob, AttackPair oned) {
int maxmeso = player.getBuffedValue(MapleBuffStat.PICKPOCKET).intValue();
for (Pair eachde : oned.attack) {
Integer eachd = (Integer) eachde.left;
if ((player.getStat().pickRate >= 100) || (Randomizer.nextInt(99) < player.getStat().pickRate)) {
player.getMap().spawnMesoDrop(Math.min((int) Math.max(eachd.intValue() / 20000.0D * maxmeso, 1.0D), maxmeso), new Point((int) (mob.getTruePosition().getX() + Randomizer.nextInt(100) - 50.0D), (int) mob.getTruePosition().getY()), mob, player, false, (byte) 0);
}
}
}
private static double CalculateMaxWeaponDamagePerHit(MapleCharacter player, MapleMonster monster, AttackInfo attack, Skill theSkill, MapleStatEffect attackEffect, double maximumDamageToMonster, Integer CriticalDamagePercent) {
int dLevel = Math.max(monster.getStats().getLevel() - player.getLevel(), 0) * 2;
int HitRate = Math.min((int) Math.floor(Math.sqrt(player.getStat().getAccuracy())) - (int) Math.floor(Math.sqrt(monster.getStats().getEva())) + 100, 100);
if (dLevel > HitRate) {
HitRate = dLevel;
}
HitRate -= dLevel;
if ((HitRate <= 0) && ((!GameConstants.isBeginnerJob(attack.skill / 10000)) || (attack.skill % 10000 != 1000)) && (!GameConstants.isPyramidSkill(attack.skill)) && (!GameConstants.isMulungSkill(attack.skill)) && (!GameConstants.isInflationSkill(attack.skill))) {
return 0.0D;
}
if ((player.getMapId() / 1000000 == 914) || (player.getMapId() / 1000000 == 927)) {
return 999999.0D;
}
List<Element> elements = new ArrayList();
boolean defined = false;
int CritPercent = CriticalDamagePercent.intValue();
int PDRate = monster.getStats().getPDRate();
MonsterStatusEffect pdr = monster.getBuff(MonsterStatus.WDEF);
if (pdr != null) {
PDRate += pdr.getX().intValue();
}
if (theSkill != null) {
elements.add(theSkill.getElement());
if (GameConstants.isBeginnerJob(theSkill.getId() / 10000)) {
switch (theSkill.getId() % 10000) {
case 1000:
maximumDamageToMonster = 40.0D;
defined = true;
break;
case 1020:
maximumDamageToMonster = 1.0D;
defined = true;
break;
case 1009:
maximumDamageToMonster = monster.getStats().isBoss() ? monster.getMobMaxHp() / 30L * 100L : monster.getMobMaxHp();
defined = true;
}
}
switch (theSkill.getId()) {
case 1311005:
PDRate = monster.getStats().isBoss() ? PDRate : 0;
break;
case 3221001:
case 33101001:
maximumDamageToMonster *= attackEffect.getMobCount();
defined = true;
break;
case 3101005:
defined = true;
break;
case 32001000:
case 32101000:
case 32111002:
case 32121002:
maximumDamageToMonster *= 1.5D;
break;
case 1221009:
case 3221007:
case 4331003:
case 23121003:
if (!monster.getStats().isBoss()) {
maximumDamageToMonster = monster.getMobMaxHp();
defined = true;
}
break;
case 1221011:
case 21120006:
maximumDamageToMonster = monster.getStats().isBoss() ? 500000.0D : monster.getHp() - 1L;
defined = true;
break;
case 3211006:
if (monster.getStatusSourceID(MonsterStatus.FREEZE) == 3211003) {
defined = true;
maximumDamageToMonster = 999999.0D;
}
break;
}
}
double elementalMaxDamagePerMonster = maximumDamageToMonster;
if ((player.getJob() == 311) || (player.getJob() == 312) || (player.getJob() == 321) || (player.getJob() == 322)) {
Skill mortal = SkillFactory.getSkill((player.getJob() == 311) || (player.getJob() == 312) ? 3110001 : 3210001);
if (player.getTotalSkillLevel(mortal) > 0) {
MapleStatEffect mort = mortal.getEffect(player.getTotalSkillLevel(mortal));
if ((mort != null) && (monster.getHPPercent() < mort.getX())) {
elementalMaxDamagePerMonster = 999999.0D;
defined = true;
if (mort.getZ() > 0) {
player.addHP(player.getStat().getMaxHp() * mort.getZ() / 100);
}
}
}
} else if ((player.getJob() == 221) || (player.getJob() == 222)) {
Skill mortal = SkillFactory.getSkill(2210000);
if (player.getTotalSkillLevel(mortal) > 0) {
MapleStatEffect mort = mortal.getEffect(player.getTotalSkillLevel(mortal));
if ((mort != null) && (monster.getHPPercent() < mort.getX())) {
elementalMaxDamagePerMonster = 999999.0D;
defined = true;
}
}
}
if ((!defined) || ((theSkill != null) && ((theSkill.getId() == 33101001) || (theSkill.getId() == 3221001)))) {
if (player.getBuffedValue(MapleBuffStat.WK_CHARGE) != null) {
int chargeSkillId = player.getBuffSource(MapleBuffStat.WK_CHARGE);
switch (chargeSkillId) {
case 1211003:
case 1211004:
elements.add(Element.FIRE);
break;
case 1211005:
case 1211006:
case 21111005:
elements.add(Element.ICE);
break;
case 1211007:
case 1211008:
case 15101006:
elements.add(Element.LIGHTING);
break;
case 1221003:
case 1221004:
case 11111007:
elements.add(Element.HOLY);
break;
case 12101005:
}
}
if (player.getBuffedValue(MapleBuffStat.LIGHTNING_CHARGE) != null) {
elements.add(Element.LIGHTING);
}
if (player.getBuffedValue(MapleBuffStat.ELEMENT_RESET) != null) {
elements.clear();
}
double elementalEffect;
if (elements.size() > 0) {
switch (attack.skill) {
case 3111003:
case 3211003:
elementalEffect = attackEffect.getX() / 100.0D;
break;
default:
elementalEffect = 0.5D / elements.size();
}
for (Element element : elements) {
switch (monster.getEffectiveness(element)) {
case IMMUNE:
elementalMaxDamagePerMonster = 1.0D;
break;
case WEAK:
elementalMaxDamagePerMonster *= (1.0D + elementalEffect + player.getStat().getElementBoost(element));
break;
case STRONG:
elementalMaxDamagePerMonster *= (1.0D - elementalEffect - player.getStat().getElementBoost(element));
}
}
}
elementalMaxDamagePerMonster -= elementalMaxDamagePerMonster * (Math.max(PDRate - Math.max(player.getStat().ignoreTargetDEF, 0) - Math.max(attackEffect == null ? 0 : attackEffect.getIgnoreMob(), 0), 0) / 100.0D);
elementalMaxDamagePerMonster += elementalMaxDamagePerMonster / 100.0D * CritPercent;
MonsterStatusEffect imprint = monster.getBuff(MonsterStatus.IMPRINT);
if (imprint != null) {
elementalMaxDamagePerMonster += elementalMaxDamagePerMonster * imprint.getX().intValue() / 100.0D;
}
elementalMaxDamagePerMonster += elementalMaxDamagePerMonster * player.getDamageIncrease(monster.getObjectId()) / 100.0D;
elementalMaxDamagePerMonster *= ((monster.getStats().isBoss()) && (attackEffect != null) ? player.getStat().bossdam_r + attackEffect.getBossDamage() : player.getStat().dam_r) / 100.0D;
}
if (elementalMaxDamagePerMonster > 999999.0D) {
if (!defined) {
elementalMaxDamagePerMonster = 999999.0D;
}
} else if (elementalMaxDamagePerMonster <= 0.0D) {
elementalMaxDamagePerMonster = 1.0D;
}
return elementalMaxDamagePerMonster;
}
public static final AttackInfo DivideAttack(final AttackInfo attack, final int rate) {
attack.real = false;
if (rate <= 1) {
return attack; //lol
}
for (AttackPair p : attack.allDamage) {
if (p.attack != null) {
for (Pair<Integer, Boolean> eachd : p.attack) {
eachd.left /= rate; //too ex.
}
}
}
return attack;
}
public static final AttackInfo Modify_AttackCrit(AttackInfo attack, MapleCharacter chr, int type, MapleStatEffect effect) {
int CriticalRate;
boolean shadow;
List damages;
List damage;
if ((attack.skill != 4211006) && (attack.skill != 3211003) && (attack.skill != 4111004)) {
CriticalRate = chr.getStat().passive_sharpeye_rate() + (effect == null ? 0 : effect.getCr());
shadow = (chr.getBuffedValue(MapleBuffStat.SHADOWPARTNER) != null) && ((type == 1) || (type == 2));
damages = new ArrayList();
damage = new ArrayList();
for (AttackPair p : attack.allDamage) {
if (p.attack != null) {
int hit = 0;
int mid_att = shadow ? p.attack.size() / 2 : p.attack.size();
int toCrit = (attack.skill == 4221001) || (attack.skill == 3221007) || (attack.skill == 23121003) || (attack.skill == 4341005) || (attack.skill == 4331006) || (attack.skill == 21120005) ? mid_att : 0;
if (toCrit == 0) {
for (Pair eachd : p.attack) {
if ((!((Boolean) eachd.right).booleanValue()) && (hit < mid_att)) {
if ((((Integer) eachd.left).intValue() > 999999) || (Randomizer.nextInt(100) < CriticalRate)) {
toCrit++;
}
damage.add(eachd.left);
}
hit++;
}
if (toCrit == 0) {
damage.clear();
} else {
Collections.sort(damage);
for (int i = damage.size(); i > damage.size() - toCrit; i--) {
damages.add(damage.get(i - 1));
}
damage.clear();
}
} else {
hit = 0;
for (Pair eachd : p.attack) {
if (!((Boolean) eachd.right).booleanValue()) {
if (attack.skill == 4221001) {
eachd.right = Boolean.valueOf(hit == 3);
} else if ((attack.skill == 3221007) || (attack.skill == 23121003) || (attack.skill == 21120005) || (attack.skill == 4341005) || (attack.skill == 4331006) || (((Integer) eachd.left).intValue() > 999999)) {
eachd.right = Boolean.valueOf(true);
} else if (hit >= mid_att) {
eachd.right = ((Pair) p.attack.get(hit - mid_att)).right;
} else {
eachd.right = Boolean.valueOf(damages.contains(eachd.left));
}
}
hit++;
}
damages.clear();
}
}
}
}
return attack;
}
public static AttackInfo parseDmgMa(LittleEndianAccessor lea, MapleCharacter chr) // magic
{
try {
AttackInfo ret = new AttackInfo();
lea.skip(1);
ret.tbyte = lea.readByte();
ret.targets = ((byte) (ret.tbyte >>> 4 & 0xF));
ret.hits = ((byte) (ret.tbyte & 0xF));
ret.skill = lea.readInt();
if (ret.skill >= 91000000 && ret.skill < 100000000) {
return null;
}
lea.skip(11);
if (GameConstants.isMagicChargeSkill(ret.skill)) {
ret.charge = lea.readInt();
} else {
ret.charge = -1;
}
ret.unk = lea.readByte();
ret.display = lea.readUShort();
lea.skip(4);
ret.speed = lea.readByte();
ret.lastAttackTickCount = lea.readInt();
lea.skip(4);
ret.allDamage = new ArrayList();
for (int i = 0; i < ret.targets; i++) {
int oid = lea.readInt();
lea.skip(20);//v140 = 19
List allDamageNumbers = new ArrayList();
for (int j = 0; j < ret.hits; j++) {
int damage = lea.readInt();
allDamageNumbers.add(new Pair(Integer.valueOf(damage), Boolean.valueOf(false)));
}
lea.skip(8);
ret.allDamage.add(new AttackPair(Integer.valueOf(oid).intValue(), allDamageNumbers));
}
if (lea.available() >= 4L) {
ret.position = lea.readPos();
}
// if (ret.skill == 2321054){//Asura - Mixtamal6
// lea.skip(3); //new
// }
return ret;
} catch (Exception e) {
}
return null;
}
public static AttackInfo parseDmgM(LittleEndianAccessor lea, MapleCharacter chr)//reg att
{
AttackInfo ret = new AttackInfo();
lea.skip(1);
ret.tbyte = lea.readByte();
ret.targets = ((byte) (ret.tbyte >>> 4 & 0xF));
ret.hits = ((byte) (ret.tbyte & 0xF));
ret.skill = lea.readInt();
if (GameConstants.isZero(chr.getJob()) && ret.skill != 0) {
lea.skip(1); //zero has byte
}
if (ret.skill == 2221012|| ret.skill == 36101001 || ret.skill == 42120003) {
lea.skip(1);
}
lea.skip(1);
lea.readInt();
lea.readInt(); //same as above
lea.readShort();
switch (ret.skill) {
case 1311011:// La Mancha Spear
case 2221012:
case 4341002:
case 4341003:
case 4221052:
case 5201002:
case 5300007:
case 5301001:
case 11121052:// Styx Crossing
case 11121055:// Styx Crossing charged
case 31201001:
case 31211001:
case 14111006:
case 24121000:
case 24121005:
case 27101202:
case 27111100:
case 27120211:
case 27121201:
case 31001000:
case 31101000:
case 31111005:
case 36121000:
case 36101001:
case 42120003: // Monkey Spirits
case 61111100:
case 61111111:
case 61111113:
case 65121003:
case 65121052:// Supreme Supernova
case 101110101:
case 101110102:
case 101110104:
case 101120200:
case 101120203:
case 101120205:
case 32121003: //Tornado Spin
// case 36121001:
ret.charge = lea.readInt();
break;
default:
ret.charge = 0;
}
ret.unk = lea.readByte();
ret.display = lea.readUShort();
if (ret.skill == 2221012 || ret.skill == 36101001 ||ret.skill == 42120003) {
lea.skip(4);
} else {
lea.skip(5);
}
if ((ret.skill == 5300007) || (ret.skill == 5101012) || (ret.skill == 5081001) || (ret.skill == 15101010)) {
lea.readInt();
}
ret.speed = lea.readByte();
ret.lastAttackTickCount = lea.readInt();
if (GameConstants.isEnergyBuff(ret.skill)) {
lea.skip(4);
}
else if (ret.skill == 4341052){//Asura - Mixtamal6
lea.skip(3); //new
}
else {
lea.skip(8);
}
ret.allDamage = new ArrayList();
for (int i = 0; i < ret.targets; i++) {
int oid = lea.readInt();
lea.skip(20);//was 19
List allDamageNumbers = new ArrayList();
for (int j = 0; j < ret.hits; j++) {
int damage = lea.readInt();
allDamageNumbers.add(new Pair(Integer.valueOf(damage), Boolean.valueOf(false)));
}
lea.skip(8);
ret.allDamage.add(new AttackPair(Integer.valueOf(oid).intValue(), allDamageNumbers));
}
ret.position = lea.readPos();
return ret;
}
public static AttackInfo parseDmgR(LittleEndianAccessor lea, MapleCharacter chr)//ranged att
{
AttackInfo ret = new AttackInfo();
lea.skip(1);
ret.tbyte = lea.readByte();
ret.targets = ((byte) (ret.tbyte >>> 4 & 0xF));
ret.hits = ((byte) (ret.tbyte & 0xF));
ret.skill = lea.readInt();
if (GameConstants.isZero(chr.getJob())) {
lea.skip(1); //zero has byte
}
lea.skip(1);
lea.readInt();
lea.readInt(); //same as above
lea.readShort();
switch (ret.skill) {
case 3121004:
case 3221001:
case 5321052:
case 5221004:
case 5311002:
case 5711002:
case 5721001:
case 13111002://Hurricane
case 13111020://Sentient Arrow
case 13121001://Song of Heaven
case 23121000:
case 24121000:
case 33121009:
case 35001001:
case 35101009:
case 60011216://Soul Buster
case 3101008:
case 3111009:// Hurricane
case 3121013:// Arrow Blaster
case 5221022:
lea.skip(4);
}
ret.charge = -1;
ret.unk = lea.readByte();
ret.display = lea.readUShort();
lea.skip(5);
if (ret.skill == 23111001 || ret.skill == 36111010) {
lea.skip(12);
} else if (ret.skill == 3121013) {// Arrow Blaster
lea.skip(8);
}if ((ret.skill == 5221022) || (ret.skill == 5220023) || (ret.skill == 95001000)) {//Corsair BoarSide IDSkills
lea.readInt();//newv144
lea.readInt();//newv144
}
ret.speed = lea.readByte();
ret.lastAttackTickCount = lea.readInt();
lea.skip(4);
ret.slot = ((byte) lea.readShort());
ret.csstar = ((byte) lea.readShort());
ret.AOE = lea.readByte();
ret.allDamage = new ArrayList();
for (int i = 0; i < ret.targets; i++) {
int oid = lea.readInt();
lea.skip(20);//v140 = 19
List allDamageNumbers = new ArrayList();
for (int j = 0; j < ret.hits; j++) {
int damage = lea.readInt();
allDamageNumbers.add(new Pair(Integer.valueOf(damage), Boolean.valueOf(false)));
}
lea.skip(8);
ret.allDamage.add(new AttackPair(Integer.valueOf(oid).intValue(), allDamageNumbers));
}
ret.position = lea.readPos();
if (lea.available() >= 4) {
lea.skip(4);//moved after pos in v141
}
return ret;
}
public static AttackInfo parseExplosionAttack(LittleEndianAccessor lea, AttackInfo ret, MapleCharacter chr) {
if (ret.hits == 0) {
lea.skip(4);
byte bullets = lea.readByte();
for (int j = 0; j < bullets; j++) {
ret.allDamage.add(new AttackPair(Integer.valueOf(lea.readInt()).intValue(), null));
lea.skip(1);
}
lea.skip(2);
return ret;
}
for (int i = 0; i < ret.targets; i++) {
int oid = lea.readInt();
lea.skip(12);
byte bullets = lea.readByte();
List allDamageNumbers = new ArrayList();
for (int j = 0; j < bullets; j++) {
allDamageNumbers.add(new Pair(Integer.valueOf(lea.readInt()), Boolean.valueOf(false)));
}
ret.allDamage.add(new AttackPair(Integer.valueOf(oid).intValue(), allDamageNumbers));
lea.skip(4);
}
lea.skip(4);
byte bullets = lea.readByte();
for (int j = 0; j < bullets; j++) {
ret.allDamage.add(new AttackPair(Integer.valueOf(lea.readInt()).intValue(), null));
lea.skip(2);
}
return ret;
}
}