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

1904 lines
109 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}
}