Fix drop delay from summon attack
This commit is contained in:
@@ -41,31 +41,14 @@ import server.life.MonsterInformationProvider;
|
|||||||
import server.maps.Summon;
|
import server.maps.Summon;
|
||||||
import tools.PacketCreator;
|
import tools.PacketCreator;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class SummonDamageHandler extends AbstractDealDamageHandler {
|
public final class SummonDamageHandler extends AbstractDealDamageHandler {
|
||||||
private static final Logger log = LoggerFactory.getLogger(SummonDamageHandler.class);
|
private static final Logger log = LoggerFactory.getLogger(SummonDamageHandler.class);
|
||||||
|
|
||||||
public final class SummonAttackEntry {
|
public record SummonAttackTarget(int monsterOid, int damage, short delay) {}
|
||||||
|
|
||||||
private final int monsterOid;
|
|
||||||
private final int damage;
|
|
||||||
|
|
||||||
public SummonAttackEntry(int monsterOid, int damage) {
|
|
||||||
this.monsterOid = monsterOid;
|
|
||||||
this.damage = damage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMonsterOid() {
|
|
||||||
return monsterOid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDamage() {
|
|
||||||
return damage;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handlePacket(InPacket p, Client c) {
|
public void handlePacket(InPacket p, Client c) {
|
||||||
@@ -86,17 +69,21 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler {
|
|||||||
Skill summonSkill = SkillFactory.getSkill(summon.getSkill());
|
Skill summonSkill = SkillFactory.getSkill(summon.getSkill());
|
||||||
StatEffect summonEffect = summonSkill.getEffect(summon.getSkillLevel());
|
StatEffect summonEffect = summonSkill.getEffect(summon.getSkillLevel());
|
||||||
p.skip(4);
|
p.skip(4);
|
||||||
List<SummonAttackEntry> allDamage = new ArrayList<>();
|
List<SummonAttackTarget> targets = new ArrayList<>();
|
||||||
byte direction = p.readByte();
|
byte direction = p.readByte();
|
||||||
int numAttacked = p.readByte();
|
int numAttacked = p.readByte();
|
||||||
p.skip(8); // I failed lol (mob x,y and summon x,y), Thanks Gerald
|
p.skip(8); // I failed lol (mob x,y and summon x,y), Thanks Gerald
|
||||||
for (int x = 0; x < numAttacked; x++) {
|
for (int x = 0; x < numAttacked; x++) {
|
||||||
int monsterOid = p.readInt(); // attacked oid
|
int monsterOid = p.readInt(); // attacked oid
|
||||||
p.skip(18); // TODO: find "delay" among these 18 skipped bytes
|
p.skip(8);
|
||||||
|
Point curPos = p.readPos();
|
||||||
|
Point nextPos = p.readPos();
|
||||||
|
short delay = p.readShort();
|
||||||
int damage = p.readInt();
|
int damage = p.readInt();
|
||||||
allDamage.add(new SummonAttackEntry(monsterOid, damage));
|
targets.add(new SummonAttackTarget(monsterOid, damage, delay));
|
||||||
}
|
}
|
||||||
player.getMap().broadcastMessage(player, PacketCreator.summonAttack(player.getId(), summon.getObjectId(), direction, allDamage), summon.getPosition());
|
player.getMap().broadcastMessage(player, PacketCreator.summonAttack(player.getId(), summon.getObjectId(),
|
||||||
|
direction, targets), summon.getPosition());
|
||||||
|
|
||||||
if (player.getMap().isOwnershipRestricted(player)) {
|
if (player.getMap().isOwnershipRestricted(player)) {
|
||||||
return;
|
return;
|
||||||
@@ -104,13 +91,16 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler {
|
|||||||
|
|
||||||
boolean magic = summonEffect.getWatk() == 0;
|
boolean magic = summonEffect.getWatk() == 0;
|
||||||
int maxDmg = calcMaxDamage(summonEffect, player, magic); // thanks Darter (YungMoozi) for reporting unchecked max dmg
|
int maxDmg = calcMaxDamage(summonEffect, player, magic); // thanks Darter (YungMoozi) for reporting unchecked max dmg
|
||||||
for (SummonAttackEntry attackEntry : allDamage) {
|
for (SummonAttackTarget target : targets) {
|
||||||
int damage = attackEntry.getDamage();
|
int damage = target.damage();
|
||||||
Monster target = player.getMap().getMonsterByOid(attackEntry.getMonsterOid());
|
Monster mob = player.getMap().getMonsterByOid(target.monsterOid());
|
||||||
if (target != null) {
|
if (mob == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (damage > maxDmg) {
|
if (damage > maxDmg) {
|
||||||
AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing summon damage exploit.");
|
AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing summon damage exploit.");
|
||||||
final String mobName = MonsterInformationProvider.getInstance().getMobNameFromId(target.getId());
|
final String mobName = MonsterInformationProvider.getInstance().getMobNameFromId(mob.getId());
|
||||||
log.info("Possible exploit - chr {} used a summon of skillId {} to attack {} with damage {} (max: {})",
|
log.info("Possible exploit - chr {} used a summon of skillId {} to attack {} with damage {} (max: {})",
|
||||||
c.getPlayer().getName(), summon.getSkill(), mobName, damage, maxDmg);
|
c.getPlayer().getName(), summon.getSkill(), mobName, damage, maxDmg);
|
||||||
damage = maxDmg;
|
damage = maxDmg;
|
||||||
@@ -118,11 +108,11 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler {
|
|||||||
|
|
||||||
if (damage > 0 && summonEffect.getMonsterStati().size() > 0) {
|
if (damage > 0 && summonEffect.getMonsterStati().size() > 0) {
|
||||||
if (summonEffect.makeChanceResult()) {
|
if (summonEffect.makeChanceResult()) {
|
||||||
target.applyStatus(player, new MonsterStatusEffect(summonEffect.getMonsterStati(), summonSkill, null, false), summonEffect.isPoison(), 4000);
|
mob.applyStatus(player, new MonsterStatusEffect(summonEffect.getMonsterStati(), summonSkill, null, false), summonEffect.isPoison(), 4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
player.getMap().damageMonster(player, target, damage);
|
player.getMap().damageMonster(player, mob, damage, target.delay());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (summon.getSkill() == Outlaw.GAVIOTA) { // thanks Periwinks for noticing Gaviota not cancelling after grenade toss
|
if (summon.getSkill() == Outlaw.GAVIOTA) { // thanks Periwinks for noticing Gaviota not cancelling after grenade toss
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ import net.server.Server;
|
|||||||
import net.server.channel.Channel;
|
import net.server.channel.Channel;
|
||||||
import net.server.channel.handlers.AbstractDealDamageHandler.AttackTarget;
|
import net.server.channel.handlers.AbstractDealDamageHandler.AttackTarget;
|
||||||
import net.server.channel.handlers.PlayerInteractionHandler;
|
import net.server.channel.handlers.PlayerInteractionHandler;
|
||||||
import net.server.channel.handlers.SummonDamageHandler.SummonAttackEntry;
|
import net.server.channel.handlers.SummonDamageHandler.SummonAttackTarget;
|
||||||
import net.server.channel.handlers.WhisperHandler;
|
import net.server.channel.handlers.WhisperHandler;
|
||||||
import net.server.guild.Alliance;
|
import net.server.guild.Alliance;
|
||||||
import net.server.guild.Guild;
|
import net.server.guild.Guild;
|
||||||
@@ -2305,18 +2305,18 @@ public class PacketCreator {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Packet summonAttack(int cid, int summonOid, byte direction, List<SummonAttackEntry> allDamage) {
|
public static Packet summonAttack(int cid, int summonOid, byte direction, List<SummonAttackTarget> targets) {
|
||||||
OutPacket p = OutPacket.create(SendOpcode.SUMMON_ATTACK);
|
OutPacket p = OutPacket.create(SendOpcode.SUMMON_ATTACK);
|
||||||
//b2 00 29 f7 00 00 9a a3 04 00 c8 04 01 94 a3 04 00 06 ff 2b 00
|
//b2 00 29 f7 00 00 9a a3 04 00 c8 04 01 94 a3 04 00 06 ff 2b 00
|
||||||
p.writeInt(cid);
|
p.writeInt(cid);
|
||||||
p.writeInt(summonOid);
|
p.writeInt(summonOid);
|
||||||
p.writeByte(0); // char level
|
p.writeByte(0); // char level
|
||||||
p.writeByte(direction);
|
p.writeByte(direction);
|
||||||
p.writeByte(allDamage.size());
|
p.writeByte(targets.size());
|
||||||
for (SummonAttackEntry attackEntry : allDamage) {
|
for (SummonAttackTarget target : targets) {
|
||||||
p.writeInt(attackEntry.getMonsterOid()); // oid
|
p.writeInt(target.monsterOid()); // oid
|
||||||
p.writeByte(6); // who knows
|
p.writeByte(6); // who knows
|
||||||
p.writeInt(attackEntry.getDamage()); // damage
|
p.writeInt(target.damage()); // damage
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
|||||||
Reference in New Issue
Block a user