1904 lines
109 KiB
Java
1904 lines
109 KiB
Java
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);
|
||
}
|
||
}
|
||
|
||
|
||
}
|