From 802cc2b5f5b252a2201215a4da4a4da0647fa6a7 Mon Sep 17 00:00:00 2001 From: P0nk Date: Sat, 17 Aug 2024 18:49:28 +0200 Subject: [PATCH] Use delay from packets for drop timing --- .../command/commands/gm3/KillAllCommand.java | 2 +- .../handlers/AbstractDealDamageHandler.java | 25 +-- .../channel/handlers/AdminCommandHandler.java | 2 +- .../handlers/FieldDamageMobHandler.java | 2 +- .../channel/handlers/MesoDropHandler.java | 5 +- .../channel/handlers/MobDamageMobHandler.java | 31 ++-- .../channel/handlers/SummonDamageHandler.java | 4 +- .../channel/handlers/TakeDamageHandler.java | 4 +- .../channel/handlers/UseCatchItemHandler.java | 24 +-- .../reactor/ReactorActionManager.java | 9 +- src/main/java/server/life/Monster.java | 4 +- src/main/java/server/maps/MapItem.java | 5 +- src/main/java/server/maps/MapleMap.java | 167 ++++++++---------- src/main/java/tools/PacketCreator.java | 5 +- 14 files changed, 147 insertions(+), 142 deletions(-) diff --git a/src/main/java/client/command/commands/gm3/KillAllCommand.java b/src/main/java/client/command/commands/gm3/KillAllCommand.java index 787e48343f..398f270008 100644 --- a/src/main/java/client/command/commands/gm3/KillAllCommand.java +++ b/src/main/java/client/command/commands/gm3/KillAllCommand.java @@ -49,7 +49,7 @@ public class KillAllCommand extends Command { for (MapObject monstermo : monsters) { Monster monster = (Monster) monstermo; if (!monster.getStats().isFriendly() && !(monster.getId() >= MobId.DEAD_HORNTAIL_MIN && monster.getId() <= MobId.HORNTAIL)) { - map.damageMonster(player, monster, Integer.MAX_VALUE); + map.damageMonster(player, monster, Integer.MAX_VALUE, (short) 0); count++; } } diff --git a/src/main/java/net/server/channel/handlers/AbstractDealDamageHandler.java b/src/main/java/net/server/channel/handlers/AbstractDealDamageHandler.java index b9b80b9b32..cea8b1a937 100644 --- a/src/main/java/net/server/channel/handlers/AbstractDealDamageHandler.java +++ b/src/main/java/net/server/channel/handlers/AbstractDealDamageHandler.java @@ -252,8 +252,8 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler { } } } - for (Integer oned : attack.targets.keySet()) { - final Monster monster = map.getMonsterByOid(oned); + for (Map.Entry target : attack.targets.entrySet()) { + final Monster monster = map.getMonsterByOid(target.getKey()); if (monster != null) { double distance = player.getPosition().distanceSq(monster.getPosition()); double distanceToDetect = 200000.0; @@ -288,7 +288,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler { } int totDamageToOneMonster = 0; - List onedList = attack.targets.get(oned).damageLines(); + List onedList = target.getValue().damageLines(); if (attack.magic) { // thanks BHB, Alex (CanIGetaPR) for noticing no immunity status check here if (monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) { @@ -324,7 +324,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler { Skill pickpocket = SkillFactory.getSkill(ChiefBandit.PICKPOCKET); int picklv = (player.isGM()) ? pickpocket.getMaxLevel() : player.getSkillLevel(pickpocket); if (picklv > 0) { - int delay = 0; + short delay = 0; final int maxmeso = player.getBuffedValue(BuffStat.PICKPOCKET); for (Integer eachd : onedList) { eachd += Integer.MAX_VALUE; @@ -337,7 +337,9 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler { eachdf = eachd; } - TimerManager.getInstance().schedule(() -> map.spawnMesoDrop(Math.min((int) Math.max(((double) eachdf / (double) 20000) * (double) maxmeso, 1), maxmeso), new Point((int) (monster.getPosition().getX() + Randomizer.nextInt(100) - 50), (int) (monster.getPosition().getY())), monster, player, true, (byte) 2), delay); + int meso = Math.min((int) Math.max(((double) eachdf / (double) 20000) * (double) maxmeso, 1), maxmeso); + Point position = new Point((int) (monster.getPosition().getX() + Randomizer.nextInt(100) - 50), (int) (monster.getPosition().getY())); + map.spawnMesoDrop(meso, position, monster, player, true, (byte) 2, delay); delay += 100; } } @@ -363,7 +365,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler { List toSteal = new ArrayList<>(); toSteal.add(mi.retrieveDrop(monster.getId()).get(i)); - map.dropItemsFromMonster(toSteal, player, monster); + map.dropItemsFromMonster(toSteal, player, monster, target.getValue().delay()); monster.addStolen(toSteal.get(0).itemId); } } @@ -483,7 +485,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler { StatEffect mortal = mortalBlow.getEffect(skillLevel); if (monster.getHp() <= (monster.getStats().getHp() * mortal.getX()) / 100) { if (Randomizer.rand(1, 100) <= mortal.getY()) { - map.damageMonster(player, monster, Integer.MAX_VALUE); // thanks Conrad for noticing reduced EXP gain from skill kill + map.damageMonster(player, monster, Integer.MAX_VALUE, target.getValue().delay()); // thanks Conrad for noticing reduced EXP gain from skill kill } } } @@ -549,7 +551,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler { map.broadcastMessage(PacketCreator.damageMonster(monster.getObjectId(), totDamageToOneMonster)); } - map.damageMonster(player, monster, totDamageToOneMonster); + map.damageMonster(player, monster, totDamageToOneMonster, target.getValue().delay()); } if (monster.isBuffed(MonsterStatus.WEAPON_REFLECT) && !attack.magic) { for (MobSkillId msId : monster.getSkills()) { @@ -576,7 +578,8 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler { } } - private static void damageMonsterWithSkill(final Character attacker, final MapleMap map, final Monster monster, final int damage, int skillid, int fixedTime) { + private static void damageMonsterWithSkill(final Character attacker, final MapleMap map, final Monster monster, + final int damage, int skillid, int fixedTime) { int animationTime; if (fixedTime == 0) { @@ -588,11 +591,11 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler { if (animationTime > 0) { // be sure to only use LIMITED ATTACKS with animation time here TimerManager.getInstance().schedule(() -> { map.broadcastMessage(PacketCreator.damageMonster(monster.getObjectId(), damage), monster.getPosition()); - map.damageMonster(attacker, monster, damage); + map.damageMonster(attacker, monster, damage, (short) 0); }, animationTime); } else { map.broadcastMessage(PacketCreator.damageMonster(monster.getObjectId(), damage), monster.getPosition()); - map.damageMonster(attacker, monster, damage); + map.damageMonster(attacker, monster, damage, (short) 0); } } diff --git a/src/main/java/net/server/channel/handlers/AdminCommandHandler.java b/src/main/java/net/server/channel/handlers/AdminCommandHandler.java index 3cd9dd6704..182087606a 100644 --- a/src/main/java/net/server/channel/handlers/AdminCommandHandler.java +++ b/src/main/java/net/server/channel/handlers/AdminCommandHandler.java @@ -133,7 +133,7 @@ public final class AdminCommandHandler extends AbstractPacketHandler { for (int x = 0; x < amount; x++) { Monster monster = (Monster) monsterx.get(x); if (monster.getId() == mobToKill) { - c.getPlayer().getMap().killMonster(monster, c.getPlayer(), true); + c.getPlayer().getMap().killMonster(monster, c.getPlayer(), true, (short) 0); } } break; diff --git a/src/main/java/net/server/channel/handlers/FieldDamageMobHandler.java b/src/main/java/net/server/channel/handlers/FieldDamageMobHandler.java index 6fdb98b197..2007c8822e 100644 --- a/src/main/java/net/server/channel/handlers/FieldDamageMobHandler.java +++ b/src/main/java/net/server/channel/handlers/FieldDamageMobHandler.java @@ -56,7 +56,7 @@ public class FieldDamageMobHandler extends AbstractPacketHandler { } map.broadcastMessage(chr, PacketCreator.damageMonster(mobOid, dmg), true); - map.damageMonster(chr, mob, dmg); + map.damageMonster(chr, mob, dmg, (short) 0); } } } diff --git a/src/main/java/net/server/channel/handlers/MesoDropHandler.java b/src/main/java/net/server/channel/handlers/MesoDropHandler.java index f99c7edbee..94389b96b7 100644 --- a/src/main/java/net/server/channel/handlers/MesoDropHandler.java +++ b/src/main/java/net/server/channel/handlers/MesoDropHandler.java @@ -67,7 +67,8 @@ public final class MesoDropHandler extends AbstractPacketHandler { if (player.attemptCatchFish(meso)) { player.getMap().disappearingMesoDrop(meso, player, player, player.getPosition()); } else { - player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2); + player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2, + (short) 0); } } -} \ No newline at end of file +} diff --git a/src/main/java/net/server/channel/handlers/MobDamageMobHandler.java b/src/main/java/net/server/channel/handlers/MobDamageMobHandler.java index ad50bd5afb..3b62ddcad4 100644 --- a/src/main/java/net/server/channel/handlers/MobDamageMobHandler.java +++ b/src/main/java/net/server/channel/handlers/MobDamageMobHandler.java @@ -57,21 +57,24 @@ public final class MobDamageMobHandler extends AbstractPacketHandler { Monster attacker = map.getMonsterByOid(from); Monster damaged = map.getMonsterByOid(to); - if (attacker != null && damaged != null) { - int maxDmg = calcMaxDamage(attacker, damaged, magic); // thanks Darter (YungMoozi) for reporting unchecked dmg - - if (dmg > maxDmg) { - AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing hypnotize damage exploit."); // thanks Rien dev team - String attackerName = MonsterInformationProvider.getInstance().getMobNameFromId(attacker.getId()); - String damagedName = MonsterInformationProvider.getInstance().getMobNameFromId(damaged.getId()); - log.warn("Chr {} had hypnotized {} to attack {} with damage {} (max: {})", c.getPlayer().getName(), - attackerName, damagedName, dmg, maxDmg); - dmg = maxDmg; - } - - map.damageMonster(chr, damaged, dmg); - map.broadcastMessage(chr, PacketCreator.damageMonster(to, dmg), false); + if (attacker == null || damaged == null) { + return; } + + int maxDmg = calcMaxDamage(attacker, damaged, magic); // thanks Darter (YungMoozi) for reporting unchecked dmg + + if (dmg > maxDmg) { + AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing hypnotize damage exploit."); // thanks Rien dev team + String attackerName = MonsterInformationProvider.getInstance().getMobNameFromId(attacker.getId()); + String damagedName = MonsterInformationProvider.getInstance().getMobNameFromId(damaged.getId()); + log.warn("Chr {} had hypnotized {} to attack {} with damage {} (max: {})", c.getPlayer().getName(), + attackerName, damagedName, dmg, maxDmg); + dmg = maxDmg; + } + + map.damageMonster(chr, damaged, dmg, (short) 0); + map.broadcastMessage(chr, PacketCreator.damageMonster(to, dmg), false); + } private static int calcMaxDamage(Monster attacker, Monster damaged, boolean magic) { diff --git a/src/main/java/net/server/channel/handlers/SummonDamageHandler.java b/src/main/java/net/server/channel/handlers/SummonDamageHandler.java index 5506818992..837c8f357a 100644 --- a/src/main/java/net/server/channel/handlers/SummonDamageHandler.java +++ b/src/main/java/net/server/channel/handlers/SummonDamageHandler.java @@ -92,7 +92,7 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler { p.skip(8); // I failed lol (mob x,y and summon x,y), Thanks Gerald for (int x = 0; x < numAttacked; x++) { int monsterOid = p.readInt(); // attacked oid - p.skip(18); + p.skip(18); // TODO: find "delay" among these 18 skipped bytes int damage = p.readInt(); allDamage.add(new SummonAttackEntry(monsterOid, damage)); } @@ -121,7 +121,7 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler { target.applyStatus(player, new MonsterStatusEffect(summonEffect.getMonsterStati(), summonSkill, null, false), summonEffect.isPoison(), 4000); } } - player.getMap().damageMonster(player, target, damage); + player.getMap().damageMonster(player, target, damage, (short) 0); } } diff --git a/src/main/java/net/server/channel/handlers/TakeDamageHandler.java b/src/main/java/net/server/channel/handlers/TakeDamageHandler.java index 5207307bfb..c8d2e0ddd9 100644 --- a/src/main/java/net/server/channel/handlers/TakeDamageHandler.java +++ b/src/main/java/net/server/channel/handlers/TakeDamageHandler.java @@ -178,7 +178,7 @@ public final class TakeDamageHandler extends AbstractPacketHandler { if (bouncedamage > attacker.getMaxHp() / 5) { bouncedamage = attacker.getMaxHp() / 5; } - map.damageMonster(chr, attacker, bouncedamage); + map.damageMonster(chr, attacker, bouncedamage, (short) 0); map.broadcastMessage(chr, PacketCreator.damageMonster(oid, bouncedamage), true); chr.sendPacket(PacketCreator.showOwnBuffEffect(id, 5)); map.broadcastMessage(chr, PacketCreator.showBuffEffect(chr.getId(), id, 5), false); @@ -211,7 +211,7 @@ public final class TakeDamageHandler extends AbstractPacketHandler { int bouncedamage = (int) (damage * (chr.getBuffedValue(BuffStat.POWERGUARD).doubleValue() / (attacker.isBoss() ? 200 : 100))); bouncedamage = Math.min(bouncedamage, attacker.getMaxHp() / 10); damage -= bouncedamage; - map.damageMonster(chr, attacker, bouncedamage); + map.damageMonster(chr, attacker, bouncedamage, (short) 0); map.broadcastMessage(chr, PacketCreator.damageMonster(oid, bouncedamage), false, true); attacker.aggroMonsterDamage(chr, bouncedamage); } diff --git a/src/main/java/net/server/channel/handlers/UseCatchItemHandler.java b/src/main/java/net/server/channel/handlers/UseCatchItemHandler.java index ead6813e66..781bdcd032 100644 --- a/src/main/java/net/server/channel/handlers/UseCatchItemHandler.java +++ b/src/main/java/net/server/channel/handlers/UseCatchItemHandler.java @@ -61,7 +61,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { case ItemId.PHEROMONE_PERFUME: if (mob.getId() == MobId.TAMABLE_HOG) { chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, ItemId.HOG, (short) 1, "", -1); } @@ -72,7 +72,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { if ((abm.getLastSpam(10) + 1000) < currentServerTime()) { if (mob.getHp() < ((mob.getMaxHp() / 10) * 4)) { chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, ItemId.GHOST_SACK, (short) 1, "", -1); } else { @@ -90,7 +90,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { if (chr.canHold(ItemId.ARPQ_SPIRIT_JEWEL, 1)) { if (Math.random() < 0.5) { // 50% chance chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, ItemId.ARPQ_SPIRIT_JEWEL, (short) 1, "", -1); chr.updateAriantScore(); @@ -113,7 +113,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { if (mob.getId() == MobId.LOST_RUDOLPH) { if (mob.getHp() < ((mob.getMaxHp() / 10) * 4)) { chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, ItemId.TAMED_RUDOLPH, (short) 1, "", -1); } else { @@ -126,7 +126,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { if (mob.getId() == MobId.KING_SLIME_DOJO) { if (mob.getHp() < ((mob.getMaxHp() / 10) * 3)) { chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, ItemId.MONSTER_MARBLE_1, (short) 1, "", -1); } else { @@ -139,7 +139,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { if (mob.getId() == MobId.FAUST_DOJO) { if (mob.getHp() < ((mob.getMaxHp() / 10) * 3)) { chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, ItemId.MONSTER_MARBLE_2, (short) 1, "", -1); } else { @@ -152,7 +152,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { if (mob.getId() == MobId.MUSHMOM_DOJO) { if (mob.getHp() < ((mob.getMaxHp() / 10) * 3)) { chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, ItemId.MONSTER_MARBLE_3, (short) 1, "", -1); } else { @@ -165,7 +165,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { if (mob.getId() == MobId.POISON_FLOWER) { if (mob.getHp() < ((mob.getMaxHp() / 10) * 4)) { chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, ItemId.EPQ_MONSTER_MARBLE, (short) 1, "", -1); } else { @@ -179,7 +179,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { if ((abm.getLastSpam(10) + 3000) < currentServerTime()) { abm.spam(10); chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, ItemId.FISH_NET_WITH_A_CATCH, (short) 1, "", -1); } else { @@ -202,7 +202,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { if (timeCatch != 0 && (abm.getLastSpam(10) + timeCatch) < currentServerTime()) { if (mobHp != 0 && mob.getHp() < ((mob.getMaxHp() / 100) * mobHp)) { chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1)); - mob.getMap().killMonster(mob, null, false); + killMonster(mob); InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true); InventoryManipulator.addById(c, itemGanho, (short) 1, "", -1); } else if (mob.getId() != MobId.P_JUNIOR) { @@ -220,4 +220,8 @@ public final class UseCatchItemHandler extends AbstractPacketHandler { // System.out.println("UseCatchItemHandler: \r\n" + slea.toString()); } } + + private static void killMonster(Monster mob) { + mob.getMap().killMonster(mob, null, false, (short) 0); + } } diff --git a/src/main/java/scripting/reactor/ReactorActionManager.java b/src/main/java/scripting/reactor/ReactorActionManager.java index b7f7c4e6a7..b5a9a50cd0 100644 --- a/src/main/java/scripting/reactor/ReactorActionManager.java +++ b/src/main/java/scripting/reactor/ReactorActionManager.java @@ -172,7 +172,8 @@ public class ReactorActionManager extends AbstractPlayerInteraction { int range = maxMeso - minMeso; int displayDrop = (int) (Math.random() * range) + minMeso; int mesoDrop = (displayDrop * c.getWorldServer().getMesoRate()); - reactor.getMap().spawnMesoDrop(mesoDrop, reactor.getMap().calcDropPos(dropPos, reactor.getPosition()), reactor, c.getPlayer(), false, (byte) 2); + reactor.getMap().spawnMesoDrop(mesoDrop, reactor.getMap().calcDropPos(dropPos, + reactor.getPosition()), reactor, c.getPlayer(), false, (byte) 2, (short) 0); } else { Item drop; @@ -192,6 +193,7 @@ public class ReactorActionManager extends AbstractPlayerInteraction { dropPos.x -= (12 * items.size()); + // TODO: simply use "delay" drop packet instead of this scheduled task sprayTask = TimerManager.getInstance().register(() -> { if (dropItems.isEmpty()) { sprayTask.cancel(false); @@ -203,7 +205,8 @@ public class ReactorActionManager extends AbstractPlayerInteraction { int range = maxMeso - minMeso; int displayDrop = (int) (Math.random() * range) + minMeso; int mesoDrop = (displayDrop * worldMesoRate); - r.getMap().spawnMesoDrop(mesoDrop, r.getMap().calcDropPos(dropPos, r.getPosition()), r, chr, false, (byte) 2); + r.getMap().spawnMesoDrop(mesoDrop, r.getMap().calcDropPos(dropPos, r.getPosition()), r, chr, + false, (byte) 2, (short) 0); } else { Item drop; @@ -333,4 +336,4 @@ public class ReactorActionManager extends AbstractPlayerInteraction { getPlayer().getMap().getBlueTeamBuffs().remove(skil); } } -} \ No newline at end of file +} diff --git a/src/main/java/server/life/Monster.java b/src/main/java/server/life/Monster.java index ea3beb85dd..e3ad4bf5b8 100644 --- a/src/main/java/server/life/Monster.java +++ b/src/main/java/server/life/Monster.java @@ -825,12 +825,12 @@ public class Monster extends AbstractLoadedLife { } if (htKilled) { - reviveMap.killMonster(ht, killer, true); + reviveMap.killMonster(ht, killer, true, (short) 0); } } for (int i = MobId.DEAD_HORNTAIL_MAX; i >= MobId.DEAD_HORNTAIL_MIN; i--) { - reviveMap.killMonster(reviveMap.getMonsterById(i), killer, true); + reviveMap.killMonster(reviveMap.getMonsterById(i), killer, true, (short) 0); } } else if (controller != null) { mob.aggroSwitchController(controller, aggro); diff --git a/src/main/java/server/maps/MapItem.java b/src/main/java/server/maps/MapItem.java index 9f1086d842..b87306990a 100644 --- a/src/main/java/server/maps/MapItem.java +++ b/src/main/java/server/maps/MapItem.java @@ -208,7 +208,8 @@ public class MapItem extends AbstractMapObject { if (chr.needQuestItem(questid, getItemId())) { this.lockItem(); try { - client.sendPacket(PacketCreator.dropItemFromMapObject(chr, this, null, getPosition(), (byte) 2)); + client.sendPacket(PacketCreator.dropItemFromMapObject(chr, this, null, getPosition(), + (byte) 2, (short) 0)); } finally { this.unlockItem(); } @@ -219,4 +220,4 @@ public class MapItem extends AbstractMapObject { public void sendDestroyData(final Client client) { client.sendPacket(PacketCreator.removeItemFromMap(getObjectId(), 1, 0)); } -} \ No newline at end of file +} diff --git a/src/main/java/server/maps/MapleMap.java b/src/main/java/server/maps/MapleMap.java index 9440fc48ff..f9f28d1363 100644 --- a/src/main/java/server/maps/MapleMap.java +++ b/src/main/java/server/maps/MapleMap.java @@ -654,7 +654,8 @@ public class MapleMap { } } - private byte dropItemsFromMonsterOnMap(List dropEntry, Point pos, byte d, int chRate, byte droptype, int mobpos, Character chr, Monster mob) { + private byte dropItemsFromMonsterOnMap(List dropEntry, Point pos, byte d, int chRate, + byte droptype, int mobpos, Character chr, Monster mob, short delay) { if (dropEntry.isEmpty()) { return d; } @@ -686,7 +687,8 @@ public class MapleMap { mesos = Integer.MAX_VALUE; } - spawnMesoDrop(mesos, calcDropPos(pos, mob.getPosition()), mob, chr, false, droptype); + spawnMesoDrop(mesos, calcDropPos(pos, mob.getPosition()), mob, chr, false, droptype, + delay); } } else { if (ItemConstants.getInventoryType(de.itemId) == InventoryType.EQUIP) { @@ -694,7 +696,7 @@ public class MapleMap { } else { idrop = new Item(de.itemId, (short) 0, (short) (de.Maximum != 1 ? Randomizer.nextInt(de.Maximum - de.Minimum) + de.Minimum : 1)); } - spawnDrop(idrop, calcDropPos(pos, mob.getPosition()), mob, chr, droptype, de.questid); + spawnDrop(idrop, calcDropPos(pos, mob.getPosition()), mob, chr, droptype, de.questid, delay); } d++; } @@ -703,7 +705,8 @@ public class MapleMap { return d; } - private byte dropGlobalItemsFromMonsterOnMap(List globalEntry, Point pos, byte d, byte droptype, int mobpos, Character chr, Monster mob) { + private byte dropGlobalItemsFromMonsterOnMap(List globalEntry, Point pos, byte d, + byte droptype, int mobpos, Character chr, Monster mob, short delay) { Collections.shuffle(globalEntry); Item idrop; @@ -722,7 +725,7 @@ public class MapleMap { } else { idrop = new Item(de.itemId, (short) 0, (short) (de.Maximum != 1 ? Randomizer.nextInt(de.Maximum - de.Minimum) + de.Minimum : 1)); } - spawnDrop(idrop, calcDropPos(pos, mob.getPosition()), mob, chr, droptype, de.questid); + spawnDrop(idrop, calcDropPos(pos, mob.getPosition()), mob, chr, droptype, de.questid, delay); d++; } } @@ -731,7 +734,7 @@ public class MapleMap { return d; } - private void dropFromMonster(final Character chr, final Monster mob, final boolean useBaseRate) { + private void dropFromMonster(final Character chr, final Monster mob, final boolean useBaseRate, short delay) { if (mob.dropsDisabled() || !dropsOn) { return; } @@ -765,10 +768,11 @@ public class MapleMap { return; } - registerMobItemDrops(droptype, mobpos, chRate, pos, dropEntry, visibleQuestEntry, otherQuestEntry, globalEntry, chr, mob); + registerMobItemDrops(droptype, mobpos, chRate, pos, dropEntry, visibleQuestEntry, otherQuestEntry, globalEntry, + chr, mob, delay); } - public void dropItemsFromMonster(List list, final Character chr, final Monster mob) { + public void dropItemsFromMonster(List list, final Character chr, final Monster mob, short delay) { if (mob.dropsDisabled() || !dropsOn) { return; } @@ -779,15 +783,16 @@ public class MapleMap { byte d = 1; Point pos = new Point(0, mob.getPosition().y); - dropItemsFromMonsterOnMap(list, pos, d, chRate, droptype, mobpos, chr, mob); + dropItemsFromMonsterOnMap(list, pos, d, chRate, droptype, mobpos, chr, mob, delay); } public void dropFromFriendlyMonster(final Character chr, final Monster mob) { - dropFromMonster(chr, mob, true); + dropFromMonster(chr, mob, true, (short) 0); } public void dropFromReactor(final Character chr, final Reactor reactor, Item drop, Point dropPos, short questid) { - spawnDrop(drop, this.calcDropPos(dropPos, reactor.getPosition()), reactor, chr, (byte) (chr.getParty() != null ? 1 : 0), questid); + spawnDrop(drop, this.calcDropPos(dropPos, reactor.getPosition()), reactor, chr, + (byte) (chr.getParty() != null ? 1 : 0), questid, (short) 0); } private void stopItemMonitor() { @@ -965,8 +970,12 @@ public class MapleMap { } } - private void registerMobItemDrops(byte droptype, int mobpos, int chRate, Point pos, List dropEntry, List visibleQuestEntry, List otherQuestEntry, List globalEntry, Character chr, Monster mob) { - MobLootEntry mle = new MobLootEntry(droptype, mobpos, chRate, pos, dropEntry, visibleQuestEntry, otherQuestEntry, globalEntry, chr, mob); + private void registerMobItemDrops(byte droptype, int mobpos, int chRate, Point pos, + List dropEntry, List visibleQuestEntry, + List otherQuestEntry, List globalEntry, + Character chr, Monster mob, short delay) { + MobLootEntry mle = new MobLootEntry(droptype, mobpos, chRate, pos, delay, dropEntry, visibleQuestEntry, + otherQuestEntry, globalEntry, chr, mob); if (YamlConfig.config.server.USE_SPAWN_LOOT_ON_ANIMATION) { int animationTime = mob.getAnimationTime("die1"); @@ -1123,7 +1132,8 @@ public class MapleMap { } } - private void spawnDrop(final Item idrop, final Point dropPos, final MapObject dropper, final Character chr, final byte droptype, final short questid) { + private void spawnDrop(final Item idrop, final Point dropPos, final MapObject dropper, final Character chr, + final byte droptype, final short questid, short delay) { final MapItem mdrop = new MapItem(idrop, dropPos, dropper, chr, chr.getClient(), droptype, false, questid); mdrop.setDropTime(Server.getInstance().getCurrentTime()); spawnAndAddRangedMapObject(mdrop, c -> { @@ -1132,7 +1142,8 @@ public class MapleMap { if (chr1.needQuestItem(questid, idrop.getItemId())) { mdrop.lockItem(); try { - c.sendPacket(PacketCreator.dropItemFromMapObject(chr1, mdrop, dropper.getPosition(), dropPos, (byte) 1)); + c.sendPacket(PacketCreator.dropItemFromMapObject(chr1, mdrop, dropper.getPosition(), dropPos, + (byte) 1, delay)); } finally { mdrop.unlockItem(); } @@ -1143,7 +1154,8 @@ public class MapleMap { activateItemReactors(mdrop, chr.getClient()); } - public final void spawnMesoDrop(final int meso, final Point position, final MapObject dropper, final Character owner, final boolean playerDrop, final byte droptype) { + public final void spawnMesoDrop(final int meso, final Point position, final MapObject dropper, + final Character owner, final boolean playerDrop, final byte droptype, short delay) { final Point droppos = calcDropPos(position, position); final MapItem mdrop = new MapItem(meso, droppos, dropper, owner, owner.getClient(), droptype, playerDrop); mdrop.setDropTime(Server.getInstance().getCurrentTime()); @@ -1151,7 +1163,8 @@ public class MapleMap { spawnAndAddRangedMapObject(mdrop, c -> { mdrop.lockItem(); try { - c.sendPacket(PacketCreator.dropItemFromMapObject(c.getPlayer(), mdrop, dropper.getPosition(), droppos, (byte) 1)); + c.sendPacket(PacketCreator.dropItemFromMapObject(c.getPlayer(), mdrop, dropper.getPosition(), droppos, + (byte) 1, delay)); } finally { mdrop.unlockItem(); } @@ -1166,7 +1179,7 @@ public class MapleMap { mdrop.lockItem(); try { - broadcastItemDropMessage(mdrop, dropper.getPosition(), droppos, (byte) 3, mdrop.getPosition()); + broadcastItemDropMessage(mdrop, dropper.getPosition(), droppos, (byte) 3, (short) 0, mdrop.getPosition()); } finally { mdrop.unlockItem(); } @@ -1178,7 +1191,7 @@ public class MapleMap { mdrop.lockItem(); try { - broadcastItemDropMessage(mdrop, dropper.getPosition(), droppos, (byte) 3, mdrop.getPosition()); + broadcastItemDropMessage(mdrop, dropper.getPosition(), droppos, (byte) 3, (short) 0, mdrop.getPosition()); } finally { mdrop.unlockItem(); } @@ -1326,7 +1339,13 @@ public class MapleMap { return count; } - public boolean damageMonster(final Character chr, final Monster monster, final int damage) { + /* TODO: start using once all erroneous damageMonster() callers have been fixed + public boolean damageMonster(final Character chr, final Monster monster, final int damage) { + damageMonster(chr, monster, damage, (short) 0); + } + */ + + public boolean damageMonster(final Character chr, final Monster monster, final int damage, short delay) { if (monster.getId() == MobId.ZAKUM_1) { for (MapObject object : chr.getMap().getMapObjects()) { Monster mons = chr.getMap().getMonsterByOid(object.getObjectId()); @@ -1351,7 +1370,7 @@ public class MapleMap { } } if (killed) { - killMonster(monster, chr, true); + killMonster(monster, chr, true, delay); } return true; } @@ -1392,11 +1411,12 @@ public class MapleMap { } } - public void killMonster(final Monster monster, final Character chr, final boolean withDrops) { - killMonster(monster, chr, withDrops, 1); + public void killMonster(final Monster monster, final Character chr, final boolean withDrops, short dropDelay) { + killMonster(monster, chr, withDrops, 1, dropDelay); } - public void killMonster(final Monster monster, final Character chr, final boolean withDrops, int animation) { + public void killMonster(final Monster monster, final Character chr, final boolean withDrops, int animation, + short dropDelay) { if (monster == null) { return; } @@ -1476,7 +1496,7 @@ public class MapleMap { if (dropOwner == null) { dropOwner = chr; } - dropFromMonster(dropOwner, monster, false); + dropFromMonster(dropOwner, monster, false, dropDelay); } if (monster.hasBossHPBar()) { @@ -1497,7 +1517,7 @@ public class MapleMap { } public void killFriendlies(Monster mob) { - this.killMonster(mob, (Character) getPlayers().get(0), false); + this.killMonster(mob, (Character) getPlayers().get(0), false, (short) 0); } public void killMonster(int mobId) { @@ -1506,7 +1526,7 @@ public class MapleMap { for (Monster mob : mobList) { if (mob.getId() == mobId) { - this.killMonster(mob, chr, false); + this.killMonster(mob, chr, false, (short) 0); } } } @@ -1525,7 +1545,7 @@ public class MapleMap { chr = defaultChr; } - this.killMonster(mob, chr, true); + this.killMonster(mob, chr, true, (short) 0); } } } @@ -1555,7 +1575,7 @@ public class MapleMap { continue; } - killMonster(monster, null, false, 1); + killMonster(monster, null, false, 1, (short) 0); } } @@ -1565,7 +1585,7 @@ public class MapleMap { for (MapObject monstermo : getMapObjectsInRange(new Point(0, 0), Double.POSITIVE_INFINITY, Arrays.asList(MapObjectType.MONSTER))) { Monster monster = (Monster) monstermo; - killMonster(monster, null, false, 1); + killMonster(monster, null, false, 1, (short) 0); } } @@ -1912,7 +1932,7 @@ public class MapleMap { Runnable removeAfterAction; if (selfDestruction == null) { - removeAfterAction = () -> killMonster(monster, null, false); + removeAfterAction = () -> killMonster(monster, null, false, (short) 0); registerMapSchedule(removeAfterAction, SECONDS.toMillis(monster.getStats().removeAfter())); } else { @@ -2160,11 +2180,13 @@ public class MapleMap { getWorldServer().registerTimedMapObject(expireKite, YamlConfig.config.server.KITE_EXPIRE_TIME); } - public final void spawnItemDrop(final MapObject dropper, final Character owner, final Item item, Point pos, final boolean ffaDrop, final boolean playerDrop) { + public final void spawnItemDrop(final MapObject dropper, final Character owner, final Item item, Point pos, + final boolean ffaDrop, final boolean playerDrop) { spawnItemDrop(dropper, owner, item, pos, (byte) (ffaDrop ? 2 : 0), playerDrop); } - public final void spawnItemDrop(final MapObject dropper, final Character owner, final Item item, Point pos, final byte dropType, final boolean playerDrop) { + public final void spawnItemDrop(final MapObject dropper, final Character owner, final Item item, Point pos, + final byte dropType, final boolean playerDrop) { if (FieldLimit.DROP_LIMIT.check(this.getFieldLimit())) { // thanks Conrad for noticing some maps shouldn't have loots available this.disappearingItemDrop(dropper, owner, item, pos); return; @@ -2177,7 +2199,8 @@ public class MapleMap { spawnAndAddRangedMapObject(mdrop, c -> { mdrop.lockItem(); try { - c.sendPacket(PacketCreator.dropItemFromMapObject(c.getPlayer(), mdrop, dropper.getPosition(), droppos, (byte) 1)); + c.sendPacket(PacketCreator.dropItemFromMapObject(c.getPlayer(), mdrop, dropper.getPosition(), droppos, + (byte) 1, (short) 0)); } finally { mdrop.unlockItem(); } @@ -2185,7 +2208,7 @@ public class MapleMap { mdrop.lockItem(); try { - broadcastItemDropMessage(mdrop, dropper.getPosition(), droppos, (byte) 0); + broadcastItemDropMessage(mdrop, dropper.getPosition(), droppos, (byte) 0, (short) 0); } finally { mdrop.unlockItem(); } @@ -2194,49 +2217,6 @@ public class MapleMap { activateItemReactors(mdrop, owner.getClient()); } - public final void spawnItemDropList(List list, final MapObject dropper, final Character owner, Point pos) { - spawnItemDropList(list, 1, 1, dropper, owner, pos, true, false); - } - - public final void spawnItemDropList(List list, int minCopies, int maxCopies, final MapObject dropper, final Character owner, Point pos) { - spawnItemDropList(list, minCopies, maxCopies, dropper, owner, pos, true, false); - } - - // spawns item instances of all defined item ids on a list - public final void spawnItemDropList(List list, int minCopies, int maxCopies, final MapObject dropper, final Character owner, Point pos, final boolean ffaDrop, final boolean playerDrop) { - int copies = (maxCopies - minCopies) + 1; - if (copies < 1) { - return; - } - - Collections.shuffle(list); - - ItemInformationProvider ii = ItemInformationProvider.getInstance(); - Random rnd = new Random(); - - final Point dropPos = new Point(pos); - dropPos.x -= (12 * list.size()); - - for (Integer integer : list) { - if (integer == 0) { - spawnMesoDrop(owner != null ? 10 * owner.getMesoRate() : 10, calcDropPos(dropPos, pos), dropper, owner, playerDrop, (byte) (ffaDrop ? 2 : 0)); - } else { - final Item drop; - int randomedId = integer; - - if (ItemConstants.getInventoryType(randomedId) != InventoryType.EQUIP) { - drop = new Item(randomedId, (short) 0, (short) (rnd.nextInt(copies) + minCopies)); - } else { - drop = ii.randomizeStats((Equip) ii.getEquipById(randomedId)); - } - - spawnItemDrop(dropper, owner, drop, calcDropPos(dropPos, pos), ffaDrop, playerDrop); - } - - dropPos.x += 25; - } - } - private void registerMapSchedule(Runnable r, long delay) { OverallService service = (OverallService) this.getChannelServer().getServiceAccess(ChannelServices.OVERALL); service.registerOverallAction(mapid, r, delay); @@ -2867,20 +2847,23 @@ public class MapleMap { } } - private void broadcastItemDropMessage(MapItem mdrop, Point dropperPos, Point dropPos, byte mod, Point rangedFrom) { - broadcastItemDropMessage(mdrop, dropperPos, dropPos, mod, getRangedDistance(), rangedFrom); + private void broadcastItemDropMessage(MapItem mdrop, Point dropperPos, Point dropPos, byte mod, short delay, + Point rangedFrom) { + broadcastItemDropMessage(mdrop, dropperPos, dropPos, mod, delay, getRangedDistance(), rangedFrom); } - private void broadcastItemDropMessage(MapItem mdrop, Point dropperPos, Point dropPos, byte mod) { - broadcastItemDropMessage(mdrop, dropperPos, dropPos, mod, Double.POSITIVE_INFINITY, null); + private void broadcastItemDropMessage(MapItem mdrop, Point dropperPos, Point dropPos, byte mod, short delay) { + broadcastItemDropMessage(mdrop, dropperPos, dropPos, mod, delay, Double.POSITIVE_INFINITY, null); } - private void broadcastItemDropMessage(MapItem mdrop, Point dropperPos, Point dropPos, byte mod, double rangeSq, Point rangedFrom) { + private void broadcastItemDropMessage(MapItem mdrop, Point dropperPos, Point dropPos, byte mod, short delay, + double rangeSq, Point rangedFrom) { chrRLock.lock(); try { for (Character chr : characters) { - Packet packet = PacketCreator.dropItemFromMapObject(chr, mdrop, dropperPos, dropPos, mod); + Packet packet = PacketCreator.dropItemFromMapObject(chr, mdrop, dropperPos, dropPos, mod, delay); + // TODO: remove along with USE_MAXRANGE config if (rangeSq < Double.POSITIVE_INFINITY) { if (rangedFrom.distanceSq(chr.getPosition()) <= rangeSq) { chr.sendPacket(packet); @@ -3405,12 +3388,14 @@ public class MapleMap { return false; } + // TODO: no reason to implement runnable - this is not intended to be submitted to another thread private class MobLootEntry implements Runnable { private final byte droptype; private final int mobpos; private final int chRate; private final Point pos; + private final short delay; private final List dropEntry; private final List visibleQuestEntry; private final List otherQuestEntry; @@ -3418,11 +3403,15 @@ public class MapleMap { private final Character chr; private final Monster mob; - protected MobLootEntry(byte droptype, int mobpos, int chRate, Point pos, List dropEntry, List visibleQuestEntry, List otherQuestEntry, List globalEntry, Character chr, Monster mob) { + protected MobLootEntry(byte droptype, int mobpos, int chRate, Point pos, short delay, + List dropEntry, List visibleQuestEntry, + List otherQuestEntry, List globalEntry, + Character chr, Monster mob) { this.droptype = droptype; this.mobpos = mobpos; this.chRate = chRate; this.pos = pos; + this.delay = delay; this.dropEntry = dropEntry; this.visibleQuestEntry = visibleQuestEntry; this.otherQuestEntry = otherQuestEntry; @@ -3436,14 +3425,14 @@ public class MapleMap { byte d = 1; // Normal Drops - d = dropItemsFromMonsterOnMap(dropEntry, pos, d, chRate, droptype, mobpos, chr, mob); + d = dropItemsFromMonsterOnMap(dropEntry, pos, d, chRate, droptype, mobpos, chr, mob, delay); // Global Drops - d = dropGlobalItemsFromMonsterOnMap(globalEntry, pos, d, droptype, mobpos, chr, mob); + d = dropGlobalItemsFromMonsterOnMap(globalEntry, pos, d, droptype, mobpos, chr, mob, delay); // Quest Drops - d = dropItemsFromMonsterOnMap(visibleQuestEntry, pos, d, chRate, droptype, mobpos, chr, mob); - dropItemsFromMonsterOnMap(otherQuestEntry, pos, d, chRate, droptype, mobpos, chr, mob); + d = dropItemsFromMonsterOnMap(visibleQuestEntry, pos, d, chRate, droptype, mobpos, chr, mob, delay); + dropItemsFromMonsterOnMap(otherQuestEntry, pos, d, chRate, droptype, mobpos, chr, mob, delay); } } diff --git a/src/main/java/tools/PacketCreator.java b/src/main/java/tools/PacketCreator.java index 3ee9d8fdff..3b328fe1b0 100644 --- a/src/main/java/tools/PacketCreator.java +++ b/src/main/java/tools/PacketCreator.java @@ -1816,7 +1816,8 @@ public class PacketCreator { return p; } - public static Packet dropItemFromMapObject(Character player, MapItem drop, Point dropfrom, Point dropto, byte mod) { + public static Packet dropItemFromMapObject(Character player, MapItem drop, Point dropfrom, Point dropto, byte mod, + short delay) { int dropType = drop.getDropType(); if (drop.hasClientsideOwnership(player) && dropType < 3) { dropType = 2; @@ -1834,7 +1835,7 @@ public class PacketCreator { if (mod != 2) { p.writePos(dropfrom); - p.writeShort(0);//Fh? + p.writeShort(delay); } if (drop.getMeso() == 0) { addExpirationTime(p, drop.getItem().getExpiration());