Add attack delay to AttackInfo

Meant to be used in item drop packet for timing handled by the client
rather than scheduling item drop packets on the server.
This commit is contained in:
P0nk
2024-08-14 07:45:06 +02:00
parent 8f2c2dc08f
commit 2ffca90d29
6 changed files with 163 additions and 128 deletions

View File

@@ -117,7 +117,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
public static class AttackInfo {
public int numAttacked, numDamage, numAttackedAndDamage, skill, skilllevel, stance, direction, rangedirection, charge, display;
public Map<Integer, List<Integer>> allDamage;
public Map<Integer, AttackTarget> targets;
public boolean ranged, magic;
public int speed = 4;
public Point position = new Point();
@@ -146,6 +146,9 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
}
}
// TODO: add position
public record AttackTarget(short delay, List<Integer> damageLines) {}
protected void applyAttack(AttackInfo attack, final Character player, int attackCount) {
final MapleMap map = player.getMap();
if (map.isOwnershipRestricted(player)) {
@@ -216,7 +219,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
if (attack.skill == ChiefBandit.MESO_EXPLOSION) {
int delay = 0;
for (Integer oned : attack.allDamage.keySet()) {
for (Integer oned : attack.targets.keySet()) {
MapObject mapobject = map.getMapObject(oned);
if (mapobject != null && mapobject.getType() == MapObjectType.ITEM) {
final MapItem mapitem = (MapItem) mapobject;
@@ -249,7 +252,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
}
}
}
for (Integer oned : attack.allDamage.keySet()) {
for (Integer oned : attack.targets.keySet()) {
final Monster monster = map.getMonsterByOid(oned);
if (monster != null) {
double distance = player.getPosition().distanceSq(monster.getPosition());
@@ -285,7 +288,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
}
int totDamageToOneMonster = 0;
List<Integer> onedList = attack.allDamage.get(oned);
List<Integer> onedList = attack.targets.get(oned).damageLines();
if (attack.magic) { // thanks BHB, Alex (CanIGetaPR) for noticing no immunity status check here
if (monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) {
@@ -600,7 +603,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
ret.numAttackedAndDamage = p.readByte();
ret.numAttacked = (ret.numAttackedAndDamage >>> 4) & 0xF;
ret.numDamage = ret.numAttackedAndDamage & 0xF;
ret.allDamage = new HashMap<>();
ret.targets = new HashMap<>();
ret.skill = p.readInt();
ret.ranged = ranged;
ret.magic = magic;
@@ -629,7 +632,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
for (int j = 0; j < bullets; j++) {
int mesoid = p.readInt();
p.skip(1);
ret.allDamage.put(mesoid, null);
ret.targets.put(mesoid, null);
}
return ret;
} else {
@@ -638,6 +641,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
for (int i = 0; i < ret.numAttacked + 1; i++) {
int oid = p.readInt();
if (i < ret.numAttacked) {
// TODO: read delay in from these skipped bytes
p.skip(12);
int bullets = p.readByte();
List<Integer> allDamageNumbers = new ArrayList<>();
@@ -645,14 +649,14 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
int damage = p.readInt();
allDamageNumbers.add(damage);
}
ret.allDamage.put(oid, allDamageNumbers);
ret.targets.put(oid, new AttackTarget((short) 0, allDamageNumbers));
p.skip(4);
} else {
int bullets = p.readByte();
for (int j = 0; j < bullets; j++) {
int mesoid = p.readInt();
p.skip(1);
ret.allDamage.put(mesoid, null);
ret.targets.put(mesoid, null);
}
}
}
@@ -814,10 +818,12 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
}
for (int i = 0; i < ret.numAttacked; i++) {
int oid = p.readInt();
p.skip(14);
List<Integer> allDamageNumbers = new ArrayList<>();
Monster monster = chr.getMap().getMonsterByOid(oid);
p.skip(4);
Point curPos = p.readPos();
Point nextPos = p.readPos();
short delay = p.readShort();
List<Integer> damageLines = new ArrayList<>();
final Monster monster = chr.getMap().getMonsterByOid(oid);
if (chr.getBuffEffect(BuffStat.WK_CHARGE) != null) {
// Charge, so now we need to check elemental effectiveness
int sourceID = chr.getBuffSource(BuffStat.WK_CHARGE);
@@ -941,12 +947,12 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
}
}
allDamageNumbers.add(damage);
damageLines.add(damage);
}
if (ret.skill != Corsair.RAPID_FIRE || ret.skill != Aran.HIDDEN_FULL_DOUBLE || ret.skill != Aran.HIDDEN_FULL_TRIPLE || ret.skill != Aran.HIDDEN_OVER_DOUBLE || ret.skill != Aran.HIDDEN_OVER_TRIPLE) {
p.skip(4);
}
ret.allDamage.put(oid, allDamageNumbers);
ret.targets.put(oid, new AttackTarget(delay, damageLines));
}
if (ret.skill == NightWalker.POISON_BOMB) { // Poison Bomb
p.skip(4);
@@ -954,8 +960,4 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
}
return ret;
}
private static int rand(int l, int u) {
return (int) ((Math.random() * (u - l + 1)) + l);
}
}

View File

@@ -78,7 +78,9 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
c.sendPacket(PacketCreator.getEnergy("energy", chr.getDojoEnergy()));
}
chr.getMap().broadcastMessage(chr, PacketCreator.closeRangeAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, attack.speed, attack.direction, attack.display), false, true);
chr.getMap().broadcastMessage(chr, PacketCreator.closeRangeAttack(chr, attack.skill, attack.skilllevel,
attack.stance, attack.numAttackedAndDamage, attack.targets, attack.speed, attack.direction,
attack.display), false, true);
int numFinisherOrbs = 0;
Integer comboBuff = chr.getBuffedValue(BuffStat.COMBO);
if (GameConstants.isFinisherSkill(attack.skill)) {
@@ -139,9 +141,9 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
}
if (attack.numAttacked > 0 && attack.skill == DragonKnight.SACRIFICE) {
int totDamageToOneMonster = 0; // sacrifice attacks only 1 mob with 1 attack
final Iterator<List<Integer>> dmgIt = attack.allDamage.values().iterator();
final Iterator<AttackTarget> dmgIt = attack.targets.values().iterator();
if (dmgIt.hasNext()) {
totDamageToOneMonster = dmgIt.next().get(0);
totDamageToOneMonster = dmgIt.next().damageLines().getFirst();
}
chr.safeAddHP(-1 * totDamageToOneMonster * attack.getAttackEffect(chr, null).getX() / 100);

View File

@@ -66,7 +66,8 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
}
int charge = (attack.skill == Evan.FIRE_BREATH || attack.skill == Evan.ICE_BREATH || attack.skill == FPArchMage.BIG_BANG || attack.skill == ILArchMage.BIG_BANG || attack.skill == Bishop.BIG_BANG) ? attack.charge : -1;
Packet packet = PacketCreator.magicAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, charge, attack.speed, attack.direction, attack.display);
Packet packet = PacketCreator.magicAttack(chr, attack.skill, attack.skilllevel, attack.stance,
attack.numAttackedAndDamage, attack.targets, charge, attack.speed, attack.direction, attack.display);
chr.getMap().broadcastMessage(chr, packet, false, true);
StatEffect effect = attack.getAttackEffect(chr, null);
@@ -84,8 +85,8 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
Skill eaterSkill = SkillFactory.getSkill((chr.getJob().getId() - (chr.getJob().getId() % 10)) * 10000);// MP Eater, works with right job
int eaterLevel = chr.getSkillLevel(eaterSkill);
if (eaterLevel > 0) {
for (Integer singleDamage : attack.allDamage.keySet()) {
eaterSkill.getEffect(eaterLevel).applyPassive(chr, chr.getMap().getMapObject(singleDamage), 0);
for (Integer oid : attack.targets.keySet()) {
eaterSkill.getEffect(eaterLevel).applyPassive(chr, chr.getMap().getMapObject(oid), 0);
}
}
}

View File

@@ -83,17 +83,23 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
}
if (attack.skill == Buccaneer.ENERGY_ORB || attack.skill == ThunderBreaker.SPARK || attack.skill == Shadower.TAUNT || attack.skill == NightLord.TAUNT) {
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, 0, attack.allDamage, attack.speed, attack.direction, attack.display), false);
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel,
attack.stance, attack.numAttackedAndDamage, 0, attack.targets, attack.speed,
attack.direction, attack.display), false);
applyAttack(attack, chr, 1);
} else if (attack.skill == ThunderBreaker.SHARK_WAVE && chr.getSkillLevel(ThunderBreaker.SHARK_WAVE) > 0) {
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, 0, attack.allDamage, attack.speed, attack.direction, attack.display), false);
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel,
attack.stance, attack.numAttackedAndDamage, 0, attack.targets, attack.speed,
attack.direction, attack.display), false);
applyAttack(attack, chr, 1);
for (int i = 0; i < attack.numAttacked; i++) {
chr.handleEnergyChargeGain();
}
} else if (attack.skill == Aran.COMBO_SMASH || attack.skill == Aran.COMBO_FENRIR || attack.skill == Aran.COMBO_TEMPEST) {
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, 0, attack.allDamage, attack.speed, attack.direction, attack.display), false);
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel,
attack.stance, attack.numAttackedAndDamage, 0, attack.targets, attack.speed,
attack.direction, attack.display), false);
if (attack.skill == Aran.COMBO_SMASH && chr.getCombo() >= 30) {
chr.setCombo((short) 0);
applyAttack(attack, chr, 1);
@@ -213,10 +219,14 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
case 3221001: // Pierce
case 5221004: // Rapid Fire
case 13111002: // KoC Hurricane
packet = PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.rangedirection, attack.numAttackedAndDamage, visProjectile, attack.allDamage, attack.speed, attack.direction, attack.display);
packet = PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.rangedirection,
attack.numAttackedAndDamage, visProjectile, attack.targets, attack.speed,
attack.direction, attack.display);
break;
default:
packet = PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, visProjectile, attack.allDamage, attack.speed, attack.direction, attack.display);
packet = PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance,
attack.numAttackedAndDamage, visProjectile, attack.targets, attack.speed,
attack.direction, attack.display);
break;
}
chr.getMap().broadcastMessage(chr, packet, false, true);