MXD-Server/src/handling/channel/handler/DamageParse.java

1904 lines
109 KiB
Java
Raw Normal View History

2025-03-03 15:16:22 +08:00
package handling.channel.handler;
import java.util.*;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import java.sql.Connection;
import com.alibaba.fastjson.JSONObject;
import database.DBConPool;
import tools.packet.MobPacket;
import server.SkillType;
import server.MapleItemInformationProvider;
import client.inventory.Equip;
import tools.data.LittleEndianAccessor;
import client.MapleJob;
import java.awt.Point;
import server.life.Element;
import client.anticheat.CheatTracker;
import client.inventory.IItem;
import server.life.MapleMonsterStats;
import server.life.MapleMonster;
import client.PlayerStats;
import server.maps.MapleMap;
import java.util.Map.Entry;
import client.inventory.MapleInventoryType;
import client.status.MonsterStatusEffect;
import server.Randomizer;
import constants.tzjc;
import client.SkillFactory;
import java.awt.geom.Point2D;
import constants.ServerConfig;
import tools.Pair;
import client.status.MonsterStatus;
import server.maps.MapleMapObject;
import server.maps.MapleMapItem;
import server.maps.MapleMapObjectType;
import tools.AttackPair;
import gui.Start;
import tools.FileoutputUtil;
import handling.world.World.Broadcast;
import client.MapleBuffStat;
import constants.GameConstants;
import tools.MaplePacketCreator;
import client.anticheat.CheatingOffense;
import server.MapleStatEffect;
import client.MapleCharacter;
import client.ISkill;
import server.maps.MaplePvp;
public class DamageParse {
public static final Map<Integer, Integer> MobRedDam = new HashMap();
public static void applyAttack(final AttackInfo attack, final ISkill theSkill, final MapleCharacter player, int attackCount, final double maxDamagePerMonster, final MapleStatEffect effect, final AttackType attack_type) {
if (!player.isAlive()) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACKING_WHILE_DEAD);
return;
}
if (attack.real) {
player.getCheatTracker().checkAttack(attack.skill, attack.lastAttackTickCount);
}
if (attack.skill != 0) {
if (effect == null) {
player.getClient().sendPacket(MaplePacketCreator.enableActions());
return;
}
if (GameConstants.isMulungSkill(attack.skill)) {
if (player.getmulungEnergy() < 10000) {
return;
}
if (player.getMapId() / 10000 != 92502) {
return;
}
player.mulungEnergyModify(false);
}
if (GameConstants.isPyramidSkill(attack.skill) && (player.getMapId() / 1000000 != 926 || player.getPyramidSubway() == null || !player.getPyramidSubway().onSkillUse(player))) {
return;
}
if (GameConstants.isAran((int) player.getJob())) {
final int reduce = player.Aran_ReduceCombo(attack.skill);
if (reduce > 0) {
player.setCombo(player.getCombo() - reduce);
}
}
int last = attackCount;
boolean mirror_fix = false;
if (player.getJob() >= 411 && player.getJob() <= 412) {
mirror_fix = true;
}
if (player.getJob() >= 1400 && player.getJob() <= 1412) {
mirror_fix = true;
}
if (attack.skill == 11101004) {
last = 2;
}
if (attack.skill == 15111007) {
last = 3;
}
last = 技能段数(attack.skill);
if (mirror_fix || player.getBuffedValue(MapleBuffStat.SHADOWPARTNER) != null) {
last *= 2;
}
if (attack.hits > last) {
if (player.hasGmLevel(1)) {
player.dropMessage("攻击次数异常攻击次数 " + (int) attack.hits + " 服务端判断正常攻击次数 " + last + " 技能ID " + attack.skill);
} else {
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 攻击次数异常已自动封锁。 玩家攻击次数 " + (int) attack.hits + " 服务端判断正常攻击次数 " + last + " 技能ID " + attack.skill));
FileoutputUtil.logToFile("logs/Hack/Ban/技能攻击次数.txt", "\r\n" + FileoutputUtil.NowTime() + "玩家: " + player.getName() + "(" + (int) player.getLevel() + ") 地图: " + player.getMapId() + " 技能代码: " + attack.skill + " 技能等级: " + player.getSkillLevel(attack.skill) + " 攻击次数 : " + (int) attack.hits + " 正常攻击次数 :" + last);
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "技能攻击次数异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
final String reason = "使用违法程式练功";
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为" + reason + "而被管理员永久停权。"));
}
}
}
int CheckCount = effect.getMobCount();
CheckCount = 技能个数(attack.skill);
if (attack.targets > CheckCount) {
if (!player.hasGmLevel(1)) {
FileoutputUtil.logToFile("logs/Hack/Ban/打怪数量异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家: " + player.getName() + "(" + (int) player.getLevel() + ") 地图: " + player.getMapId() + "技能代码: " + attack.skill + " 技能等级: " + player.getSkillLevel(effect.getSourceId()) + " 封包怪物量 : " + (int) attack.targets + " 服务端怪物量 :" + CheckCount);
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 攻击怪物数量异常。 封包怪物量 " + (int) attack.targets + " 服务端怪物量 " + CheckCount + " 技能ID " + attack.skill));
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "打怪数量异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
final String reason2 = "使用违法程式练功";
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为" + reason2 + "而被管理员永久停权。"));
}
return;
}
player.dropMessage("打怪数量异常,技能代码: " + attack.skill + " 封包怪物量 : " + (int) attack.targets + " 服务端怪物量 :" + CheckCount);
}
}
if (attack.hits > 0 && attack.targets > 0 && !player.getStat().checkEquipDurabilitys(player, -1)) {
player.dropMessage(5, "耐久度已经归零");
return;
}
int totDamage = 0;
final MapleMap map = player.getMap();
if (map.getId() == 990010000) {
MaplePvp.doPvP(player, map, attack);
}
if (attack.skill == 4211006) {
for (final AttackPair oned : attack.allDamage) {
if (oned.attack != null) {
continue;
}
final MapleMapObject mapobject = map.getMapObject(oned.objectid, MapleMapObjectType.ITEM);
if (mapobject == null) {
player.getCheatTracker().registerOffense(CheatingOffense.EXPLODING_NONEXISTANT);
return;
}
final MapleMapItem mapitem = (MapleMapItem) mapobject;
mapitem.getLock().lock();
try {
if (mapitem.getMeso() <= 0) {
player.getCheatTracker().registerOffense(CheatingOffense.ETC_EXPLOSION);
return;
}
if (mapitem.isPickedUp()) {
return;
}
map.removeMapObject((MapleMapObject) mapitem);
map.broadcastMessage(MaplePacketCreator.explodeDrop(mapitem.getObjectId()));
mapitem.setPickedUp(true);
} finally {
mapitem.getLock().unlock();
}
}
}
int totDamageToOneMonster = 0;
long newtotDamageToOneMonster = 0L;
long hpMob = 0L;
final PlayerStats stats = player.getStat();
final int CriticalDamage = stats.passive_sharpeye_percent();
byte ShdowPartnerAttackPercentage = 0;
if (attack_type == AttackType.RANGED_WITH_SHADOWPARTNER || attack_type == AttackType.NON_RANGED_WITH_MIRROR) {
MapleStatEffect shadowPartnerEffect;
if (attack_type == AttackType.NON_RANGED_WITH_MIRROR) {
shadowPartnerEffect = player.getStatForBuff(MapleBuffStat.MIRROR_IMAGE);
} else {
shadowPartnerEffect = player.getStatForBuff(MapleBuffStat.SHADOWPARTNER);
}
if (shadowPartnerEffect != null) {
if (attack.skill != 0 && attack_type != AttackType.NON_RANGED_WITH_MIRROR) {
ShdowPartnerAttackPercentage = (byte) shadowPartnerEffect.getY();
} else {
ShdowPartnerAttackPercentage = (byte) shadowPartnerEffect.getX();
}
}
attackCount /= 2;
}
double maxDamagePerHit = 0.0;
for (final AttackPair oned2 : attack.allDamage) {
final MapleMonster monster = map.getMonsterByOid(oned2.objectid);
if (monster != null) {
totDamageToOneMonster = 0;
newtotDamageToOneMonster = 0L;
hpMob = monster.getHp();
final MapleMonsterStats monsterstats = monster.getStats();
final int fixeddmg = monsterstats.getFixedDamage();
final boolean Tempest = monster.getStatusSourceID(MonsterStatus.FREEZE) == 21120006;
maxDamagePerHit = calculateMaxWeaponDamagePerHit(player, monster, attack, theSkill, effect, maxDamagePerMonster, Integer.valueOf(CriticalDamage));
byte overallAttackCount = 0;
for (final Pair<Integer, Boolean> eachde : oned2.attack) {
Integer eachd = (Integer) eachde.left;
++overallAttackCount;
if (!GameConstants.isElseSkill(attack.skill)) {
if (GameConstants.Novice_Skill(attack.skill) && eachd.intValue() > 40) {
boolean apple = false;
if (player.getBuffSource(MapleBuffStat.WATK) == 2022179 || player.getBuffSource(MapleBuffStat.MATK) == 2022179 || player.getBuffSource(MapleBuffStat.WDEF) == 2022179) {
apple = true;
}
if (!player.hasGmLevel(1)) {
FileoutputUtil.logToFile("logs/Hack/Ban/伤害异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家<" + (int) player.getLevel() + ">: " + player.getName() + " 怪物 " + monster.getId() + " 地图: " + player.getMapId() + " 技能代码: " + attack.skill + " 最高伤害: 40 本次伤害 :" + eachd + " 预计伤害: " + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss() + " 紫色蘋果: " + apple);
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 最高伤害 40 本次伤害 " + eachd + " 技能ID " + attack.skill));
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "伤害异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为伤害异常而被管理员永久停权。"));
}
return;
}
player.dropMessage("[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 最高伤害 40 本次伤害 " + eachd + " 技能ID " + attack.skill);
}
boolean ban = false;
int atk = 2140000001;
if (eachd.intValue() < 0) {
if (!player.hasGmLevel(1)) {
FileoutputUtil.logToFile("logs/Hack/Ban/伤害异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家<" + (int) player.getLevel() + ">: " + player.getName() + " 怪物 " + monster.getId() + " 地图: " + player.getMapId() + " 技能代码: " + attack.skill + " 伤害过低导致越界 本次伤害 :" + eachd + " 预计伤害: " + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss());
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 伤害过低导致越界本次伤害 " + eachd + " 技能ID " + attack.skill));
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "伤害异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为伤害异常而被管理员永久停权。"));
}
return;
}
player.dropMessage("[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 伤害过低导致越界本次伤害 " + eachd + " 技能ID " + attack.skill);
}
if (!GameConstants.isAran((int) player.getJob())) {
if (((Integer) Start.ConfigValuesMap.get("伤害检测")).intValue() > 0) {
atk = ((Integer) Start.ConfigValuesMap.get("伤害上限")).intValue();
}
if (eachd.intValue() >= atk && (double) eachd.intValue() > Math.ceil(maxDamagePerHit * 1.2)) {
ban = true;
}
if ((long) eachd.intValue() == monster.getMobMaxHp()) {
ban = false;
}
if (ban) {
boolean apple2 = false;
if (player.getBuffSource(MapleBuffStat.WATK) == 2022179 || player.getBuffSource(MapleBuffStat.MATK) == 2022179 || player.getBuffSource(MapleBuffStat.WDEF) == 2022179) {
apple2 = true;
}
if (!player.hasGmLevel(1)) {
FileoutputUtil.logToFile("logs/Hack/Ban/伤害异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家<" + (int) player.getLevel() + ">: " + player.getName() + " 怪物 " + monster.getId() + " 地图: " + player.getMapId() + " 技能代码: " + attack.skill + " 最高伤害: " + atk + " 本次伤害 :" + eachd + " 预计伤害: " + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss() + " 紫色蘋果: " + apple2);
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 最高伤害 " + atk + " 本次伤害 " + eachd + " 技能ID " + attack.skill + "预计伤害: " + (int) maxDamagePerHit));
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "伤害异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为伤害异常而被管理员永久停权。"));
}
return;
}
player.dropMessage("[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 最高伤害 " + atk + " 本次伤害 " + eachd + " 技能ID " + attack.skill + "预计伤害: " + (int) maxDamagePerHit);
}
}
atk = GameConstants.getMaxDamage((int) player.getLevel(), (int) player.getJob(), attack.skill);
if (GameConstants.isAran((int) player.getJob())) {
if (player.getLevel() > 10 && eachd.intValue() > atk && (double) eachd.intValue() > maxDamagePerHit * 2.0) {
FileoutputUtil.logToFile("logs/Hack/伤害异常_狂狼.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家<" + (int) player.getLevel() + ">: " + player.getName() + " 技能代码: " + attack.skill + " 怪物: " + monster.getId() + " 最高伤害: " + atk + " 本次伤害 :" + eachd + " 预计伤害: " + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss());
}
if (player.getLevel() <= 20) {
atk = 1000;
if (eachd.intValue() >= atk && (double) eachd.intValue() > maxDamagePerHit) {
boolean apple2 = false;
if (player.getBuffSource(MapleBuffStat.WATK) == 2022179 || player.getBuffSource(MapleBuffStat.MATK) == 2022179 || player.getBuffSource(MapleBuffStat.WDEF) == 2022179) {
apple2 = true;
}
ban = true;
FileoutputUtil.logToFile("logs/Hack/Ban/伤害异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家<" + (int) player.getLevel() + ">: " + player.getName() + " 怪物 " + monster.getId() + " 地图: " + player.getMapId() + " 技能代码: " + attack.skill + " 最高伤害: " + atk + " 本次伤害 :" + eachd + " 预计伤害: " + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss() + " 紫色蘋果: " + apple2);
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 最高伤害 " + atk + " 本次伤害 " + eachd + " 技能ID " + attack.skill));
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为伤害异常而被管理员永久停权。"));
player.ban(player.getName() + "伤害异常", true, true, false);
player.getClient().getSession().close();
return;
}
}
}
} else if (eachd.intValue() > atk && (double) eachd.intValue() > maxDamagePerHit * 2.0) {
FileoutputUtil.logToFile("logs/Hack/伤害异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家<" + (int) player.getLevel() + ">: " + player.getName() + " 技能代码: " + attack.skill + " 怪物: " + monster.getId() + " 最高伤害: " + atk + " 本次伤害 :" + eachd + " 预计伤害: " + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss());
}
}
if (overallAttackCount - 1 == attackCount) {
double min = maxDamagePerHit;
final double shadow = ((double) ShdowPartnerAttackPercentage == 0.0) ? 1.0 : ((double) ShdowPartnerAttackPercentage);
if (ShdowPartnerAttackPercentage != 0) {
min = maxDamagePerHit / 100.0;
}
final double dam = monsterstats.isBoss() ? stats.bossdam_r : stats.dam_r;
final double last2 = maxDamagePerHit = min * (shadow * dam / 100.0);
}
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() && ((Integer) Start.ConfigValuesMap.get("伤害修正")).intValue() > 0) {
if (!Tempest) {
if (!monster.isBuffed(MonsterStatus.DAMAGE_IMMUNITY) && !monster.isBuffed(MonsterStatus.WEAPON_IMMUNITY) && !monster.isBuffed(MonsterStatus.WEAPON_DAMAGE_REFLECT)) {
if ((double) eachd.intValue() > maxDamagePerHit) {
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE, "[伤害: " + eachd + ", 预期: " + maxDamagePerHit + ", 怪物: " + monster.getId() + "] [职业: " + (int) player.getJob() + ", 等级: " + (int) player.getLevel() + ", 使用的技能: " + attack.skill + "]");
if ((double) eachd.intValue() > maxDamagePerHit * 2.0) {
if ((double) eachd.intValue() > maxDamagePerHit * 2.0 && maxDamagePerHit != 1.0) {
if (ServerConfig.LOG_DAMAGE) {
FileoutputUtil.logToFile("Logs/hack/伤害计算/伤害计算修正_" + monster.getId() + "_" + attack.skill + ".txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家: " + player.getName() + "(" + (int) player.getLevel() + ") 职业: " + (int) player.getJob() + " 怪物:" + monster.getId() + " 封包伤害 :" + eachd + " 预计伤害 :" + (int) maxDamagePerHit + " 是否为BOSS: " + monster.getStats().isBoss(), false, false);
}
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_2, "[伤害: " + eachd + ", 预计伤害: " + (int) maxDamagePerHit + ", 怪物: " + monster.getId() + "] [职业: " + (int) player.getJob() + ", 等级: " + (int) player.getLevel() + ", 技能: " + attack.skill + "]");
}
eachd = Integer.valueOf((int) (maxDamagePerHit * 2.0));
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_2, "[伤害: " + eachd + ", 预期: " + maxDamagePerHit + ", 怪物: " + monster.getId() + "] [职业: " + (int) player.getJob() + ", 等级: " + (int) player.getLevel() + ", 使用的技能: " + attack.skill + "]");
if (eachd.intValue() >= 10000) {
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_2, "[伤害: " + eachd + ", 预期: " + maxDamagePerHit + ", 怪物: " + monster.getId() + "] [职业: " + (int) player.getJob() + ", 等级: " + (int) player.getLevel() + ", 使用的技能: " + attack.skill + "]");
}
}
}
} else if ((double) eachd.intValue() > maxDamagePerHit) {
eachd = Integer.valueOf((int) maxDamagePerHit);
if ((double) eachd.intValue() > maxDamagePerHit * 2.0 && maxDamagePerHit != 1.0) {
if (ServerConfig.LOG_DAMAGE) {
FileoutputUtil.logToFile("Logs/hack/伤害计算/伤害计算修正_" + monster.getId() + "_" + attack.skill + ".txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家: " + player.getName() + "(" + (int) player.getLevel() + ") 职业: " + (int) player.getJob() + " 怪物:" + monster.getId() + " 封包伤害 :" + eachd + " 预计伤害 :" + (int) maxDamagePerHit + " 是否为BOSS: " + monster.getStats().isBoss());
}
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_2, "[伤害: " + eachd + ", 预计伤害: " + (int) maxDamagePerHit + ", 怪物: " + monster.getId() + "] [职业: " + (int) player.getJob() + ", 等级: " + (int) player.getLevel() + ", 技能: " + attack.skill + "]");
}
}
}
}
totDamageToOneMonster += eachd.intValue();
newtotDamageToOneMonster += (long) eachd.intValue();
if (monster.getId() == 9300021 && player.getPyramidSubway() != null) {
player.getPyramidSubway().onMiss(player);
}
}
totDamage += totDamageToOneMonster;
player.checkMonsterAggro(monster);
final double range = player.getPosition().distanceSq((Point2D) monster.getPosition());
double SkillRange = GameConstants.getAttackRange(player, effect, attack);
if (((Integer) Start.ConfigValuesMap.get("重置技能范围开关")).intValue() > 0) {
SkillRange = (double) ((Integer) Start.ConfigValuesMap.get("重置技能总范围")).intValue();
}
if (player.getDebugMessage() && range > SkillRange) {
player.dropMessage("技能[" + attack.skill + "] 预计范围: " + (int) SkillRange + " 实際范围: " + (int) range + "");
}
if (range > SkillRange && !player.inBossMap() && attack.skill != 5221004 && attack.skill != 21120006) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACK_FARAWAY_MONSTER, "攻击范围异常,技能:" + attack.skill + "(" + SkillFactory.getName(attack.skill) + ")\u3000怪物:" + monster.getId() + " 正常范围:" + (int) SkillRange + " 计算范围:" + (int) range);
if (range > SkillRange * 2.0 && ((Integer) Start.ConfigValuesMap.get("全屏检测")).intValue() > 0) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACK_FARAWAY_MONSTER_BAN, "超大攻击范围,技能:" + attack.skill + "(" + SkillFactory.getName(attack.skill) + ")\u3000怪物:" + monster.getId() + " 正常范围:" + (int) SkillRange + " 计算范围:" + (int) range);
}
return;
}
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, oned2);
break;
}
}
}
final MapleStatEffect ds = player.getStatForBuff(MapleBuffStat.DARKSIGHT);
if (ds != null && ds.getSourceId() != 9001004 && (ds.getSourceId() != 4330001 || !ds.makeChanceResult())) {
player.cancelEffectFromBuffStat(MapleBuffStat.DARKSIGHT);
}
final MapleStatEffect wd = player.getStatForBuff(MapleBuffStat.WIND_WALK);
if (wd != null && player.getJob() >= 1300 && player.getJob() <= 1312) {
player.cancelEffectFromBuffStat(MapleBuffStat.WIND_WALK);
}
if (newtotDamageToOneMonster <= 0L) {
continue;
}
final tzjc t = new tzjc();
newtotDamageToOneMonster = t.star_damage(player, newtotDamageToOneMonster, monster);
if (attack.skill != 1221011) {
long newDamage = 0L;
newtotDamageToOneMonster = TWgetNewtotDamageToOneMonster(attack, player, newtotDamageToOneMonster, monster);
monster.damage(player, newtotDamageToOneMonster, true, attack.skill);
if (monster.getHp() > 0) {
long hp = monster.getHp();
long mobMaxHp = monster.getMobMaxHp();
double percentage = ((double) hp / mobMaxHp) * 100; // 显式转换为浮点数并计算百分比‌:ml-citation{ref="1,3" data="citationList"}
String result = String.format("%.2f%%", percentage);
double l = (double) hp / mobMaxHp;
player.dropMessage(-1, "当前怪物血量为:" +hp +" "+result);
}
} 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)));
}
if (stats.hpRecoverProp > 0 && Randomizer.nextInt(100) <= stats.hpRecoverProp) {
player.healHP(stats.hpRecover);
}
if (stats.mpRecoverProp > 0 && Randomizer.nextInt(100) <= stats.mpRecoverProp) {
player.healMP(stats.mpRecover);
}
if (player.getBuffedValue(MapleBuffStat.COMBO_DRAIN) != null) {
stats.setHp(stats.getHp() + (int) Math.min(monster.getMobMaxHp(), (long) Math.min((int) ((double) totDamage * (double) player.getStatForBuff(MapleBuffStat.COMBO_DRAIN).getX() / 100.0), stats.getMaxHp() / 2)), true);
}
final int[] array;
final int[] skillsl = array = new int[]{4120005, 4220005, 14110004};
final int length = array.length;
int k = 0;
while (k < length) {
final int i = array[k];
final ISkill skill = SkillFactory.getSkill(i);
if (player.getSkillLevel(skill) > 0) {
final MapleStatEffect venomEffect = skill.getEffect((int) player.getSkillLevel(skill));
if (venomEffect.makeChanceResult()) {
monster.applyStatus(player, new MonsterStatusEffect(MonsterStatus.POISON, Integer.valueOf(1), i, null, false), true, (long) venomEffect.getDuration(), monster.getStats().isBoss(), venomEffect);
break;
}
break;
} else {
++k;
}
}
switch (attack.skill) {
case 4101005:
case 5111004:
case 15111001: {
final int getHP = (int) Math.min(monster.getMobMaxHp(), (long) Math.min((int) ((double) totDamage * (double) theSkill.getEffect((int) player.getSkillLevel(theSkill)).getX() / 100.0), stats.getMaxHp() / 2));
stats.setHp(stats.getHp() + getHP, true);
break;
}
case 5211006:
case 5220011: {
player.setLinkMid(monster.getObjectId());
break;
}
case 1311005: {
final int remainingHP = stats.getHp() - totDamage * ((effect != null) ? effect.getX() : 0) / 100;
stats.setHp((remainingHP > 1) ? remainingHP : 1);
break;
}
case 4001002:
case 4001334:
case 4001344:
case 4111005:
case 4121007:
case 4201005:
case 4211002:
case 4211004:
case 4221001:
case 4221007:
case 14001002:
case 14001004:
case 14111002:
case 14111005: {
if (player.hasBuffedValue(MapleBuffStat.WK_CHARGE) && !monster.getStats().isBoss()) {
final 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, (long) (eff.getY() * 1000), monster.getStats().isBoss(), eff);
}
}
if (player.hasBuffedValue(MapleBuffStat.BODY_PRESSURE) && !monster.getStats().isBoss()) {
final 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, (long) (eff.getX() * 1000), monster.getStats().isBoss(), eff);
}
}
final int[] array2;
final int[] skills = array2 = new int[]{4120005, 4220005, 14110004};
k = array2.length;
int l = 0;
while (l < k) {
final int j = array2[l];
final ISkill skill2 = SkillFactory.getSkill(j);
if (player.getSkillLevel(skill2) > 0) {
final MapleStatEffect venomEffect2 = skill2.getEffect((int) player.getSkillLevel(skill2));
if (venomEffect2.makeChanceResult()) {
monster.applyStatus(player, new MonsterStatusEffect(MonsterStatus.POISON, Integer.valueOf(1), j, null, false), true, (long) venomEffect2.getDuration(), monster.getStats().isBoss(), venomEffect2);
break;
}
break;
} else {
++l;
}
}
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()) {
final 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, (long) (eff.getY() * 1000), monster.getStats().isBoss(), eff);
}
}
if (player.getBuffedValue(MapleBuffStat.BODY_PRESSURE) == null || monster.getStats().isBoss()) {
break;
}
final 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, (long) (eff.getX() * 1000), true, eff);
break;
}
break;
}
}
if (totDamageToOneMonster > 0) {
final IItem weapon_ = player.getInventory(MapleInventoryType.EQUIPPED).getItem((short) (-11));
if (weapon_ != null) {
final MonsterStatus stat = GameConstants.getStatFromWeapon(weapon_.getItemId());
if (stat != null && Randomizer.nextInt(100) < GameConstants.getStatChance()) {
final MonsterStatusEffect monsterStatusEffect = new MonsterStatusEffect(stat, Integer.valueOf(GameConstants.getXForStat(stat)), GameConstants.getSkillForStat(stat), null, false);
monster.applyStatus(player, monsterStatusEffect, false, 10000L, monster.getStats().isBoss(), null);
}
}
if (player.hasBuffedValue(MapleBuffStat.BLIND)) {
final MapleStatEffect eff2 = player.getStatForBuff(MapleBuffStat.BLIND);
if (eff2 != null && eff2.makeChanceResult()) {
final MonsterStatusEffect monsterStatusEffect = new MonsterStatusEffect(MonsterStatus.ACC, Integer.valueOf(eff2.getX()), eff2.getSourceId(), null, false);
monster.applyStatus(player, monsterStatusEffect, false, (long) (eff2.getY() * 1000), monster.getStats().isBoss(), eff2);
}
}
if (player.hasBuffedValue(MapleBuffStat.HAMSTRING)) {
final MapleStatEffect eff2 = player.getStatForBuff(MapleBuffStat.HAMSTRING);
if (eff2 != null && eff2.makeChanceResult()) {
final MonsterStatusEffect monsterStatusEffect = new MonsterStatusEffect(MonsterStatus.SPEED, Integer.valueOf(eff2.getX()), 3121007, null, false);
monster.applyStatus(player, monsterStatusEffect, false, (long) (eff2.getY() * 1000), monster.getStats().isBoss(), eff2);
}
}
if (player.getJob() == 121) {
ISkill skill3 = SkillFactory.getSkill(1211006);
if (player.isBuffFrom(MapleBuffStat.WK_CHARGE, skill3)) {
final MapleStatEffect eff3 = skill3.getEffect((int) player.getSkillLevel(skill3));
final MonsterStatusEffect monsterStatusEffect2 = new MonsterStatusEffect(MonsterStatus.FREEZE, Integer.valueOf(1), skill3.getId(), null, false);
monster.applyStatus(player, monsterStatusEffect2, false, (long) (eff3.getY() * 2000), monster.getStats().isBoss(), eff3);
}
skill3 = SkillFactory.getSkill(1211005);
if (player.isBuffFrom(MapleBuffStat.WK_CHARGE, skill3)) {
final MapleStatEffect eff3 = skill3.getEffect((int) player.getSkillLevel(skill3));
final MonsterStatusEffect monsterStatusEffect2 = new MonsterStatusEffect(MonsterStatus.FREEZE, Integer.valueOf(1), skill3.getId(), null, false);
monster.applyStatus(player, monsterStatusEffect2, false, (long) (eff3.getY() * 2000), monster.getStats().isBoss(), eff3);
}
}
}
if (effect == null || effect.getMonsterStati().size() <= 0 || !effect.makeChanceResult()) {
continue;
}
for (final Entry<client.status.MonsterStatus, java.lang.Integer> z : effect.getMonsterStati().entrySet()) {
monster.applyStatus(player, new MonsterStatusEffect((MonsterStatus) z.getKey(), (Integer) z.getValue(), theSkill.getId(), null, false), effect.isPoison(), (long) effect.getDuration(), monster.getStats().isBoss(), effect);
}
}
}
if (effect != null && attack.skill != 0 && (attack.targets > 0 || (attack.skill != 4331003 && attack.skill != 4341002)) && attack.skill != 21101003 && attack.skill != 5110001 && attack.skill != 15100004 && attack.skill != 11101002 && attack.skill != 13101002 && attack.skill != 14111006) {
effect.applyTo(player, attack.position);
}
if (attack.skill == 14111006) {
effect.applyTo(player, attack.positionxy);
}
if (totDamage > 1) {
final CheatTracker tracker = player.getCheatTracker();
tracker.setAttacksWithoutHit(true);
if (tracker.getAttacksWithoutHit() > 50) {
tracker.registerOffense(CheatingOffense.ATTACK_WITHOUT_GETTING_HIT, Integer.toString(tracker.getAttacksWithoutHit()));
}
}
}
private static long TWgetNewtotDamageToOneMonster(AttackInfo attack, MapleCharacter player, long newtotDamageToOneMonster, MapleMonster monster) {
newtotDamageToOneMonster += 额外伤害(player, newtotDamageToOneMonster, monster, true);
//计算段数和倍率
double[] 额外段数 = 额外段数(player, monster, true, attack.skill);
double[] 额外伤害倍率 = 额外伤害倍率(player, newtotDamageToOneMonster, monster, true, attack.skill);
String a = "";
String b = "";
String c = "";
String d = "";
String e = "";
//获得未减伤之前的真实伤害
long 额外真伤 = 额外真伤(player, newtotDamageToOneMonster, monster, true, attack.skill);
long v = 0;
if (额外段数[0] > 0.0) {
v = (long) (newtotDamageToOneMonster * (额外段数[0] * 额外段数[1]) / attack.hits);
newtotDamageToOneMonster += (long) v;
}
if (额外伤害倍率[0] > 0.0) {
newtotDamageToOneMonster += newtotDamageToOneMonster * (额外伤害倍率[0] / 100.0);
a = "伤害加成 #b" + (int) 额外伤害倍率[0] + "%#k";
}
if (额外段数[0] > 0.0) {
b = "额外段伤 #b" + (int) 额外段数[0] + "段#k";
String s = convertNumber(v);
c = "段伤伤害 #b" + s + "#k";
}
if (额外真伤 > 0) {
String s = convertNumber(额外真伤);
d = "切割伤害 #b" + s + "#k";
}
newtotDamageToOneMonster = 伤害减伤(monster.getId(), newtotDamageToOneMonster);
//将计算完减伤之后的伤害加上真实伤害
newtotDamageToOneMonster += 额外真伤;
String s2 = convertNumber(newtotDamageToOneMonster);
e = "伤害统计 #r" + s2 + "#k";
int length = e.length();
if (!a.isEmpty()) {
a = String.format("%-" + length + "s", a) ;
}
if (!b.isEmpty()) {
b = String.format("%-" + (length) + "s", b) ;
}
if (!c.isEmpty()) {
c = String.format("%-" + length + "s", c) ;
}
if (!d.isEmpty()) {
d = String.format("%-" + length + "s", d) ;
}
int targetWidth = e.length()+6; // 目标显示宽度(半角字符数)
String f = "";
String[] strs = {a, b, c, d, e};
for (String s : strs) {
if (s.isEmpty())continue;
int currentWidth = getDisplayWidth(s);
int spacesNeeded = (currentWidth >= targetWidth) ? 0 : (targetWidth - currentWidth);
// 填充空格并截断‌:ml-citation{ref="2,3" data="citationList"}
s= String.format("%s%" + spacesNeeded + "s", s, "").substring(0, Math.min(s.length() + spacesNeeded, s.length() + targetWidth)) ;
s+="\r\n";
f +=s;
// System.out.println("|" + aligned + "|");
}
e = a + b + c + d + e;
player.showInstruction(f, 130, 10);
return newtotDamageToOneMonster;
}
public static final void applyAttackMagic(final AttackInfo attack, final ISkill theSkill, final MapleCharacter player, final MapleStatEffect effect) {
if (!player.isAlive()) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACKING_WHILE_DEAD);
return;
}
if (attack.real) {
player.getCheatTracker().checkAttack(attack.skill, attack.lastAttackTickCount);
}
int last = (effect.getAttackCount() > effect.getBulletCount()) ? effect.getAttackCount() : effect.getBulletCount();
boolean mirror_fix = false;
if (player.getJob() >= 411 && player.getJob() <= 412) {
mirror_fix = true;
}
if (player.getJob() >= 1400 && player.getJob() <= 1412) {
mirror_fix = true;
}
if (attack.skill == 11101004) {
last = 2;
}
if (attack.skill == 15111007) {
last = 3;
}
last = 技能段数(attack.skill);
if (mirror_fix || player.getBuffedValue(MapleBuffStat.SHADOWPARTNER) != null) {
last *= 2;
}
if (attack.hits > last) {
if (!player.hasGmLevel(1)) {
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 攻击次数异常已自动封锁。 玩家攻击次数 " + (int) attack.hits + " 服务端判断正常攻击次数 " + last + " 技能ID " + attack.skill));
FileoutputUtil.logToFile("logs/Hack/Ban/技能攻击次数.txt", "\r\n" + FileoutputUtil.NowTime() + "玩家2: " + player.getName() + "(" + (int) player.getLevel() + ") 技能代码: " + attack.skill + " 技能等级: " + player.getSkillLevel(attack.skill) + " 攻击次数 : " + (int) attack.hits + " 正常攻击次数 :" + last);
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "技能攻击次数异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
final String reason = "使用违法程式练功";
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为" + reason + "而被管理员永久停权。"));
}
return;
}
player.dropMessage("攻击次数异常攻击次数 " + (int) attack.hits + " 服务端判断正常攻击次数 " + last + " 技能ID " + attack.skill);
}
int CheckCount = effect.getMobCount();
CheckCount = 技能个数(attack.skill);
if (attack.targets > CheckCount) {
if (!player.hasGmLevel(1)) {
FileoutputUtil.logToFile("logs/Hack/Ban/打怪数量异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家2: " + player.getName() + "(" + (int) player.getLevel() + ") 技能代码: " + attack.skill + " 技能等级: " + player.getSkillLevel(effect.getSourceId()) + " 封包怪物量 : " + (int) attack.targets + " 服务端怪物量 :" + CheckCount);
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 攻击怪物数量异常。 封包怪物量 " + (int) attack.targets + " 服务端怪物量 " + CheckCount + " 技能ID " + attack.skill));
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "打怪数量异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
final String reason2 = "使用违法程式练功";
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为" + reason2 + "而被管理员永久停权。"));
}
return;
}
player.dropMessage("打怪数量异常,技能代码: " + attack.skill + " 封包怪物量 : " + (int) attack.targets + " 服务端怪物量 :" + CheckCount);
}
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;
}
player.mulungEnergyModify(false);
}
if (GameConstants.isPyramidSkill(attack.skill)) {
if (player.getMapId() / 1000000 != 926) {
return;
}
if (player.getPyramidSubway() == null || !player.getPyramidSubway().onSkillUse(player)) {
return;
}
}
final PlayerStats stats = player.getStat();
//最终伤害值
double maxDamagePerHit;
if (attack.skill == 1000 || attack.skill == 10001000 || attack.skill == 20001000 || attack.skill == 20011000 || attack.skill == 30001000) {
maxDamagePerHit = 40.0;
} else if (GameConstants.isPyramidSkill(attack.skill)) {
maxDamagePerHit = 1.0;
} else {
final double v75 = (double) effect.getMatk() * 0.058;
maxDamagePerHit = (double) stats.getTotalMagic() * ((double) stats.getInt() * 0.5 + v75 * v75 + (double) effect.getMatk() * 3.3) / 100.0;
}
maxDamagePerHit *= 1.04;
final Element element = (player.getBuffedValue(MapleBuffStat.ELEMENT_RESET) != null) ? Element.NEUTRAL : theSkill.getElement();
double MaxDamagePerHit = 0.0;
int totDamage = 0;
final int CriticalDamage = stats.passive_sharpeye_percent();
final ISkill eaterSkill = SkillFactory.getSkill(GameConstants.getMPEaterForJob((int) player.getJob()));
final int eaterLevel = player.getSkillLevel(eaterSkill);
final MapleMap map = player.getMap();
if (map.getId() == 990010000) {
MaplePvp.doPvP(player, map, attack);
}
int 循环 = 0;
for (final AttackPair oned : attack.allDamage) {
final MapleMonster monster = map.getMonsterByOid(oned.objectid);
++循环;
if (monster != null) {
final boolean Tempest = monster.getStatusSourceID(MonsterStatus.FREEZE) == 21120006 && !monster.getStats().isBoss();
int totDamageToOneMonster = 0;
long newtotDamageToOneMonster = 0L;
final MapleMonsterStats monsterstats = monster.getStats();
final int fixeddmg = monsterstats.getFixedDamage();
MaxDamagePerHit = calculateMaxMagicDamagePerHit(player, theSkill, monster, monsterstats, stats, element, Integer.valueOf(CriticalDamage), maxDamagePerHit);
byte overallAttackCount = 0;
for (final Pair<Integer, Boolean> eachde : oned.attack) {
Integer eachd = (Integer) eachde.left;
++overallAttackCount;
if (!GameConstants.isElseSkill(attack.skill)) {
if (GameConstants.Novice_Skill(attack.skill) && eachd.intValue() > 40) {
if (!player.hasGmLevel(1)) {
FileoutputUtil.logToFile("logs/Hack/Ban/伤害异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家2<" + (int) player.getLevel() + ">: " + player.getName() + " 怪物 " + monster.getId() + " 地图: " + player.getMapId() + " 技能代码: " + attack.skill + " 最高伤害: 40 本次伤害 :" + eachd + " 预计伤害: " + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss());
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 最高伤害 40 本次伤害 " + eachd + " 技能ID " + attack.skill));
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "伤害异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为伤害异常而被管理员永久停权。"));
}
return;
}
player.dropMessage("[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 最高伤害 40 本次伤害 " + eachd + " 技能ID " + attack.skill);
}
int atk = 2140000001;
if (eachd.intValue() < 0) {
if (!player.hasGmLevel(1)) {
FileoutputUtil.logToFile("logs/Hack/Ban/伤害异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家<" + (int) player.getLevel() + ">: " + player.getName() + " 怪物 " + monster.getId() + " 地图: " + player.getMapId() + " 技能代码: " + attack.skill + " 伤害过低导致越界 本次伤害 :" + eachd + " 预计伤害: " + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss());
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 伤害过低导致越界本次伤害 " + eachd + " 技能ID " + attack.skill));
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "伤害异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为伤害异常而被管理员永久停权。"));
}
return;
}
player.dropMessage("[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 伤害过低导致越界本次伤害 " + eachd + " 技能ID " + attack.skill);
}
if (!GameConstants.isAran((int) player.getJob()) && player.getLevel() > 10) {
boolean ban = false;
if (((Integer) Start.ConfigValuesMap.get("伤害检测")).intValue() > 0) {
atk = ((Integer) Start.ConfigValuesMap.get("伤害上限")).intValue();
}
if (eachd.intValue() >= atk && (double) eachd.intValue() > Math.ceil(maxDamagePerHit * 1.2)) {
ban = true;
}
if ((long) eachd.intValue() == monster.getMobMaxHp()) {
ban = false;
}
if (ban) {
boolean apple = false;
if (player.getBuffSource(MapleBuffStat.WATK) == 2022179 || player.getBuffSource(MapleBuffStat.MATK) == 2022179 || player.getBuffSource(MapleBuffStat.WDEF) == 2022179) {
apple = true;
}
if (!player.hasGmLevel(1)) {
FileoutputUtil.logToFile("logs/Hack/Ban/伤害异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家2<" + (int) player.getLevel() + ">: " + player.getName() + " 怪物 " + monster.getId() + " 地图: " + player.getMapId() + " 技能代码: " + attack.skill + " 最高伤害: " + atk + " 本次伤害 :" + eachd + " 预计伤害: " + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss() + " 紫色蘋果: " + apple);
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 最高伤害 " + atk + " 本次伤害 " + eachd + " 技能ID " + attack.skill + "预计伤害: " + (int) maxDamagePerHit));
if (((Integer) Start.ConfigValuesMap.get("封停IP")).intValue() > 0) {
player.ban(player.getName() + "伤害异常", true, true, false);
}
if (((Integer) Start.ConfigValuesMap.get("封停MAC")).intValue() > 0) {
player.getClient().banMacs();
}
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
player.getClient().getSession().close();
}
if (((Integer) Start.ConfigValuesMap.get("全服通告")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为伤害异常而被管理员永久停权。"));
}
return;
}
player.dropMessage("[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 伤害异常。 最高伤害 " + atk + " 本次伤害 " + eachd + " 技能ID " + attack.skill + "预计伤害: " + (int) maxDamagePerHit);
}
}
}
if (fixeddmg != -1) {
eachd = Integer.valueOf(monsterstats.getOnlyNoramlAttack() ? 0 : fixeddmg);
} else if (monsterstats.getOnlyNoramlAttack()) {
eachd = Integer.valueOf(0);
} else if (!player.isGM() && ((Integer) Start.ConfigValuesMap.get("伤害修正")).intValue() > 0) {
if (!Tempest) {
if (!monster.isBuffed(MonsterStatus.DAMAGE_IMMUNITY) && !monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY) && !monster.isBuffed(MonsterStatus.MAGIC_DAMAGE_REFLECT)) {
if ((double) eachd.intValue() > maxDamagePerHit) {
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE, "[伤害: " + eachd + ", 预期: " + maxDamagePerHit + ", 怪物: " + monster.getId() + "] [职业: " + (int) player.getJob() + ", 等级: " + (int) player.getLevel() + ", 使用的技能: " + attack.skill + "]");
if (attack.real) {
player.getCheatTracker().checkSameDamage(eachd.intValue(), maxDamagePerHit);
}
if ((double) eachd.intValue() > MaxDamagePerHit * 2.0) {
eachd = Integer.valueOf((int) (MaxDamagePerHit * 2.0));
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_MAGIC_2, "[伤害: " + eachd + ", 预期: " + maxDamagePerHit + ", 怪物: " + monster.getId() + "] [职业: " + (int) player.getJob() + ", 等级: " + (int) player.getLevel() + ", 使用的技能: " + attack.skill + "]");
if (eachd.intValue() >= 10000 && ServerConfig.LOG_DAMAGE) {
FileoutputUtil.logToFile("Logs/hack/伤害计算/魔法伤害计算修正_" + attack.skill + ".txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家: " + player.getName() + "(" + (int) player.getLevel() + ") 职业: " + (int) player.getJob() + " 怪物:" + monster.getId() + " 封包伤害 :" + eachd + " 预计伤害 :" + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss(), false, false);
player.getCheatTracker().registerOffense(CheatingOffense.HIGH_DAMAGE_MAGIC_2, "[伤害: " + eachd + ", 预期: " + maxDamagePerHit + ", 怪物: " + monster.getId() + "] [职业: " + (int) player.getJob() + ", 等级: " + (int) player.getLevel() + ", 使用的技能: " + attack.skill + "]");
return;
}
}
}
} else if ((double) eachd.intValue() > maxDamagePerHit) {
eachd = Integer.valueOf((int) maxDamagePerHit);
if ((double) eachd.intValue() > MaxDamagePerHit * 2.0 && maxDamagePerHit != 1.0 && ServerConfig.LOG_DAMAGE) {
FileoutputUtil.logToFile("Logs/hack/伤害计算/魔法伤害计算修正_" + attack.skill + ".txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家: " + player.getName() + "(" + (int) player.getLevel() + ") 职业: " + (int) player.getJob() + " 怪物:" + monster.getId() + " 封包伤害 :" + eachd + " 预计伤害 :" + (int) maxDamagePerHit + "是否为BOSS: " + monster.getStats().isBoss(), false, false);
}
}
}
}
totDamageToOneMonster += eachd.intValue();
newtotDamageToOneMonster += (long) eachd.intValue();
}
totDamage += totDamageToOneMonster;
player.checkMonsterAggro(monster);
final double range = player.getPosition().distanceSq((Point2D) monster.getPosition());
double SkillRange = GameConstants.getAttackRange(player, effect, attack);
if (((Integer) Start.ConfigValuesMap.get("重置技能范围开关")).intValue() > 0) {
SkillRange = (double) ((Integer) Start.ConfigValuesMap.get("重置技能总范围")).intValue();
}
if (player.getDebugMessage() && range > SkillRange) {
player.dropMessage("技能[" + attack.skill + "] 预计范围: " + (int) SkillRange + " 实際范围: " + (int) range);
}
if (range > SkillRange && !player.inBossMap() && attack.skill != 5221004 && attack.skill != 21120006) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACK_FARAWAY_MONSTER, "攻击范围异常,技能:" + attack.skill + "(" + SkillFactory.getName(attack.skill) + ")\u3000正常范围:" + (int) SkillRange + " 计算范围:" + (int) range);
if (range > SkillRange * 2.0 && ((Integer) Start.ConfigValuesMap.get("全屏检测")).intValue() > 0) {
player.getCheatTracker().registerOffense(CheatingOffense.ATTACK_FARAWAY_MONSTER_BAN, "超大攻击范围,技能:" + attack.skill + "(" + SkillFactory.getName(attack.skill) + ")\u3000怪物:" + monster.getId() + " 正常范围:" + (int) SkillRange + " 计算范围:" + (int) range);
}
return;
}
if (attack.skill == 2301002 && !monsterstats.getUndead()) {
player.getCheatTracker().registerOffense(CheatingOffense.HEAL_ATTACKING_UNDEAD);
FileoutputUtil.logToFile("logs/Hack/Ban/技能异常.txt", "\r\n " + FileoutputUtil.NowTime() + " 玩家2<" + (int) player.getLevel() + ">: " + player.getName() + " 怪物 " + monster.getId() + " 地图: " + player.getMapId() + " 技能代码: " + attack.skill + " 使用群体治愈攻击非不死系怪物");
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM 密语系统] " + player.getName() + " (等级 " + (int) player.getLevel() + ") 技能异常。 使用群体治愈攻击非不死系怪物 技能ID " + attack.skill));
if (((Integer) Start.ConfigValuesMap.get("封停账号")).intValue() > 0) {
Broadcast.broadcastMessage(MaplePacketCreator.serverNotice(6, "[封锁系统] " + player.getName() + " 因为技能异常而被管理员永久停权。"));
player.ban(player.getName() + "修改WZ", true, true, false);
player.getClient().getSession().close();
return;
}
}
if (newtotDamageToOneMonster <= 0L) {
continue;
}
final tzjc t = new tzjc();
long newDamage = 0L;
newtotDamageToOneMonster = TWgetNewtotDamageToOneMonster(attack, player, newtotDamageToOneMonster, monster);
monster.damage(player, newtotDamageToOneMonster, true, attack.skill);
if (monster.getHp() > 0) {
player.dropMessage(-1, "当前怪物血量为: " + monster.getHp());
}
if (monster.isBuffed(MonsterStatus.MAGIC_DAMAGE_REFLECT)) {
player.addHP(-(7000 + Randomizer.nextInt(8000)));
}
switch (attack.skill) {
case 2221003: {
monster.setTempEffectiveness(Element.FIRE, (long) theSkill.getEffect((int) player.getSkillLevel(theSkill)).getDuration());
break;
}
case 2121003: {
monster.setTempEffectiveness(Element.ICE, (long) theSkill.getEffect((int) player.getSkillLevel(theSkill)).getDuration());
break;
}
}
if (effect.getMonsterStati().size() >= 0 && effect.makeChanceResult()) {
for (final Entry<MonsterStatus, Integer> z : effect.getMonsterStati().entrySet()) {
monster.applyStatus(player, new MonsterStatusEffect((MonsterStatus) z.getKey(), (Integer) z.getValue(), theSkill.getId(), null, false), effect.isPoison(), (long) effect.getDuration(), monster.getStats().isBoss(), effect);
}
}
if (eaterLevel <= 0) {
continue;
}
eaterSkill.getEffect(eaterLevel).applyPassive(player, (MapleMapObject) monster);
}
}
if (attack.skill != 2301002) {
effect.applyTo(player);
}
if (totDamage > 1) {
final 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(final MapleCharacter chr, final ISkill skill, final MapleMonster monster, final MapleMonsterStats mobstats, final PlayerStats stats, final Element elem, final Integer sharpEye, final double maxDamagePerMonster) {
final int dLevel = Math.max(mobstats.getLevel() - chr.getLevel(), 0);
final int Accuracy = (int) (Math.floor((double) stats.getTotalInt() / 10.0) + Math.floor((double) stats.getTotalLuk() / 10.0));
final int MinAccuracy = mobstats.getEva() * (dLevel * 2 + 51) / 120;
if (MinAccuracy > Accuracy && skill.getId() != 1000 && skill.getId() != 10001000 && skill.getId() != 20001000 && skill.getId() != 20011000 && skill.getId() != 30001000 && !GameConstants.isPyramidSkill(skill.getId())) {
return 0.0;
}
double elemMaxDamagePerMob = 0.0;
switch (monster.getEffectiveness(elem)) {
case IMMUNE: {
elemMaxDamagePerMob = 1.0;
break;
}
case NORMAL: {
elemMaxDamagePerMob = ElementalStaffAttackBonus(elem, maxDamagePerMonster, stats);
break;
}
case WEAK: {
elemMaxDamagePerMob = ElementalStaffAttackBonus(elem, maxDamagePerMonster * 1.5, stats);
break;
}
case STRONG: {
elemMaxDamagePerMob = ElementalStaffAttackBonus(elem, maxDamagePerMonster * 0.5, stats);
break;
}
default: {
throw new RuntimeException("Unknown enum constant");
}
}
elemMaxDamagePerMob -= (double) mobstats.getMagicDefense() * 0.5;
elemMaxDamagePerMob += elemMaxDamagePerMob / 100.0 * (double) sharpEye.intValue();
if (skill.getId() == 21120006) {
elemMaxDamagePerMob *= 15.0;
}
if (skill.getId() == 2211006) {
elemMaxDamagePerMob *= 2.0;
}
elemMaxDamagePerMob += elemMaxDamagePerMob * (mobstats.isBoss() ? stats.bossdam_r : stats.dam_r) / 100.0;
switch (skill.getId()) {
case 1000:
case 10001000:
case 20001000: {
elemMaxDamagePerMob = 40.0;
break;
}
case 1020:
case 10001020:
case 20001020: {
elemMaxDamagePerMob = 1.0;
break;
}
}
if (elemMaxDamagePerMob <= 500000.0) {
if (elemMaxDamagePerMob < 0.0) {
elemMaxDamagePerMob = 1.0;
}
}
return elemMaxDamagePerMob;
}
private static final double ElementalStaffAttackBonus(final Element elem, final double elemMaxDamagePerMob, final PlayerStats stats) {
switch (elem) {
case FIRE: {
return elemMaxDamagePerMob / 100.0 * (double) stats.element_fire;
}
case ICE: {
return elemMaxDamagePerMob / 100.0 * (double) stats.element_ice;
}
case LIGHTING: {
return elemMaxDamagePerMob / 100.0 * (double) stats.element_light;
}
case POISON: {
return elemMaxDamagePerMob / 100.0 * (double) stats.element_psn;
}
default: {
return elemMaxDamagePerMob / 100.0 * (double) stats.def;
}
}
}
private static void handlePickPocket(final MapleCharacter player, final MapleMonster mob, final AttackPair oned) {
final int maxmeso = player.getBuffedValue(MapleBuffStat.PICKPOCKET).intValue();
final ISkill skill = SkillFactory.getSkill(4211003);
final MapleStatEffect s = skill.getEffect((int) player.getSkillLevel(skill));
for (final Pair eachde : oned.attack) {
final Integer eachd = (Integer) eachde.left;
if (s.makeChanceResult()) {
player.getMap().spawnMesoDrop(Math.min((int) Math.max((double) eachd.intValue() / 20000.0 * (double) maxmeso, 1.0), maxmeso), new Point((int) (mob.getTruePosition().getX() + (double) Randomizer.nextInt(100) - 50.0), (int) mob.getTruePosition().getY()), (MapleMapObject) mob, player, false, (byte) 0);
}
}
}
private static double calculateMaxWeaponDamagePerHit(final MapleCharacter player, final MapleMonster monster, final AttackInfo attack, final ISkill theSkill, final MapleStatEffect attackEffect, double maximumDamageToMonster, final Integer CriticalDamagePercent) {
if (player.getMapId() / 1000000 == 914) {
return 5.0E8;
}
final List<Element> elements = (List<Element>) new ArrayList();
boolean defined = false;
if (theSkill != null) {
elements.add(theSkill.getElement());
if (monster.getStatusSourceID(MonsterStatus.FREEZE) == 21120006) {
defined = true;
}
switch (theSkill.getId()) {
case 3001004:
case 3221001: {
defined = true;
break;
}
case 1000:
case 10001000:
case 20001000:
case 20011000:
case 30001000: {
maximumDamageToMonster = 40.0;
defined = true;
break;
}
case 1020:
case 10001020:
case 20001020:
case 20011020:
case 30001020: {
maximumDamageToMonster = 1.0;
defined = true;
break;
}
case 3221007: {
maximumDamageToMonster = (double) (monster.getStats().isBoss() ? 500000L : monster.getMobMaxHp());
defined = true;
break;
}
case 1221011: {
maximumDamageToMonster = (double) (monster.getStats().isBoss() ? 500000L : (monster.getHp() - 1L));
defined = true;
break;
}
case 4211006: {
maximumDamageToMonster = (double) (monster.getStats().isBoss() ? 500000L : monster.getMobMaxHp());
defined = true;
break;
}
case 1009:
case 10001009:
case 20001009:
case 20011009:
case 30001009: {
defined = true;
maximumDamageToMonster = (double) (monster.getStats().isBoss() ? (monster.getMobMaxHp() / 30L * 100L) : monster.getMobMaxHp());
break;
}
case 3211006: {
if (monster.getStatusSourceID(MonsterStatus.FREEZE) == 3211003) {
defined = true;
maximumDamageToMonster = (double) monster.getHp();
break;
}
break;
}
case 5121007: {
maximumDamageToMonster *= 2.8;
break;
}
case 1111008:
case 1121006:
case 1311001:
case 1311006:
case 4201005: {
maximumDamageToMonster *= 3.0;
break;
}
case 1001004:
case 1121008:
case 4221001: {
maximumDamageToMonster *= 2.5;
break;
}
case 1001005:
case 1311004:
case 3121004: {
maximumDamageToMonster *= 2.0;
break;
}
}
}
if (MapleJob.is战神((int) player.getJob())) {
maximumDamageToMonster *= 2.0;
} else if (MapleJob.is拳霸((int) player.getJob())) {
maximumDamageToMonster *= 1.1;
}
if (player.getBuffedValue(MapleBuffStat.WK_CHARGE) != null) {
final 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: {
elements.clear();
break;
}
}
}
if (player.getBuffedValue(MapleBuffStat.LIGHTNING_CHARGE) != null) {
elements.add(Element.LIGHTING);
}
double elementalMaxDamagePerMonster = maximumDamageToMonster;
if (elements.size() > 0) {
double elementalEffect = 0.0;
switch (attack.skill) {
case 3111003:
case 3211003: {
elementalEffect = (double) attackEffect.getX() / 200.0;
break;
}
default: {
elementalEffect = 0.5;
break;
}
}
for (final Element element : elements) {
switch (monster.getEffectiveness(element)) {
case IMMUNE: {
elementalMaxDamagePerMonster = 1.0;
continue;
}
case WEAK: {
elementalMaxDamagePerMonster *= 1.0 + elementalEffect;
continue;
}
case STRONG: {
elementalMaxDamagePerMonster *= 1.0 - elementalEffect;
continue;
}
}
}
}
final short moblevel = monster.getStats().getLevel();
final short d = (short) ((moblevel > player.getLevel()) ? ((short) (moblevel - player.getLevel())) : 0);
elementalMaxDamagePerMonster = elementalMaxDamagePerMonster * (1.0 - 0.01 * (double) d) - (double) monster.getStats().getPhysicalDefense() * 0.5;
elementalMaxDamagePerMonster += elementalMaxDamagePerMonster / 100.0 * (double) CriticalDamagePercent.intValue();
if (theSkill != null && theSkill.isChargeSkill() && player.getKeyDownSkill_Time() == 0L && theSkill.getId() != 4111005) {
return 0.0;
}
final MapleStatEffect homing = player.getStatForBuff(MapleBuffStat.HOMING_BEACON);
if (homing != null && player.getLinkMid() == monster.getObjectId() && homing.getSourceId() == 5220011) {
elementalMaxDamagePerMonster += elementalMaxDamagePerMonster * (double) homing.getX();
}
final PlayerStats stat = player.getStat();
elementalMaxDamagePerMonster += elementalMaxDamagePerMonster * (monster.getStats().isBoss() ? (stat.bossdam_r * 2.0) : stat.dam_r) / 100.0;
switch (monster.getId()) {
case 1110101: {
elementalMaxDamagePerMonster *= 2.0;
break;
}
}
if (player.getDebugMessage()) {
player.dropMessage("[伤害计算]属性伤害:" + (int) Math.ceil(elementalMaxDamagePerMonster) + " BOSS伤害" + (int) Math.ceil((monster.getStats().isBoss() ? player.getStat().bossdam_r : player.getStat().dam_r) - 100.0) + "%");
}
if (elementalMaxDamagePerMonster > 500000.0) {
if (!defined) {
}
} else if (elementalMaxDamagePerMonster < 0.0) {
elementalMaxDamagePerMonster = 1.0;
}
return elementalMaxDamagePerMonster;
}
public static final AttackInfo DivideAttack(final AttackInfo attack, final int rate) {
attack.real = false;
for (final AttackPair p : attack.allDamage) {
if (p.attack != null) {
for (final Pair<Integer, Boolean> eachd : p.attack) {
long 伤害 = 0L;
伤害 = (long) ((Integer) eachd.left).intValue() * (long) (((Integer) Start.ConfigValuesMap.get("克隆基础伤害")).intValue() + rate) / 100L;
if (伤害 >= 21000000000L) {
eachd.left = Integer.valueOf(2100000000);
} else {
eachd.left = Integer.valueOf((int) 伤害);
}
}
}
}
return attack;
}
public static final AttackInfo Modify_AttackCrit(final AttackInfo attack, final MapleCharacter chr, final int type) {
final int criticalRate = chr.getStat().passive_sharpeye_rate();
final boolean shadow = (type == 2 && chr.getBuffedValue(MapleBuffStat.SHADOWPARTNER) != null) || (type == 1 && chr.getBuffedValue(MapleBuffStat.MIRROR_IMAGE) != null);
if (attack.skill != 4211006 && attack.skill != 3211003 && attack.skill != 4111004 && (criticalRate > 0 || attack.skill == 4221001 || attack.skill == 3221007)) {
for (final AttackPair attackPair : attack.allDamage) {
if (attackPair.attack != null) {
int hit = 0;
final int midAtt = attackPair.attack.size() / 2;
final List<Pair<Integer, Boolean>> eachd_copy = new ArrayList(attackPair.attack);
for (final Pair<Integer, Boolean> eachd : attackPair.attack) {
++hit;
if (!((Boolean) eachd.right).booleanValue()) {
if (attack.skill == 4221001) {
eachd.right = Boolean.valueOf(hit == 4 && Randomizer.nextInt(100) < 90);
} else if (attack.skill == 3221007 || ((Integer) eachd.left).intValue() > 199999) {
eachd.right = Boolean.valueOf(true);
} else if (shadow && hit > midAtt) {
eachd.right = (eachd_copy.get(hit - 1 - midAtt)).right;
} else {
eachd.right = Boolean.valueOf(Randomizer.nextInt(100) < criticalRate);
}
(eachd_copy.get(hit - 1)).right = eachd.right;
}
}
}
}
}
return attack;
}
public static final AttackInfo parseDmgMa(final LittleEndianAccessor lea, final MapleCharacter chr) {
final AttackInfo ret = new AttackInfo();
lea.skip(1);
lea.skip(8);
ret.tbyte = lea.readByte();
ret.targets = (byte) (ret.tbyte >>> 4 & 0xF);
ret.hits = (byte) (ret.tbyte & 0xF);
lea.skip(8);
ret.skill = lea.readInt();
lea.skip(12);
switch (ret.skill) {
case 2121001:
case 2221001:
case 2321001:
case 22121000:
case 22151001: {
ret.charge = lea.readInt();
break;
}
default: {
ret.charge = -1;
break;
}
}
lea.skip(1);
ret.unk = 0;
ret.display = lea.readByte();
ret.animation = lea.readByte();
lea.skip(1);
ret.speed = lea.readByte();
if (ret.display == 2126 && ret.speed == 5 && ret.skill == 0) {
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[系统警告] ID " + chr.getId() + " " + chr.getName() + " 疑似使用路飞霸气。 "));
}
ret.lastAttackTickCount = lea.readInt();
ret.allDamage = (List<AttackPair>) new ArrayList();
for (int i = 0; i < ret.targets; ++i) {
final int oid = lea.readInt();
lea.skip(14);
final List<Pair<Integer, Boolean>> allDamageNumbers = (List<Pair<Integer, Boolean>>) new ArrayList();
for (int j = 0; j < ret.hits; ++j) {
int damage = lea.readInt();
int 系统最大破功 = 199999;
if (((Integer) Start.ConfigValuesMap.get("伤害突破开关")).intValue() > 0) {
系统最大破功 = ((Integer) Start.ConfigValuesMap.get("突破上线")).intValue();
}
int maxdamage = 0;
if (((Integer) Start.ConfigValuesMap.get("装备卡破功开关")).intValue() > 0) {
int 破攻值 = 0;
int 装备破攻值 = 0;
破攻值 = 装备破功(chr);
装备破攻值 = 装备基础破功(chr);
maxdamage = 装备破攻值 + 破攻值;
}
if (((Integer) Start.ConfigValuesMap.get("装备卡破功开关")).intValue() > 0 && damage > maxdamage) {
damage = maxdamage;
}
if (((Integer) Start.ConfigValuesMap.get("表单卡破功开关")).intValue() > 0) {
maxdamage = (int) chr.getLimitBreak();
}
if (((Integer) Start.ConfigValuesMap.get("表单卡破功开关")).intValue() > 0 && damage > maxdamage) {
damage = maxdamage;
}
if (damage > 系统最大破功) {
damage = 系统最大破功;
}
if ((ret.skill == 3221007 || ret.skill == 4221001) && damage >= 199999) {
damage = 199999;
}
if (chr.isGM() && ((Integer) Start.ConfigValuesMap.get("GM固伤开关")).intValue() > 0) {
damage = GM伤害(chr);
}
if (((Integer) Start.ConfigValuesMap.get("所有显示开关")).intValue() > 0 && ((Integer) Start.ConfigValuesMap.get("突破显示开关")).intValue() > 0) {
chr.dropMessage(-1, "客户端传输实际伤害1: " + damage);
}
allDamageNumbers.add(new Pair(Integer.valueOf(damage), Boolean.valueOf(false)));
}
lea.skip(4);
ret.allDamage.add(new AttackPair(Integer.valueOf(oid).intValue(), allDamageNumbers));
}
ret.position = lea.readPos();
return ret;
}
public static final AttackInfo parseDmgM(final LittleEndianAccessor lea, final MapleCharacter chr) {
final AttackInfo ret = new AttackInfo();
lea.skip(1);
lea.skip(8);
ret.tbyte = lea.readByte();
ret.targets = (byte) (ret.tbyte >>> 4 & 0xF);
ret.hits = (byte) (ret.tbyte & 0xF);
lea.skip(8);
ret.skill = lea.readInt();
lea.skip(12);
switch (ret.skill) {
case 5101004:
case 5201002:
case 14111006:
case 15101003: {
ret.charge = lea.readInt();
break;
}
default: {
ret.charge = 0;
break;
}
}
ret.unk = lea.readByte();
ret.display = lea.readByte();
ret.animation = lea.readByte();
lea.skip(1);
ret.speed = lea.readByte();
if (ret.display == 2126 && ret.speed == 5 && ret.skill == 0) {
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[系统警告] ID " + chr.getId() + " " + chr.getName() + " 疑似使用路飞霸气。 "));
}
ret.lastAttackTickCount = lea.readInt();
ret.allDamage = (List<AttackPair>) new ArrayList();
if (ret.skill == 4211006) {
return parseExplosionAttack(lea, ret);
}
for (int i = 0; i < ret.targets; ++i) {
final int oid = lea.readInt();
lea.skip(14);
final List<Pair<Integer, Boolean>> allDamageNumbers = (List<Pair<Integer, Boolean>>) new ArrayList();
for (int j = 0; j < ret.hits; ++j) {
int damage = lea.readInt();
int 系统最大破功 = 199999;
if (((Integer) Start.ConfigValuesMap.get("伤害突破开关")).intValue() > 0) {
系统最大破功 = ((Integer) Start.ConfigValuesMap.get("突破上线")).intValue();
}
int maxdamage = 0;
if (((Integer) Start.ConfigValuesMap.get("装备卡破功开关")).intValue() > 0) {
int 破攻值 = 0;
int 装备破攻值 = 0;
破攻值 = 装备破功(chr);
装备破攻值 = 装备基础破功(chr);
maxdamage = 装备破攻值 + 破攻值;
}
if (((Integer) Start.ConfigValuesMap.get("装备卡破功开关")).intValue() > 0 && damage > maxdamage) {
damage = maxdamage;
}
if (((Integer) Start.ConfigValuesMap.get("表单卡破功开关")).intValue() > 0) {
maxdamage = (int) chr.getLimitBreak();
}
if (((Integer) Start.ConfigValuesMap.get("表单卡破功开关")).intValue() > 0 && damage > maxdamage) {
damage = maxdamage;
}
if (damage > 系统最大破功) {
damage = 系统最大破功;
}
if ((ret.skill == 3221007 || ret.skill == 4221001) && damage >= 199999) {
damage = 199999;
}
if (chr.isGM() && ((Integer) Start.ConfigValuesMap.get("GM固伤开关")).intValue() > 0) {
damage = GM伤害(chr);
}
if (((Integer) Start.ConfigValuesMap.get("所有显示开关")).intValue() > 0 && ((Integer) Start.ConfigValuesMap.get("突破显示开关")).intValue() > 0) {
chr.dropMessage(-1, "客户端传输实际伤害2: " + damage);
}
allDamageNumbers.add(new Pair(Integer.valueOf(damage), Boolean.valueOf(false)));
}
lea.skip(4);
ret.allDamage.add(new AttackPair(Integer.valueOf(oid).intValue(), allDamageNumbers));
}
ret.position = lea.readPos();
if (ret.skill == 14111006) {
ret.positionxy = lea.readPos();
}
return ret;
}
public static final AttackInfo parseDmgR(final LittleEndianAccessor lea, final MapleCharacter chr) {
final AttackInfo ret = new AttackInfo();
lea.skip(1);
lea.skip(8);
ret.tbyte = lea.readByte();
ret.targets = (byte) (ret.tbyte >>> 4 & 0xF);
ret.hits = (byte) (ret.tbyte & 0xF);
lea.skip(8);
ret.skill = lea.readInt();
lea.skip(12);
switch (ret.skill) {
case 3121004:
case 3221001:
case 5221004:
case 13111002: {
lea.skip(4);
break;
}
}
ret.charge = -1;
ret.unk = lea.readByte();
ret.display = lea.readByte();
ret.animation = lea.readByte();
lea.skip(1);
ret.speed = lea.readByte();
if (ret.display == 2126 && ret.speed == 5 && ret.skill == 0) {
Broadcast.broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[系统警告] ID " + chr.getId() + " " + chr.getName() + " 疑似使用路飞霸气。 "));
}
ret.lastAttackTickCount = lea.readInt();
ret.slot = (byte) lea.readShort();
ret.csstar = (byte) lea.readShort();
ret.AOE = lea.readByte();
ret.allDamage = (List<AttackPair>) new ArrayList();
for (int i = 0; i < ret.targets; ++i) {
final int oid = lea.readInt();
lea.skip(14);
final List<Pair<Integer, Boolean>> allDamageNumbers = (List<Pair<Integer, Boolean>>) new ArrayList();
for (int j = 0; j < ret.hits; ++j) {
int damage = lea.readInt();
int 系统最大破功 = 199999;
if (((Integer) Start.ConfigValuesMap.get("伤害突破开关")).intValue() > 0) {
系统最大破功 = ((Integer) Start.ConfigValuesMap.get("突破上线")).intValue();
}
int maxdamage = 0;
if (((Integer) Start.ConfigValuesMap.get("装备卡破功开关")).intValue() > 0) {
int 破攻值 = 0;
int 装备破攻值 = 0;
破攻值 = 装备破功(chr);
装备破攻值 = 装备基础破功(chr);
maxdamage = 装备破攻值 + 破攻值;
}
if (((Integer) Start.ConfigValuesMap.get("装备卡破功开关")).intValue() > 0 && damage > maxdamage) {
damage = maxdamage;
}
if (((Integer) Start.ConfigValuesMap.get("表单卡破功开关")).intValue() > 0) {
maxdamage = (int) chr.getLimitBreak();
}
if (((Integer) Start.ConfigValuesMap.get("表单卡破功开关")).intValue() > 0 && damage > maxdamage) {
damage = maxdamage;
}
if (damage > 系统最大破功) {
damage = 系统最大破功;
}
if ((ret.skill == 3221007 || ret.skill == 4221001) && damage >= 199999) {
damage = 199999;
}
if (chr.isGM() && ((Integer) Start.ConfigValuesMap.get("GM固伤开关")).intValue() > 0) {
damage = GM伤害(chr);
}
if (((Integer) Start.ConfigValuesMap.get("所有显示开关")).intValue() > 0 && ((Integer) Start.ConfigValuesMap.get("突破显示开关")).intValue() > 0) {
chr.dropMessage(-1, "客户端传输实际伤害3: " + damage);
}
allDamageNumbers.add(new Pair(Integer.valueOf(damage), Boolean.valueOf(false)));
}
lea.skip(4);
ret.allDamage.add(new AttackPair(Integer.valueOf(oid).intValue(), allDamageNumbers));
}
lea.skip(4);
ret.position = lea.readPos();
return ret;
}
public static final AttackInfo parseExplosionAttack(final LittleEndianAccessor lea, final AttackInfo ret) {
if (ret.hits == 0) {
lea.skip(4);
final byte bullets = lea.readByte();
for (int j = 0; j < bullets; ++j) {
ret.allDamage.add(new AttackPair(lea.readInt(), null));
lea.skip(1);
}
lea.skip(2);
return ret;
}
for (int i = 0; i < ret.targets; ++i) {
final int oid = lea.readInt();
lea.skip(12);
final byte bullets2 = lea.readByte();
final List<Pair<Integer, Boolean>> allDamageNumbers = (List<Pair<Integer, Boolean>>) new ArrayList();
for (int k = 0; k < bullets2; ++k) {
allDamageNumbers.add(new Pair(Integer.valueOf(lea.readInt()), Boolean.valueOf(false)));
}
ret.allDamage.add(new AttackPair(oid, allDamageNumbers));
lea.skip(4);
}
lea.skip(4);
final byte bullets = lea.readByte();
for (int j = 0; j < bullets; ++j) {
ret.allDamage.add(new AttackPair(lea.readInt(), null));
lea.skip(1);
}
lea.skip(2);
return ret;
}
public static int GM伤害(final MapleCharacter chr) {
final int 伤害 = ((Integer) Start.ConfigValuesMap.get("GM固伤伤害")).intValue();
return 伤害;
}
public static int 装备破功(final MapleCharacter chr) {
int 破攻值 = 0;
int 破攻系数 = 0;
final IItem 装备 = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) (-11));
if (装备 != null && 装备 instanceof Equip) {
破攻系数 = MapleItemInformationProvider.getInstance().getHands((Equip) 装备);
破攻值 = 破攻系数 * 10000;
}
return 破攻值;
}
public static int 技能段数(final int skill) {
int last = 99;
if (((Integer) Start.ConfigValuesMap.get("段数检测")).intValue() > 0) {
for (int a = 0; a < Start.SkillType.size(); ++a) {
if (skill == ((SkillType) Start.SkillType.get(a)).getSkillId()) {
last = ((SkillType) Start.SkillType.get(a)).getAttackCount();
break;
}
}
}
return last;
}
public static int 技能个数(final int skill) {
int last = 99;
if (((Integer) Start.ConfigValuesMap.get("个数检测")).intValue() > 0) {
for (int a = 0; a < Start.SkillType.size(); ++a) {
if (skill == ((SkillType) Start.SkillType.get(a)).getSkillId()) {
last = ((SkillType) Start.SkillType.get(a)).getMobCount();
break;
}
}
}
return last;
}
public static long 伤害减伤(final int mobid, final long damage) {
long 数值 = 0L;
if (((Integer) Start.ConfigValuesMap.get("怪物减伤开关")).intValue() > 0) {
数值 = (long) Math.floor((double) (damage / (long) getMobRedDam(mobid)));
} else {
数值 = damage;
}
return 数值;
}
public static double[] 额外段数(final MapleCharacter play, final MapleMonster monster, boolean mag, int skillId) {
double Magnification = 0.0;
if (Start.ConfigValuesJson == null) return new double[]{0.0, 0.0};
Magnification = play.getDD();
Double ddxs = Start.ConfigValuesJson.getJSONObject("ddxs").getDouble(String.valueOf(skillId));
if (ddxs == null) {
ddxs = 1.0;
}
if (Magnification == 0) {
return new double[]{0.0, 0.0};
}
return new double[]{Magnification, ddxs};
}
public static double[] 额外伤害倍率(final MapleCharacter play, long damage, final MapleMonster monster, boolean mag, int skillId) {
double Magnification = 0.0;
Magnification = play.getDB();
Double ddxs = Start.ConfigValuesJson.getJSONObject("dbxs").getDouble(String.valueOf(skillId));
if (ddxs == null) {
ddxs = 1.0;
}
return new double[]{Magnification, ddxs};
}
public static long 额外真伤(final MapleCharacter play, long damage, final MapleMonster monster, boolean mag, int skillId) {
double Magnification = 0.0;
Magnification = play.getQG();
Double qgxs = Start.ConfigValuesJson.getJSONObject("qgxs").getDouble(String.valueOf(skillId));
if (qgxs == null) {
qgxs = 1.0;
}
if (Magnification > 0) {
return (long) ((Magnification * qgxs));
} else {
return 0;
}
}
public static long 额外伤害(final MapleCharacter play, final long damage, final MapleMonster monster, boolean mag) {
long 数值 = 0L;
try {
if (damage >= Integer.MAX_VALUE) {
if (mag)
数值 = (long) (play.getStat().calculateMaxBaseDamage(play.getStat().getTotalMagic(), play.getStat().getTotalWatk()) * 14);
else
数值 = (long) (play.getStat().calculateMaxBaseDamage(play.getStat().getTotalMagic(), play.getStat().getTotalWatk()) * 525);
}
if (((Integer) Start.ConfigValuesMap.get("自定义伤害加成开关")).intValue() < 1) {
return 数值;
}
if (damage >= (long) ((Integer) Start.ConfigValuesMap.get("伤害高于次数值")).intValue() || (((Integer) Start.ConfigValuesMap.get("道具加成自定义伤害开关")).intValue() > 0 && play.getItemQuantity(((Integer) Start.ConfigValuesMap.get("自定义伤害加成道具代码")).intValue(), false) > 0)) {
数值 = (long) play.getComStr() * (long) ((Integer) Start.ConfigValuesMap.get("自定义力量加成比例")).intValue() + (long) play.getComDex() * (long) ((Integer) Start.ConfigValuesMap.get("自定义敏捷加成比例")).intValue() + (long) play.getComInt() * (long) ((Integer) Start.ConfigValuesMap.get("自定义智力加成比例")).intValue() + (long) play.getComLuk() * (long) ((Integer) Start.ConfigValuesMap.get("自定义运气加成比例")).intValue() + (long) play.getComWatk() * (long) ((Integer) Start.ConfigValuesMap.get("自定义物攻加成比例")).intValue() + (long) play.getComMatk() * (long) ((Integer) Start.ConfigValuesMap.get("自定义魔攻加成比例")).intValue() + (long) play.getComWdef() * (long) ((Integer) Start.ConfigValuesMap.get("自定义物防加成比例")).intValue() + (long) play.getComMdef() * (long) ((Integer) Start.ConfigValuesMap.get("自定义魔防加成比例")).intValue() + (long) play.getComHp() * (long) ((Integer) Start.ConfigValuesMap.get("自定义血量加成比例")).intValue() + (long) play.getComMp() * (long) ((Integer) Start.ConfigValuesMap.get("自定义魔量加成比例")).intValue();
}
if (((Integer) Start.ConfigValuesMap.get("扣除21E伤害")).intValue() > 0) {
数值 -= 21474836470L;
}
if (((Integer) Start.ConfigValuesMap.get("自定义伤害气泡显示")).intValue() > 0) {
play.showInstruction("【#r额外伤害 → " + 数值 + "#k】", 240, 10);
}
if (((Integer) Start.ConfigValuesMap.get("自定义伤害黄字喇叭显示")).intValue() > 0) {
play.dropMessage(-1, "【额外伤害 →" + 数值 + "");
}
if (数值 > 0) {
play.dropMessage(-1, "【额外伤害 →" + 数值 + "");
play.getMap().broadcastMessage(MobPacket.damageMonster(monster.getObjectId(), (long) (int) 数值));
}
} catch (Exception e) {
FileoutputUtil.outError("logs/额外伤害异常.txt", (Throwable) e);
return 数值;
}
return 数值;
}
public static int 装备基础破功(final MapleCharacter chr) {
int 破攻值1 = 0;
int 装备等级 = 0;
final IItem 装备 = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) (-11));
if (装备 != null) {
装备等级 = MapleItemInformationProvider.getInstance().getReqLevel(装备.getItemId());
}
if (装备等级 < 120) {
破攻值1 = 199999;
} else if (装备等级 >= 120 && 装备等级 < 125) {
破攻值1 = 249999;
} else if (装备等级 >= 125 && 装备等级 < 130) {
破攻值1 = 299999;
} else if (装备等级 >= 130 && 装备等级 < 135) {
破攻值1 = 349999;
} else if (装备等级 >= 135 && 装备等级 < 140) {
破攻值1 = 399999;
} else if (装备等级 >= 140 && 装备等级 < 145) {
破攻值1 = 449999;
} else if (装备等级 >= 145 && 装备等级 < 150) {
破攻值1 = 499999;
} else if (装备等级 >= 150 && 装备等级 < 160) {
破攻值1 = 549999;
} else if (装备等级 >= 160 && 装备等级 < 180) {
破攻值1 = 599999;
} else if (装备等级 >= 180 && 装备等级 < 200) {
破攻值1 = 699999;
} else if (装备等级 >= 200 && 装备等级 < 230) {
破攻值1 = 799999;
} else if (装备等级 >= 230 && 装备等级 <= 255) {
破攻值1 = 999999;
}
return 破攻值1;
}
public static void readMobRedDam() {
DamageParse.MobRedDam.clear();
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = (Connection) DBConPool.getInstance().getDataSource().getConnection();
ps = con.prepareStatement("SELECT * FROM mobreddam");
rs = ps.executeQuery();
while (rs.next()) {
final Integer sn = Integer.valueOf(rs.getInt("mobid"));
final Integer numb = Integer.valueOf(rs.getInt("numb"));
DamageParse.MobRedDam.put(sn, numb);
}
rs.close();
ps.close();
} catch (Exception e) {
FileoutputUtil.outError("logs/减伤读取异常.txt", (Throwable) e);
DBConPool.cleanUP(rs, ps, con);
e.printStackTrace();
} finally {
DBConPool.cleanUP(rs, ps, con);
}
}
public static int getMobRedDam(final int mobid) {
if (DamageParse.MobRedDam.get(Integer.valueOf(mobid)) != null) {
return ((Integer) DamageParse.MobRedDam.get(Integer.valueOf(mobid))).intValue();
}
return 1;
}
static {
readMobRedDam();
}
// 计算字符串显示宽度全角字符算2半角算1
private static int getDisplayWidth(String s) {
return s.codePoints().map(c -> (c <= 255) ? 1 : 2).sum();
}
public static String convertNumber(long number) {
if (number < 10000) {
// 数字小于 10000直接返回原数字
return String.valueOf(number);
} else if (number < 100000000) {
// 数字大于等于 10000 且小于 1 亿,转换为以“万”为单位
double result = (double) number / 10000;
return String.format("%.0f万", result);
} else if (number < 10000000000000000L) {
// 数字大于等于 1 亿 且小于 1 京,转换为以“亿”为单位
double result = (double) number / 100000000;
return String.format("%.0f亿", result);
} else {
// 数字大于等于 1 京,转换为以“京”为单位
double result = (double) number / 10000000000000000L;
return String.format("%.0f京", result);
}
}
}