Search in sources :

Example 1 with MobAttackInfo

use of server.life.MobAttackInfo in project HeavenMS by ronancpl.

the class MoveLifeHandler method handlePacket.

@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
    int objectid = slea.readInt();
    short moveid = slea.readShort();
    MapleMapObject mmo = c.getPlayer().getMap().getMapObject(objectid);
    if (mmo == null || mmo.getType() != MapleMapObjectType.MONSTER) {
        return;
    }
    MapleMonster monster = (MapleMonster) mmo;
    List<LifeMovementFragment> res = null;
    List<MapleCharacter> banishPlayers = new ArrayList<>();
    byte pNibbles = slea.readByte();
    byte rawActivity = slea.readByte();
    byte useSkillId = slea.readByte();
    byte useSkillLevel = slea.readByte();
    short pOption = slea.readShort();
    slea.skip(8);
    if (rawActivity >= 0) {
        rawActivity = (byte) (rawActivity & 0xFF >> 1);
    }
    boolean isAttack = inRangeInclusive(rawActivity, 12, 20);
    boolean isSkill = inRangeInclusive(rawActivity, 21, 25);
    byte attackId = (byte) (isAttack ? rawActivity - 12 : -1);
    boolean nextMovementCouldBeSkill = (pNibbles & 0x0F) != 0;
    boolean pUnk = (pNibbles & 0xF0) != 0;
    int nextCastSkill = useSkillId;
    int nextCastSkillLevel = useSkillLevel;
    MobSkill toUse = null;
    int percHpLeft = (int) (((float) monster.getHp() / monster.getMaxHp()) * 100);
    if (nextMovementCouldBeSkill && monster.getNoSkills() > 0) {
        int Random = Randomizer.nextInt(monster.getNoSkills());
        Pair<Integer, Integer> skillToUse = monster.getSkills().get(Random);
        nextCastSkill = skillToUse.getLeft();
        nextCastSkillLevel = skillToUse.getRight();
        toUse = MobSkillFactory.getMobSkill(nextCastSkill, nextCastSkillLevel);
        if (isSkill || isAttack) {
            if (nextCastSkill != toUse.getSkillId() || nextCastSkillLevel != toUse.getSkillLevel()) {
                // toUse.resetAnticipatedSkill();
                return;
            } else if (toUse.getHP() < percHpLeft) {
                toUse = null;
            } else if (monster.canUseSkill(toUse)) {
                toUse.applyEffect(c.getPlayer(), monster, true, banishPlayers);
            // System.out.println("Applied: " + nextCastSkill + " Level: " + nextCastSkillLevel);
            }
        } else {
            MobAttackInfo mobAttack = MobAttackInfoFactory.getMobAttackInfo(monster, attackId);
        // System.out.println("Attacked");
        }
    }
    slea.readByte();
    // whatever
    slea.readInt();
    // hmm.. startpos?
    short start_x = slea.readShort();
    // hmm...
    short start_y = slea.readShort();
    Point startPos = new Point(start_x, start_y);
    res = parseMovement(slea);
    if (monster.getController() != c.getPlayer()) {
        if (monster.isAttackedBy(c.getPlayer())) {
            monster.switchController(c.getPlayer(), true);
        } else {
            return;
        }
    } else if (rawActivity == -1 && monster.isControllerKnowsAboutAggro() && !monster.isMobile() && !monster.isFirstAttack()) {
        monster.setControllerHasAggro(false);
        monster.setControllerKnowsAboutAggro(false);
    }
    boolean aggro = monster.isControllerHasAggro();
    if (toUse != null) {
        c.announce(MaplePacketCreator.moveMonsterResponse(objectid, moveid, monster.getMp(), aggro, toUse.getSkillId(), toUse.getSkillLevel()));
    } else {
        c.announce(MaplePacketCreator.moveMonsterResponse(objectid, moveid, monster.getMp(), aggro));
    }
    if (aggro) {
        monster.setControllerKnowsAboutAggro(true);
    }
    if (res != null) {
        c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.moveMonster(objectid, nextMovementCouldBeSkill, rawActivity, useSkillId, useSkillLevel, pOption, startPos, res), monster.getPosition());
        updatePosition(res, monster, -1);
        c.getPlayer().getMap().moveMonster(monster, monster.getPosition());
    }
    for (MapleCharacter chr : banishPlayers) {
        chr.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
    }
}
Also used : MapleCharacter(client.MapleCharacter) ArrayList(java.util.ArrayList) MapleMapObject(server.maps.MapleMapObject) MobAttackInfo(server.life.MobAttackInfo) Point(java.awt.Point) Point(java.awt.Point) LifeMovementFragment(server.movement.LifeMovementFragment) MobSkill(server.life.MobSkill) MapleMonster(server.life.MapleMonster)

Example 2 with MobAttackInfo

use of server.life.MobAttackInfo in project HeavenMS by ronancpl.

the class TakeDamageHandler method handlePacket.

@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
    List<MapleCharacter> banishPlayers = new ArrayList<>();
    MapleCharacter chr = c.getPlayer();
    slea.readInt();
    byte damagefrom = slea.readByte();
    // Element
    slea.readByte();
    int damage = slea.readInt();
    int oid = 0, monsteridfrom = 0, pgmr = 0, direction = 0;
    int pos_x = 0, pos_y = 0, fake = 0;
    boolean is_pgmr = false, is_pg = true, is_deadly = false;
    int mpattack = 0;
    MapleMonster attacker = null;
    final MapleMap map = chr.getMap();
    if (damagefrom != -3 && damagefrom != -4) {
        monsteridfrom = slea.readInt();
        oid = slea.readInt();
        try {
            MapleMapObject mmo = map.getMapObject(oid);
            if (mmo instanceof MapleMonster) {
                attacker = (MapleMonster) mmo;
                if (attacker.getId() != monsteridfrom) {
                    attacker = null;
                }
            }
            if (attacker != null) {
                List<loseItem> loseItems;
                if (attacker.isBuffed(MonsterStatus.NEUTRALISE)) {
                    return;
                }
                if (damage > 0) {
                    MapleMonster assaulter = map.getMonsterById(monsteridfrom);
                    if (assaulter != null) {
                        loseItems = assaulter.getStats().loseItem();
                        if (loseItems != null) {
                            MapleInventoryType type;
                            final int playerpos = chr.getPosition().x;
                            byte d = 1;
                            Point pos = new Point(0, chr.getPosition().y);
                            for (loseItem loseItem : loseItems) {
                                type = ItemConstants.getInventoryType(loseItem.getId());
                                for (byte b = 0; b < loseItem.getX(); b++) {
                                    // LOL?
                                    if (Randomizer.nextInt(101) >= loseItem.getChance()) {
                                        if (chr.haveItem(loseItem.getId())) {
                                            pos.x = (int) (playerpos + ((d % 2 == 0) ? (25 * (d + 1) / 2) : -(25 * (d / 2))));
                                            MapleInventoryManipulator.removeById(c, type, loseItem.getId(), 1, false, false);
                                            map.spawnItemDrop(chr, chr, new Item(loseItem.getId(), (short) 0, (short) 1), map.calcDropPos(pos, chr.getPosition()), true, true);
                                            d++;
                                        } else {
                                            break;
                                        }
                                    }
                                }
                            }
                            map.removeMapObject(attacker);
                        }
                    }
                }
            } else {
                return;
            }
        } catch (ClassCastException e) {
            // this happens due to mob on last map damaging player just before changing maps
            e.printStackTrace();
            FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, "Attacker is not a mob-type, rather is a " + map.getMapObject(oid).getClass().getName() + " entity.");
            return;
        }
        direction = slea.readByte();
    }
    if (damagefrom != -1 && damagefrom != -2 && attacker != null) {
        MobAttackInfo attackInfo = MobAttackInfoFactory.getMobAttackInfo(attacker, damagefrom);
        if (attackInfo != null) {
            if (attackInfo.isDeadlyAttack()) {
                mpattack = chr.getMp() - 1;
                is_deadly = true;
            }
            mpattack += attackInfo.getMpBurn();
            MobSkill mobSkill = MobSkillFactory.getMobSkill(attackInfo.getDiseaseSkill(), attackInfo.getDiseaseLevel());
            if (mobSkill != null && damage > 0) {
                mobSkill.applyEffect(chr, attacker, false, banishPlayers);
            }
            attacker.setMp(attacker.getMp() - attackInfo.getMpCon());
            if (chr.getBuffedValue(MapleBuffStat.MANA_REFLECTION) != null && damage > 0 && !attacker.isBoss()) {
                int jobid = chr.getJob().getId();
                if (jobid == 212 || jobid == 222 || jobid == 232) {
                    int id = jobid * 10000 + 1002;
                    Skill manaReflectSkill = SkillFactory.getSkill(id);
                    if (chr.isBuffFrom(MapleBuffStat.MANA_REFLECTION, manaReflectSkill) && chr.getSkillLevel(manaReflectSkill) > 0 && manaReflectSkill.getEffect(chr.getSkillLevel(manaReflectSkill)).makeChanceResult()) {
                        int bouncedamage = (damage * manaReflectSkill.getEffect(chr.getSkillLevel(manaReflectSkill)).getX() / 100);
                        if (bouncedamage > attacker.getMaxHp() / 5) {
                            bouncedamage = attacker.getMaxHp() / 5;
                        }
                        map.damageMonster(chr, attacker, bouncedamage);
                        map.broadcastMessage(chr, MaplePacketCreator.damageMonster(oid, bouncedamage), true);
                        chr.getClient().announce(MaplePacketCreator.showOwnBuffEffect(id, 5));
                        map.broadcastMessage(chr, MaplePacketCreator.showBuffeffect(chr.getId(), id, 5), false);
                    }
                }
            }
        }
    }
    if (damage == -1) {
        fake = 4020002 + (chr.getJob().getId() / 10 - 40) * 100000;
    }
    // in dojo player cannot use pot, so deadly attacks should be turned off as well
    if (is_deadly && chr.getMap().isDojoMap() && !ServerConstants.USE_DEADLY_DOJO) {
        damage = 0;
        mpattack = 0;
    }
    if (damage == 0) {
        chr.getAutobanManager().addMiss();
    } else {
        chr.getAutobanManager().resetMisses();
    }
    if (damage > 0 && !chr.isHidden()) {
        if (attacker != null && damagefrom == -1 && chr.getBuffedValue(MapleBuffStat.POWERGUARD) != null) {
            // PG works on bosses, but only at half of the rate.
            int bouncedamage = (int) (damage * (chr.getBuffedValue(MapleBuffStat.POWERGUARD).doubleValue() / (attacker.isBoss() ? 200 : 100)));
            bouncedamage = Math.min(bouncedamage, attacker.getMaxHp() / 10);
            damage -= bouncedamage;
            map.damageMonster(chr, attacker, bouncedamage);
            map.broadcastMessage(chr, MaplePacketCreator.damageMonster(oid, bouncedamage), false, true);
            chr.checkMonsterAggro(attacker);
        }
        if (attacker != null && damagefrom == -1 && chr.getBuffedValue(MapleBuffStat.BODY_PRESSURE) != null) {
            Skill skill = SkillFactory.getSkill(Aran.BODY_PRESSURE);
            final MapleStatEffect eff = skill.getEffect(chr.getSkillLevel(skill));
            if (!attacker.alreadyBuffedStats().contains(MonsterStatus.NEUTRALISE)) {
                if (!attacker.isBoss() && eff.makeChanceResult()) {
                    attacker.applyStatus(chr, new MonsterStatusEffect(Collections.singletonMap(MonsterStatus.NEUTRALISE, 1), skill, null, false), false, (eff.getDuration() / 10) * 2, false);
                }
            }
        }
        if (damagefrom != -3 && damagefrom != -4) {
            int achilles = 0;
            Skill achilles1 = null;
            int jobid = chr.getJob().getId();
            if (jobid < 200 && jobid % 10 == 2) {
                achilles1 = SkillFactory.getSkill(jobid * 10000 + (jobid == 112 ? 4 : 5));
                achilles = chr.getSkillLevel(achilles1);
            }
            if (achilles != 0 && achilles1 != null) {
                damage *= (achilles1.getEffect(achilles).getX() / 1000.0);
            }
        }
        Integer mesoguard = chr.getBuffedValue(MapleBuffStat.MESOGUARD);
        if (chr.getBuffedValue(MapleBuffStat.MAGIC_GUARD) != null && mpattack == 0) {
            int mploss = (int) (damage * (chr.getBuffedValue(MapleBuffStat.MAGIC_GUARD).doubleValue() / 100.0));
            int hploss = damage - mploss;
            int curmp = chr.getMp();
            if (mploss > curmp) {
                hploss += mploss - curmp;
                mploss = curmp;
            }
            chr.addMPHP(-hploss, -mploss);
        } else if (mesoguard != null) {
            damage = Math.round(damage / 2);
            int mesoloss = (int) (damage * (mesoguard.doubleValue() / 100.0));
            if (chr.getMeso() < mesoloss) {
                chr.gainMeso(-chr.getMeso(), false);
                chr.cancelBuffStats(MapleBuffStat.MESOGUARD);
            } else {
                chr.gainMeso(-mesoloss, false);
            }
            chr.addMPHP(-damage, -mpattack);
        } else {
            if (chr.getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null) {
                if (chr.getBuffedValue(MapleBuffStat.MONSTER_RIDING).intValue() == Corsair.BATTLE_SHIP) {
                    chr.decreaseBattleshipHp(damage);
                }
            }
            chr.addMPHP(-damage, -mpattack);
        }
    }
    if (!chr.isHidden()) {
        map.broadcastMessage(chr, MaplePacketCreator.damagePlayer(damagefrom, monsteridfrom, chr.getId(), damage, fake, direction, is_pgmr, pgmr, is_pg, oid, pos_x, pos_y), false);
        chr.checkBerserk(true);
    } else {
        map.broadcastGMMessage(chr, MaplePacketCreator.damagePlayer(damagefrom, monsteridfrom, chr.getId(), damage, fake, direction, is_pgmr, pgmr, is_pg, oid, pos_x, pos_y), false);
        chr.checkBerserk(false);
    }
    if (GameConstants.isDojo(map.getId())) {
        chr.setDojoEnergy(chr.getDojoEnergy() + ServerConstants.DOJO_ENERGY_DMG);
        c.announce(MaplePacketCreator.getEnergy("energy", chr.getDojoEnergy()));
    }
    for (MapleCharacter player : banishPlayers) {
        // chill, if this list ever gets non-empty an attacker does exist, trust me :)
        player.changeMapBanish(attacker.getBanish().getMap(), attacker.getBanish().getPortal(), attacker.getBanish().getMsg());
    }
}
Also used : MapleCharacter(client.MapleCharacter) MonsterStatusEffect(client.status.MonsterStatusEffect) ArrayList(java.util.ArrayList) MapleMapObject(server.maps.MapleMapObject) MobAttackInfo(server.life.MobAttackInfo) MapleLifeFactory.loseItem(server.life.MapleLifeFactory.loseItem) Point(java.awt.Point) Point(java.awt.Point) MapleMap(server.maps.MapleMap) Item(client.inventory.Item) MapleLifeFactory.loseItem(server.life.MapleLifeFactory.loseItem) MapleInventoryType(client.inventory.MapleInventoryType) Skill(client.Skill) MobSkill(server.life.MobSkill) MapleStatEffect(server.MapleStatEffect) MobSkill(server.life.MobSkill) MapleMonster(server.life.MapleMonster)

Aggregations

MapleCharacter (client.MapleCharacter)2 Point (java.awt.Point)2 ArrayList (java.util.ArrayList)2 MapleMonster (server.life.MapleMonster)2 MobAttackInfo (server.life.MobAttackInfo)2 MobSkill (server.life.MobSkill)2 MapleMapObject (server.maps.MapleMapObject)2 Skill (client.Skill)1 Item (client.inventory.Item)1 MapleInventoryType (client.inventory.MapleInventoryType)1 MonsterStatusEffect (client.status.MonsterStatusEffect)1 MapleStatEffect (server.MapleStatEffect)1 MapleLifeFactory.loseItem (server.life.MapleLifeFactory.loseItem)1 MapleMap (server.maps.MapleMap)1 LifeMovementFragment (server.movement.LifeMovementFragment)1