@Override
 public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
   c.getPlayer().resetAfkTime();
   AttackInfo attack = parseDamage(slea, false);
   MapleCharacter player = c.getPlayer();
   MaplePacket packet =
       MaplePacketCreator.magicAttack(
           player.getId(),
           attack.skill,
           attack.stance,
           attack.numAttackedAndDamage,
           attack.allDamage,
           -1,
           attack.speed);
   if (attack.skill == 2121001 || attack.skill == 2221001 || attack.skill == 2321001) {
     packet =
         MaplePacketCreator.magicAttack(
             player.getId(),
             attack.skill,
             attack.stance,
             attack.numAttackedAndDamage,
             attack.allDamage,
             attack.charge,
             attack.speed);
   }
   player.getMap().broadcastMessage(player, packet, false, true);
   MapleStatEffect effect = attack.getAttackEffect(c.getPlayer());
   int maxdamage;
   // TODO fix magic damage calculation
   maxdamage = 99999;
   ISkill skill = SkillFactory.getSkill(attack.skill);
   int skillLevel = c.getPlayer().getSkillLevel(skill);
   MapleStatEffect effect_ = skill.getEffect(skillLevel);
   if (effect_.getCooldown() > 0) {
     if (player.skillisCooling(attack.skill)) {
       // player.getCheatTracker().registerOffense(CheatingOffense.COOLDOWN_HACK);
       return;
     } else {
       c.getSession().write(MaplePacketCreator.skillCooldown(attack.skill, effect_.getCooldown()));
       ScheduledFuture<?> timer =
           TimerManager.getInstance()
               .schedule(
                   new CancelCooldownAction(c.getPlayer(), attack.skill),
                   effect_.getCooldown() * 1000);
       player.addCooldown(
           attack.skill, System.currentTimeMillis(), effect_.getCooldown() * 1000, timer);
     }
   }
   applyAttack(attack, player, maxdamage, effect.getAttackCount());
   // MP Eater
   for (int i = 1; i <= 3; i++) {
     ISkill eaterSkill = SkillFactory.getSkill(2000000 + i * 100000);
     int eaterLevel = player.getSkillLevel(eaterSkill);
     if (eaterLevel > 0) {
       for (Pair<Integer, List<Integer>> singleDamage : attack.allDamage) {
         eaterSkill
             .getEffect(eaterLevel)
             .applyPassive(player, player.getMap().getMapObject(singleDamage.getLeft()), 0);
       }
       break;
     }
   }
 }
  @Override
  public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
    // damage from map object
    // 26 00 EB F2 2B 01 FE 25 00 00 00 00 00
    // damage from monster
    // 26 00 0F 60 4C 00 FF 48 01 00 00 B5 89 5D 00 CC CC CC CC 00 00 00 00

    /* Damagefrom:  -2 = map attack
     *		-1 = walk over monster
     *		0 = spell
     *		1 = seems to be a spell too...
     *
     * Damage: -1 = none taken?
     *	   > 0 = normal damage
     */

    MapleCharacter player = c.getPlayer();

    slea.readInt();
    int damagefrom = slea.readByte();
    slea.readByte();
    int damage = slea.readInt();
    int oid = 0;
    int monsteridfrom = 0;
    int pgmr = 0;
    int direction = 0;
    int pos_x = 0;
    int pos_y = 0;
    int fake = 0;
    boolean is_pgmr = false;
    boolean is_pg = true;
    int mpattack = 0;

    MapleMonster attacker = null;
    if (damagefrom == -2) {
      int debuffLevel = slea.readByte();
      int debuffId = slea.readByte();
      if (debuffId == 125) {
        debuffLevel = debuffLevel - 1;
      }
      MobSkill skill = MobSkillFactory.getMobSkill(debuffId, debuffLevel);
      if (skill != null) {
        skill.applyEffect(player, attacker, false);
      }
    } else {
      monsteridfrom = slea.readInt();
      oid = slea.readInt();
      if (monsteridfrom != 0 && damage != -1) {
        attacker = (MapleMonster) player.getMap().getMapObject(monsteridfrom);
      } else {
        attacker = (MapleMonster) player.getMap().getMapObject(oid);
      }
      direction = slea.readByte();
    }

    if (damagefrom != -1 && damagefrom != -2 && attacker != null) {
      MobAttackInfo attackInfo = MobAttackInfoFactory.getMobAttackInfo(attacker, damagefrom);
      if (damage != -1) {
        if (attackInfo.isDeadlyAttack()) {
          mpattack = player.getMp() - 1;
        } else {
          mpattack += attackInfo.getMpBurn();
        }
        if (mpattack - player.getMp() < 0) {
          mpattack = player.getMp();
        }
      }
      MobSkill skill =
          MobSkillFactory.getMobSkill(attackInfo.getDiseaseSkill(), attackInfo.getDiseaseLevel());
      if (skill != null && damage > 0) {
        skill.applyEffect(player, attacker, false);
      }
      if (attacker != null) {
        attacker.setMp(attacker.getMp() - attackInfo.getMpCon());
      }
    }
    try {
      for (MapleMapObject mmo : player.getMap().getMapObjects()) {
        if (mmo instanceof MapleMist) {
          MapleMist mist = (MapleMist) mmo;
          if (mist.getSourceSkill().getId() == 4221006) { // Smokescreen
            for (MapleMapObject mmoplayer :
                player
                    .getMap()
                    .getMapObjectsInRect(
                        mist.getBox(), Collections.singletonList(MapleMapObjectType.PLAYER))) {
              if (player == (MapleCharacter) mmoplayer) {
                damage = -1;
              }
            }
          }
        }
      }
    } catch (Exception e) {
      log.warn("Unable to handle smokescreen...", e);
    }

    if (damage == -1) {
      int job = (int) (player.getJob().getId() / 10 - 40);
      fake = 4020002 + (job * 100000);
      if (damagefrom == -1
          && damagefrom != -2
          && player.getInventory(MapleInventoryType.EQUIPPED).getItem((byte) -10) != null) {
        int[] guardianSkillId = {1120005, 1220006};
        for (int guardian : guardianSkillId) {
          ISkill guardianSkill = SkillFactory.getSkill(guardian);
          if (player.getSkillLevel(guardianSkill) > 0 && attacker != null) {
            MonsterStatusEffect monsterStatusEffect =
                new MonsterStatusEffect(
                    Collections.singletonMap(MonsterStatus.STUN, 1), guardianSkill, false);
            attacker.applyStatus(player, monsterStatusEffect, false, 2 * 1000);
          }
        }
      }
    }

    if (damage < -1 || damage > 100000) {
      AutobanManager.getInstance()
          .autoban(player.getClient(), player.getName() + " took " + damage + " of damage.");
    } else if (damage > 60000) {
      log.warn(player.getName() + " receive " + damage + " of abnormal amount of damage.");
      c.disconnect();
      return;
    }

    player.getCheatTracker().checkTakeDamage();

    if (damage > 0) {
      player.getCheatTracker().setAttacksWithoutHit(0);
      player.getCheatTracker().resetHPRegen();

      if (!player.isHidden() && player.isAlive()) {
        if (MapleLifeFactory.getMonster(monsteridfrom) != null) {
          if (player.getBuffedValue(MapleBuffStat.MORPH) != null) {
            player.cancelMorphs();
          }
          if (attacker != null && !attacker.isBoss()) {
            if (damagefrom == -1 && player.getBuffedValue(MapleBuffStat.POWERGUARD) != null) {
              int bouncedamage =
                  (int)
                      (damage
                          * (player.getBuffedValue(MapleBuffStat.POWERGUARD).doubleValue() / 100));
              bouncedamage = Math.min(bouncedamage, attacker.getMaxHp() / 10);
              player.getMap().damageMonster(player, attacker, bouncedamage);
              damage -= bouncedamage;
              player
                  .getMap()
                  .broadcastMessage(
                      player, MaplePacketCreator.damageMonster(oid, bouncedamage), false, true);
              player.checkMonsterAggro(attacker);
            }
            if ((damagefrom == 0 || damagefrom == 1)
                && player.getBuffedValue(MapleBuffStat.MANA_REFLECTION) != null) {
              int[] manaReflectSkillId = {2121002, 2221002, 2321002};
              for (int manaReflect : manaReflectSkillId) {
                ISkill manaReflectSkill = SkillFactory.getSkill(manaReflect);
                if (player.isBuffFrom(MapleBuffStat.MANA_REFLECTION, manaReflectSkill)
                    && player.getSkillLevel(manaReflectSkill) > 0
                    && manaReflectSkill
                        .getEffect(player.getSkillLevel(manaReflectSkill))
                        .makeChanceResult()) {
                  int bouncedamage =
                      (int)
                          (damage
                              * (manaReflectSkill
                                      .getEffect(player.getSkillLevel(manaReflectSkill))
                                      .getX()
                                  / 100));
                  if (bouncedamage > attacker.getMaxHp() * .2) {
                    bouncedamage = (int) (attacker.getMaxHp() * .2);
                  }
                  player.getMap().damageMonster(player, attacker, bouncedamage);
                  player
                      .getMap()
                      .broadcastMessage(
                          player, MaplePacketCreator.damageMonster(oid, bouncedamage), true);
                  player
                      .getClient()
                      .getSession()
                      .write(MaplePacketCreator.showOwnBuffEffect(manaReflect, 5));
                  player
                      .getMap()
                      .broadcastMessage(
                          player,
                          MaplePacketCreator.showBuffeffect(
                              player.getId(), manaReflect, 5, (byte) 3),
                          false);
                  break;
                }
              }
            }
          }
          if (damagefrom == -1) {
            try {
              int[] achillesSkillId = {1120004, 1220005, 1320005};
              for (int achilles : achillesSkillId) {
                ISkill achillesSkill = SkillFactory.getSkill(achilles);
                if (player.getSkillLevel(achillesSkill) > 0) {
                  double multiplier =
                      achillesSkill.getEffect(player.getSkillLevel(achillesSkill)).getX() / 1000.0;
                  int newdamage = (int) (multiplier * damage);
                  damage = newdamage;
                  break;
                }
              }
            } catch (Exception e) {
              log.warn("Failed to handle achilles..", e);
            }
          }
          if (player.getBuffedValue(MapleBuffStat.MAGIC_GUARD) != null && mpattack == 0) {
            int mploss =
                (int)
                    (damage
                        * (player.getBuffedValue(MapleBuffStat.MAGIC_GUARD).doubleValue() / 100.0));
            int hploss = damage - mploss;
            if (mploss > player.getMp()) {
              hploss += mploss - player.getMp();
              mploss = player.getMp();
            }
            player.addMPHP(-hploss, -mploss);
          } else if (player.getBuffedValue(MapleBuffStat.MESOGUARD) != null) {
            damage = (damage % 2 == 0) ? damage / 2 : (damage / 2) + 1;
            int mesoloss =
                (int)
                    (damage
                        * (player.getBuffedValue(MapleBuffStat.MESOGUARD).doubleValue() / 100.0));
            if (player.getMeso() < mesoloss) {
              player.gainMeso(-player.getMeso(), false);
              player.cancelBuffStats(MapleBuffStat.MESOGUARD);
            } else {
              player.gainMeso(-mesoloss, false);
            }
            player.addMPHP(-damage, -mpattack);
          } else {
            player.addMPHP(-damage, -mpattack);
          }
          if (c.getPlayer().getMap().getId() == 980010101) {
            if (monsteridfrom == 9300166) {
              player.setBombPoints(player.getBombPoints() - 1);
              if (player.getBombPoints() < 1) {
                player.setHp(0);
                player.updateSingleStat(MapleStat.HP, 0);
                player.setBombPoints(10);
                c.getPlayer()
                    .dropMessage(
                        "["
                            + c.getChannelServer().getServerName()
                            + "] You have died in Battle at the Bomberman Arena.");
                c.getPlayer()
                    .getMap()
                    .broadcastMessage(
                        MaplePacketCreator.serverNotice(
                            1,
                            "["
                                + c.getChannelServer().getServerName()
                                + "] The person "
                                + player.getName()
                                + " has died in Bomberman PvP."));
                return;
              } else {
                c.getPlayer()
                    .getMap()
                    .broadcastMessage(
                        MaplePacketCreator.serverNotice(
                            1,
                            "["
                                + c.getChannelServer().getServerName()
                                + "] The player "
                                + player.getName()
                                + " now has "
                                + player.getBombPoints()
                                + " points left in Bomberman PvP."));
                return;
              }
            }
          } else {
            player
                .getMap()
                .broadcastMessage(
                    player,
                    MaplePacketCreator.damagePlayer(
                        damagefrom,
                        monsteridfrom,
                        player.getId(),
                        damage,
                        fake,
                        direction,
                        is_pgmr,
                        pgmr,
                        is_pg,
                        oid,
                        pos_x,
                        pos_y),
                    false);
          }
        } else {
          player.dropMessage(
              1, "You have been suspected of Packet Editing. A GM will be notified.");
        }
      }
    }
  }
Esempio n. 3
0
  @Override
  public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
    // System.out.println("SummonDamage 封包: "+slea.toString());

    int oid = slea.readInt();
    slea.skip(5);
    MapleCharacter player = c.getPlayer();
    if (!player.isAlive()) {
      return;
    }
    MapleSummon summon = null;
    boolean is磁场 = false;
    boolean is磁场攻击 = false;
    // System.out.println("接收到的召唤兽的oid"+oid);
    /*
     * for (List<MapleSummon> sums : c.getPlayer().getSummons().values()) {
     * for (MapleSummon sum : sums) {
     * //System.out.println("召唤兽的oid"+sum.getObjectId()); if
     * (sum.getObjectId() == oid) { summon = sum; break; } } }
     */
    Object obj = c.getPlayer().getMap().getMapObject(oid);
    if (obj instanceof MapleSummon) {
      summon = (MapleSummon) obj;
    }
    if (summon == null) {
      // System.out.println("召唤兽伤害被拦截");
      return;
    }
    int skillid;
    int skilllevel;
    Point pos;
    skillid = summon.getSkill();
    skilllevel = summon.getSkillLevel();
    pos = summon.getPosition();
    ISkill summonSkill = SkillFactory.getSkill(skillid);
    MapleStatEffect summonEffect = summonSkill.getEffect(skilllevel);
    List<SummonAttackEntry> allDamage = new ArrayList<SummonAttackEntry>();
    int numAttacked = changeNumAttacked(slea.readByte(), skillid); // 这里还读了一个byte
    int numAccackMonster = numAttacked >> 4;
    int numAccackMonsterCount = numAttacked & 0xf;
    // System.out.println("攻击怪的个数: " + numAttacked);
    player.getCheatTracker().checkSummonAttack();
    int oid1 = slea.readInt(); // 第一个磁场的oid
    if (skillid == 机械师.磁场) {
      // is磁场 = true;
      for (List<MapleSummon> sums : c.getPlayer().getSummons().values()) {
        for (MapleSummon sum : sums) {
          if (sum.getObjectId() == oid1) {
            is磁场攻击 = true;
            oid = oid1;
            break;
          }
        }
      }
      if (is磁场攻击) {
        slea.skip(4); // 第二个磁场的oid
        slea.skip(4); // 第三个磁场的oid
        slea.skip(4); // 没用的
      }
    }
    slea.skip(4);
    slea.skip(4); // 00
    for (int x = 0; x < numAccackMonster; x++) {
      int monsterOid = slea.readInt(); // attacked oid
      slea.skip(4); // mobid 对应的怪物在WZ里的id
      slea.skip(19);
      int damage = slea.readInt();

      for (int i = 0; i < numAccackMonsterCount; i++) {} // 以后召唤兽可能会多重攻击

      slea.skip(8);
      // System.out.println("mobid: " + monsterOid);
      // System.out.println("打怪伤害: " + damage);
      allDamage.add(new SummonAttackEntry(monsterOid, damage));
    }
    if (!player.isAlive()) {
      player.getCheatTracker().registerOffense(CheatingOffense.ATTACKING_WHILE_DEAD);
      return;
    }
    player
        .getMap()
        .broadcastMessage(
            player, MaplePacketCreator.summonAttack(player, oid, 4, allDamage, numAttacked), pos);
    for (SummonAttackEntry attackEntry : allDamage) {
      int damage = attackEntry.getDamage();
      // System.out.println("遍历回来的伤害:"+damage);
      MapleMonster target = player.getMap().getMonsterByOid(attackEntry.getMonsterOid());
      if (target != null) {
        if (damage > 0 && summonEffect.getMonsterStati().size() > 0) {
          if (summonEffect.makeChanceResult()) {
            MonsterStatusEffect monsterStatusEffect =
                new MonsterStatusEffect(summonEffect.getMonsterStati(), summonSkill, false);
            target.applyStatus(player, monsterStatusEffect, summonEffect.isPoison(), 4000);
          }
        }
        if (damage > 30000) {
          damage = 30000;
        }
        player.getMap().damageMonster(player, target, damage);
        player.checkMonsterAggro(target);
        // System.out.println("target == null");
      }
    }
    if (是自爆召唤兽(skillid) || is磁场 && !is磁场攻击) {
      // System.out.println("机械召唤兽的removeSpecialMapObject特殊处理");
      player.getMap().broadcastMessage(MaplePacketCreator.removeSpecialMapObject(summon, true));
      player.getMap().removeMapObject(summon);
      player.removeVisibleMapObject(summon);
      // player.getSummons().remove(skillid);
      player.removeSummon(skillid);
    }
  }