private void spawnClone() {
   Npc KutolClone = getPosition().getWorldMapInstance().getNpc(282302);
   int random = Rnd.get(1, 3);
   if (KutolClone == null) {
     switch (random) {
       case 1:
         spawn(282302, getOwner().getX(), getOwner().getY(), getOwner().getZ() + 2, (byte) 3);
         break;
       case 2:
         spawn(282302, getOwner().getX(), getOwner().getY(), getOwner().getZ() + 2, (byte) 3);
         spawn(
             282302,
             getOwner().getX() - 5,
             getOwner().getY() - 3,
             getOwner().getZ() + 2,
             (byte) 3);
         break;
       default:
         spawn(282302, getOwner().getX(), getOwner().getY(), getOwner().getZ() + 2, (byte) 3);
         spawn(
             282302,
             getOwner().getX() - 5,
             getOwner().getY() - 3,
             getOwner().getZ() + 2,
             (byte) 3);
         spawn(
             282302,
             getOwner().getX() + 5,
             getOwner().getY() - 3,
             getOwner().getZ() + 2,
             (byte) 3);
         break;
     }
   }
 }
  /**
   * Calculates BLOCK chance
   *
   * @param attacker
   * @param attacked
   * @return int
   */
  public static boolean calculatePhysicalBlockRate(Creature attacker, Creature attacked) {
    // check always block
    if (attacked.getObserveController().checkAttackStatus(AttackStatus.BLOCK)) {
      return true;
    }

    float accuracy = attacker.getGameStats().getMainHandPAccuracy().getCurrent();
    float block = 0;
    if (attacked instanceof Player) {
      block =
          attacked.getGameStats().getBlock().getBonus()
              + getMovementModifier(
                  attacked, StatEnum.BLOCK, attacked.getGameStats().getBlock().getBase())
              + attacked.getGameStats().getStat(StatEnum.PVP_BLOCK, 0).getCurrent();
    } else {
      block =
          attacked.getGameStats().getBlock().getBonus()
              + getMovementModifier(
                  attacked, StatEnum.BLOCK, attacked.getGameStats().getBlock().getBase());
    }
    float blockRate = block - accuracy;
    // blockRate = blockRate*0.6f+50;
    if (blockRate > 500) {
      blockRate = 500;
    }
    return Rnd.nextInt(1000) < blockRate;
  }
  /**
   * Calculates MAGICAL CRITICAL chance
   *
   * @param attacker
   * @param attacke
   * @return boolean
   */
  public static boolean calculateMagicalCriticalRate(
      Creature attacker, Creature attacked, int criticalProb) {
    if (attacker instanceof Servant || attacker instanceof Homing) {
      return false;
    }

    int critical = attacker.getGameStats().getMCritical().getCurrent();
    if (attacked instanceof Player) {
      critical =
          attacked.getGameStats().getPositiveReverseStat(StatEnum.MAGICAL_CRITICAL_RESIST, critical)
              + attacked
                  .getGameStats()
                  .getPositiveReverseStat(StatEnum.PVP_MAGICAL_RESIST, critical);
    } else {
      critical =
          attacked
              .getGameStats()
              .getPositiveReverseStat(StatEnum.MAGICAL_CRITICAL_RESIST, critical);
    }

    // add critical Prob
    critical *= (float) criticalProb / 100f;

    double criticalRate;

    if (critical <= 440) {
      criticalRate = critical * 0.1f;
    } else if (critical <= 600) {
      criticalRate = (440 * 0.1f) + ((critical - 440) * 0.05f);
    } else {
      criticalRate = (440 * 0.1f) + (160 * 0.05f) + ((critical - 600) * 0.02f);
    }

    return Rnd.nextInt(100) < criticalRate;
  }
示例#4
0
 @Override
 protected void handleAttack(Creature creature) {
   super.handleAttack(creature);
   if (Rnd.get(1, 100) < 3) {
     spawnServant();
   }
 }
 /**
  * Accuracy (includes evasion/parry/block formulas): Accuracy formula is based on opponents
  * evasion/parry/block vs your own Accuracy. If your Accuracy is 300 or more above opponents
  * evasion/parry/block then you can not be evaded, parried or blocked. <br>
  * https://docs.google.com/spreadsheet/ccc?key=0AqxBGNJV9RrzdF9tOWpwUlVLOXE5bVRWeHQtbGQxaUE&hl=en_US#gid=2
  */
 public static boolean calculatePhysicalEvasion(float diff, int upperCap) {
   diff = diff * 0.6f + 50;
   if (diff > upperCap) {
     diff = upperCap;
   }
   return Rnd.nextInt(1000) < diff;
 }
示例#6
0
 private void spawnServant() {
   Npc healServant = getPosition().getWorldMapInstance().getNpc(282988);
   if (healServant == null) {
     rndSpawn(282988, Rnd.get(1, 3));
     NpcShoutsService.getInstance().sendMsg(getOwner(), 341784, getObjectId(), 0, 0);
   }
 }
  @Override
  public void onDie(Npc npc) {
    switch (npc.getNpcId()) {
      case 233719: // bosses
        spawnChests(npc);
        break;
      case 235537:
        int ap = 0;
        switch (Rnd.get(1, 3)) {
          case 1:
            ap = 3000;
            break;
          case 2:
            ap = 6000;
            break;
          case 3:
            ap = 15000;
            break;
        }

        final int apReward = ap / instance.getPlayersInside().size();
        instance.doOnAllPlayers(
            new Visitor<Player>() {

              @Override
              public void visit(Player player) {
                AbyssPointsService.addAGp(player, apReward, 0);
                PacketSendUtility.sendPacket(player, new SM_ABYSS_RANK(player.getAbyssRank()));
              }
            });
        despawnNpc(npc);
        break;
    }
  }
 @Override
 public void onDropRegistered(Npc npc) {
   Set<DropItem> dropItems =
       DropRegistrationService.getInstance().geCurrentDropMap().get(npc.getObjectId());
   int npcId = npc.getNpcId();
   int itemId = 0;
   Integer object = instance.getSoloPlayerObj();
   switch (npcId) {
     case 832865:
       dropItems.clear();
       switch (Rnd.get(1, 3)) {
         case 1:
           itemId = 188052742;
           break;
         case 2:
           itemId = 188052485;
           break;
         case 3:
           itemId = 188053450;
           break;
       }
       dropItems.add(
           DropRegistrationService.getInstance().regDropItem(1, object, npcId, itemId, 1));
       break;
   }
 }
  @Override
  protected void handleAttack(Creature creature) {
    super.handleAttack(creature);

    if (Rnd.get(1, 100) < 1) {
      spawnClone();
    }
  }
  /**
   * Calculates CRITICAL chance
   * http://www.wolframalpha.com/input/?i=quadratic+fit+%7B%7B300%2C+30.97%7D%2C+%7B320%2C+31.68%7D%2C+%7B340%2C+33.30%7D%2C+%7B360%2C+36.09%7D%2C+%7B380%2C+37.81%7D%2C+%7B400%2C+40.72%7D%2C+%7B420%2C+42.12%7D%2C+%7B440%2C+44.03%7D%2C+%7B480%2C+44.66%7D%2C+%7B500%2C+45.96%7D%2C%7B604%2C+51.84%7D%2C+%7B649%2C+52.69%7D%7D
   * http://www.aionsource.com/topic/40542-character-stats-xp-dp-origin-gerbatorteam-july-2009/
   * http://www.wolframalpha.com/input/?i=-0.000126341+x%5E2%2B0.184411+x-13.7738
   * https://docs.google.com/spreadsheet/ccc?key=0AqxBGNJV9RrzdGNjbEhQNHN3S3M5bUVfUVQxRkVIT3c&hl=en_US#gid=0
   *
   * @param attacker
   * @return double
   */
  public static boolean calculatePhysicalCriticalRate(
      Creature attacker, Creature attacked, boolean isMainHand, int criticalProb, boolean isSkill) {
    if (attacker instanceof Servant || attacker instanceof Homing) {
      return false;
    }
    int critical;
    if (attacker instanceof Player && !isMainHand) {
      critical = ((PlayerGameStats) attacker.getGameStats()).getOffHandPCritical().getCurrent();
    } else {
      critical = attacker.getGameStats().getMainHandPCritical().getCurrent();
    }

    // check one time boost skill critical
    AttackerCriticalStatus acStatus =
        attacker.getObserveController().checkAttackerCriticalStatus(AttackStatus.CRITICAL, isSkill);
    if (acStatus.isResult()) {
      if (acStatus.isPercent()) {
        critical *= (1 + acStatus.getValue() / 100);
      } else {
        return Rnd.nextInt(1000) < acStatus.getValue();
      }
    }

    critical =
        attacked.getGameStats().getPositiveReverseStat(StatEnum.PHYSICAL_CRITICAL_RESIST, critical)
            - attacker.getGameStats().getStat(StatEnum.PVP_HIT_ACCURACY, 0).getCurrent();

    // add critical Prob
    critical *= (float) criticalProb / 100f;

    double criticalRate;

    if (critical <= 440) {
      criticalRate = critical * 0.1f;
    } else if (critical <= 600) {
      criticalRate = (440 * 0.1f) + ((critical - 440) * 0.05f);
    } else {
      criticalRate = (440 * 0.1f) + (160 * 0.05f) + ((critical - 600) * 0.02f);
    }

    return Rnd.nextInt(100) < criticalRate;
  }
示例#11
0
 private SpawnTemplate rndSpawnInRange(int npcId) {
   float direction = Rnd.get(0, 199) / 100f;
   float x1 = (float) (Math.cos(Math.PI * direction) * 5);
   float y1 = (float) (Math.sin(Math.PI * direction) * 5);
   return SpawnEngine.addNewSingleTimeSpawn(
       getPosition().getMapId(),
       npcId,
       getPosition().getX() + x1,
       getPosition().getY() + y1,
       getPosition().getZ(),
       getPosition().getHeading());
 }
  @Override
  public void onEnterInstance(Player player) {
    if (isInstanceStarted.compareAndSet(false, true)) {
      sp(730311, 554.83081f, 173.87158f, 432.52448f, (byte) 0, 9, 720000);
      sp(730312, 397.11661f, 184.29782f, 432.80328f, (byte) 0, 42, 720000);
      if (Rnd.get(1, 100) < 21) {
        sp(216889, 484.1199f, 314.08817f, 403.7213f, (byte) 5, 720000);
      }
      if (Rnd.get(1, 100) < 21) {
        sp(216890, 499.52f, 598.67f, 390.49f, (byte) 59, 720000);
      }
      if (Rnd.get(1, 100) < 21) {
        spawn(216887, 486.26382f, 909.48175f, 405.24463f, (byte) 90);
      }
      if (Rnd.get(1, 100) < 51) {
        switch (Rnd.get(2)) {
          case 0:
            spawn(216888, 416.3429f, 282.32785f, 409.7311f, (byte) 80);
            break;
          default:
            spawn(216888, 552.07446f, 289.058f, 409.7311f, (byte) 80);
            break;
        }
      }

      int spawnTime = Rnd.get(10, 15) * 60 * 1000 + 120000;
      sendMsgByRace(1400633, Race.PC_ALL, spawnTime);
      sp(216941, 485.99f, 299.23f, 402.57f, (byte) 30, spawnTime);
      startInstanceTask();
    }
    super.onEnterInstance(player);
  }
 @Override
 public void onDropRegistered(Npc npc) {
   Set<DropItem> dropItems =
       DropRegistrationService.getInstance().geCurrentDropMap().get(npc.getObjectId());
   int npcId = npc.getNpcId();
   int itemId = 0;
   Integer object = instance.getSoloPlayerObj();
   switch (npcId) {
     case 702700:
       dropItems.add(
           DropRegistrationService.getInstance().regDropItem(1, object, npcId, 185000224, 1));
       if (Rnd.get(1, 100) < 70) {
         dropItems.add(
             DropRegistrationService.getInstance().regDropItem(1, object, npcId, 186000066, 1));
       }
       break;
     case 219963:
     case 219964:
     case 219965:
     case 219966:
     case 219967:
     case 219968:
       dropItems.clear();
       switch (Rnd.get(1, 3)) {
         case 1:
           itemId = 188052548;
           break;
         case 2:
           itemId = 188053620;
           break;
         case 3:
           itemId = 188053400;
           break;
       }
       dropItems.add(
           DropRegistrationService.getInstance().regDropItem(1, object, npcId, itemId, 3));
       break;
   }
 }
示例#14
0
 private void spawn(Player player) {
   int mobToSpawn = mobs.get(Rnd.get(0, 3));
   float x = 0;
   float y = 0;
   final float z = 124.942f;
   switch (mobToSpawn) {
     case 218760:
       {
         x = 250.081f;
         y = 268.308f;
         break;
       }
     case 218762:
       {
         x = 273.354f;
         y = 244.489f;
         break;
       }
     case 218761:
       {
         x = 272.994f;
         y = 244.674f;
         break;
       }
     case 218763:
       {
         x = 250.800f;
         y = 222.782f;
         break;
       }
   }
   Npc spawn =
       (Npc)
           QuestService.spawnQuestNpc(
               300330000, player.getInstanceId(), mobToSpawn, x, y, z, (byte) 0);
   Collection<Npc> allNpcs = World.getInstance().getNpcs();
   Npc target = null;
   for (Npc npc : allNpcs) {
     if (npc.getNpcId() == 730493) {
       target = npc;
     }
   }
   if (target != null) {
     spawn.getAggroList().addHate(target, 1);
   }
 }
示例#15
0
  private static void initPig() {
    float[] coords = floatArray.get(Rnd.get(floatArray.size()));
    SpawnTemplate spawn =
        SpawnEngine.addNewSingleTimeSpawn(
            WORLD_ID, NPC_ID, coords[0], coords[1], coords[2], (byte) coords[3]);
    VisibleObject mainObject = SpawnEngine.spawnObject(spawn, 1);
    if (mainObject instanceof Npc) {
      mainN = (Npc) mainObject;
    }
    ActionObserver observer =
        new ActionObserver(ObserverType.ATTACKED) {

          @Override
          public void attacked(Creature creature) {
            if (creature instanceof Player) {
              final Player player = (Player) creature;
              final int id = rewards[Rnd.get(rewards.length)];
              ItemService.addItem(player, id, 1);
              World.getInstance()
                  .doOnAllPlayers(
                      new Visitor<Player>() {

                        @Override
                        public void visit(Player object) {
                          PacketSendUtility.sendYellowMessageOnCenter(
                              object,
                              player.getName()
                                  + MuiService.getInstance().getMessage("PIG_EVENT_REWARD", id));
                        }
                      });
            }
            mainN.getObserveController().removeObserver(this);
            // mainN.setSpawn(null);
            mainN.getController().onDelete();
            initPig();
          }
        };
    if (mainN != null) {
      mainN.getObserveController().attach(observer);
    }
  }
 @Override
 public void onInstanceCreate(WorldMapInstance instance) {
   super.onInstanceCreate(instance);
   int spawn_point = Rnd.get(1, 2);
   spawn(spawn_point == 1 ? 235537 : 832865, 649.1376f, 278.06427f, 191.72736f, (byte) 90);
   int spawn_point2 = Rnd.get(1, 2);
   spawn(spawn_point2 == 1 ? 235537 : 832865, 424.37238f, 278.05197f, 191.72f, (byte) 90);
   int spawn_point3 = Rnd.get(1, 2);
   spawn(spawn_point3 == 1 ? 235537 : 832865, 387.86472f, 431.94095f, 197.20628f, (byte) 0);
   int spawn_point4 = Rnd.get(1, 2);
   spawn(spawn_point4 == 1 ? 235537 : 832865, 661.91473f, 431.9554f, 197.20628f, (byte) 60);
   int spawn_point5 = Rnd.get(1, 2);
   spawn(spawn_point5 == 1 ? 235537 : 832865, 500.65875f, 338.41437f, 180.32727f, (byte) 0);
   int spawn_point6 = Rnd.get(1, 2);
   spawn(spawn_point6 == 1 ? 235537 : 832865, 555.80597f, 575.031f, 176.89429f, (byte) 60);
   int spawn_point7 = Rnd.get(1, 2);
   spawn(spawn_point7 == 1 ? 235537 : 832865, 393.83f, 591.704f, 191.18f, (byte) 90);
   int spawn_point8 = Rnd.get(1, 2);
   spawn(spawn_point8 == 1 ? 235537 : 832865, 659.3397f, 571.47174f, 191.20131f, (byte) 60);
   int spawn_point9 = Rnd.get(1, 2);
   spawn(spawn_point9 == 1 ? 235537 : 832865, 540.199f, 448.91748f, 180.8847f, (byte) 90);
   // legion
   int spawn_legion_point = Rnd.get(1, 2);
   spawn(spawn_legion_point == 1 ? 235537 : 832865, 434.95197f, 591.77057f, 191.18217f, (byte) 90);
   int spawn_legion_point2 = Rnd.get(1, 2);
   spawn(
       spawn_legion_point2 == 1 ? 235537 : 832865, 437.78436f, 432.13367f, 197.20628f, (byte) 60);
   int spawn_legion_point3 = Rnd.get(1, 2);
   spawn(spawn_legion_point3 == 1 ? 235537 : 832865, 390.86206f, 270.09f, 191.78427f, (byte) 90);
   int spawn_legion_point4 = Rnd.get(1, 2);
   spawn(spawn_legion_point4 == 1 ? 235537 : 832865, 552.3796f, 338.2951f, 180.32727f, (byte) 60);
   int spawn_legion_point5 = Rnd.get(1, 2);
   spawn(
       spawn_legion_point5 == 1 ? 235537 : 832865, 506.79877f, 441.54056f, 180.94101f, (byte) 90);
   int spawn_legion_point6 = Rnd.get(1, 2);
   spawn(spawn_legion_point6 == 1 ? 235537 : 832865, 496.29544f, 575.58014f, 176.89429f, (byte) 0);
   int spawn_legion_point7 = Rnd.get(1, 2);
   spawn(spawn_legion_point7 == 1 ? 235537 : 832865, 615.22076f, 586.3513f, 191.21751f, (byte) 0);
   int spawn_legion_point8 = Rnd.get(1, 2);
   spawn(spawn_legion_point8 == 1 ? 235537 : 832865, 611.54803f, 431.9057f, 197.20628f, (byte) 0);
   int spawn_legion_point9 = Rnd.get(1, 2);
   spawn(
       spawn_legion_point9 == 1 ? 235537 : 832865, 615.80884f, 270.33264f, 191.78235f, (byte) 90);
 }
示例#17
0
文件: Skill.java 项目: soulxj/aion-cn
  /** Apply effects and perform actions specified in skill template */
  protected void endCast() {
    if (!effector.isCasting() || isCancelled) return;

    // if target out of range
    if (skillTemplate == null) return;

    // Check if target is out of skill range
    Properties properties = skillTemplate.getProperties();
    if (properties != null && !properties.endCastValidate(this)) {
      effector.getController().cancelCurrentSkill();
      return;
    }

    if (!validateEffectedList()) {
      effector.getController().cancelCurrentSkill();
      return;
    }

    if (!preUsageCheck()) {
      return;
    }

    effector.setCasting(null);

    if (this.getSkillTemplate().isDeityAvatar() && effector instanceof Player) {
      AbyssService.rankerSkillAnnounce((Player) effector, this.getSkillTemplate().getNameId());
    }

    /** try removing item, if its not possible return to prevent exploits */
    if (effector instanceof Player && skillMethod == SkillMethod.ITEM) {
      Item item = ((Player) effector).getInventory().getItemByObjId(this.itemObjectId);
      if (item == null) return;
      if (item.getActivationCount() > 1) {
        item.setActivationCount(item.getActivationCount() - 1);
      } else {
        if (!((Player) effector)
            .getInventory()
            .decreaseByObjectId(item.getObjectId(), 1, ItemUpdateType.DEC_USE)) return;
      }
    }
    /** Create effects and precalculate result */
    int spellStatus = 0;
    int dashStatus = 0;
    int resistCount = 0;
    boolean blockedChain = false;
    boolean blockedStance = false;
    final List<Effect> effects = new ArrayList<Effect>();
    if (skillTemplate.getEffects() != null) {
      boolean blockAOESpread = false;
      for (Creature effected : effectedList) {
        Effect effect = new Effect(this, effected, 0, itemTemplate);
        if (effected instanceof Player) {
          if (effect.getEffectResult() == EffectResult.CONFLICT) blockedStance = true;
        }
        // Force RESIST status if AOE spell spread must be blocked
        if (blockAOESpread) effect.setAttackStatus(AttackStatus.RESIST);
        effect.initialize();
        final int worldId = effector.getWorldId();
        final int instanceId = effector.getInstanceId();
        effect.setWorldPosition(worldId, instanceId, x, y, z);

        effects.add(effect);
        spellStatus = effect.getSpellStatus().getId();
        dashStatus = effect.getDashStatus().getId();

        // Block AOE propagation if firstTarget resists the spell
        if ((!blockAOESpread)
            && (effect.getAttackStatus() == AttackStatus.RESIST)
            && (isTargetAOE())) blockAOESpread = true;

        if (effect.getAttackStatus() == AttackStatus.RESIST
            || effect.getAttackStatus() == AttackStatus.DODGE) {
          resistCount++;
        }
      }

      if (resistCount == effectedList.size()) {
        blockedChain = true;
        blockedPenaltySkill = true;
      }

      // exception for point point skills(example Ice Sheet)
      if (effectedList.isEmpty() && this.isPointPointSkill()) {
        Effect effect = new Effect(this, null, 0, itemTemplate);
        effect.initialize();
        final int worldId = effector.getWorldId();
        final int instanceId = effector.getInstanceId();
        effect.setWorldPosition(worldId, instanceId, x, y, z);
        effects.add(effect);
        spellStatus = effect.getSpellStatus().getId();
      }
    }

    if (effector instanceof Player && skillMethod == SkillMethod.CAST) {
      Player playerEffector = (Player) effector;
      if (playerEffector.getController().isUnderStance()) {
        playerEffector.getController().stopStance();
      }
      if (skillTemplate.isStance() && !blockedStance) {
        playerEffector.getController().startStance(skillTemplate.getSkillId());
      }
    }

    boolean setCooldowns = true;
    if (effector instanceof Player) {
      if (this.isMulticast()
          && ((Player) effector)
                  .getChainSkills()
                  .getChainCount((Player) effector, this.getSkillTemplate(), this.chainCategory)
              != 0) {
        setCooldowns = false;
      }
    }

    // Check Chain Skill Trigger Rate
    if (CustomConfig.SKILL_CHAIN_TRIGGERRATE) {
      int chainProb = skillTemplate.getChainSkillProb();
      if (this.chainCategory != null && !blockedChain) {
        this.chainSuccess = Rnd.get(90) < chainProb;
      }
    } else {
      this.chainSuccess = true;
    }

    /** set variables for chaincondition check */
    if (effector instanceof Player && this.chainSuccess && this.chainCategory != null) {
      ((Player) effector).getChainSkills().addChainSkill(this.chainCategory, this.isMulticast());
    }

    /** Perform necessary actions (use mp,dp items etc) */
    Actions skillActions = skillTemplate.getActions();
    if (skillActions != null) {
      for (Action action : skillActions.getActions()) {
        if (!action.act(this)) return;
      }
    }

    if (effector instanceof Player) {
      QuestEnv env = new QuestEnv(effector.getTarget(), (Player) effector, 0, 0);
      QuestEngine.getInstance().onUseSkill(env, skillTemplate.getSkillId());
    }

    if (setCooldowns) this.setCooldowns();

    if (hitTime == 0) applyEffect(effects);
    else {
      ThreadPoolManager.getInstance()
          .schedule(
              new Runnable() {

                @Override
                public void run() {
                  applyEffect(effects);
                }
              },
              hitTime);
    }
    if (skillMethod == SkillMethod.CAST
        || skillMethod == SkillMethod.ITEM
        || skillMethod == SkillMethod.CHARGE) sendCastspellEnd(spellStatus, dashStatus, effects);

    endCondCheck();

    if (effector instanceof Npc)
      SkillAttackManager.afterUseSkill((NpcAI2) ((Npc) effector).getAi2());
  }
示例#18
0
  /**
   * Start gathering process
   *
   * @param player
   */
  public void onStartUse(final Player player) {
    // basic actions, need to improve here
    final GatherableTemplate template = this.getObjectTemplate();

    if (!checkPlayerSkill(player, template)) return;

    List<Material> materials = template.getMaterials().getMaterial();

    int index = 0;
    Material material = materials.get(index); // default is 0
    int count = materials.size();

    if (count < 1) {
      // error - theoretically if XML data is correct, this should never happen.
      return;
    } else if (count == 1) {
      // default is 0
    } else {
      if (player.getInventory().isFull()) {
        PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.EXTRACT_GATHER_INVENTORY_IS_FULL());
        return;
      }

      int gatherRate =
          1; // 1x rates (probably make config later, if fixed to non-linear statistic probability)
      float maxrate = 0;
      int rate = 0;
      int i = 0; // index counter

      // sort materials to ascending order
      SortedMap<Integer, Integer> hasMat = new TreeMap<Integer, Integer>();
      for (Material mat : materials) {
        maxrate += mat.getRate(); // get maxrate
        hasMat.put(
            mat.getRate(),
            i); // sort and save index of materials (key is rate and rate is unique on each
                // gatherId)
        i++;
      }

      Iterator<Integer> it = hasMat.keySet().iterator();
      while (it.hasNext()) {
        rate = it.next();
        float percent = Rnd.get() * 100f;
        float chance = ((rate / maxrate) * 100f * gatherRate);

        // default index is to 0, look to up little bit on 'material'
        if (percent < chance) {
          index = hasMat.get(rate); // return index				
          material = materials.get(index);
          break;
        }
      }
    }

    final Material finalMaterial = material;

    if (state != GatherState.GATHERING) {
      state = GatherState.GATHERING;
      currentGatherer = player.getObjectId();
      player
          .getObserveController()
          .attach(
              new StartMovingListener() {

                @Override
                public void moved() {
                  finishGathering(player);
                }
              });
      int skillLvlDiff =
          player.getSkillList().getSkillLevel(template.getHarvestSkill())
              - template.getSkillLevel();
      task = new GatheringTask(player, this, finalMaterial, skillLvlDiff);
      task.start();
    }
  }
 /** @param worldMapInstance */
 private static void startInstanceChecker(WorldMapInstance worldMapInstance) {
   int delay = 60000 + Rnd.get(-10, 10);
   worldMapInstance.setEmptyInstanceTask(
       ThreadPoolManager.getInstance()
           .scheduleAtFixedRate(new EmptyInstanceCheckerTask(worldMapInstance), delay, delay));
 }
  public static int calculateMagicalAttackDamage(
      Creature attacker, Creature target, SkillElement element, boolean isMainHand) {
    Preconditions.checkNotNull(element, "Skill element should be NONE instead of null");
    Stat2 mAttack;

    if (isMainHand) {
      mAttack = attacker.getGameStats().getMainHandMAttack();
    } else {
      mAttack = attacker.getGameStats().getOffHandMAttack();
    }

    float resultDamage = mAttack.getCurrent();

    if (attacker instanceof Player) {
      Equipment equipment = ((Player) attacker).getEquipment();
      Item weapon = equipment.getMainHandWeapon();

      if (weapon != null) {
        WeaponStats weaponStat = weapon.getItemTemplate().getWeaponStats();
        if (weaponStat == null) {
          return 0;
        }
        int totalMin = weaponStat.getMinDamage();
        int totalMax = weaponStat.getMaxDamage();
        if (totalMax - totalMin < 1) {
          log.warn("Weapon stat MIN_MAX_DAMAGE resulted average zero in main-hand calculation");
          log.warn(
              "Weapon ID: "
                  + String.valueOf(
                      equipment.getMainHandWeapon().getItemTemplate().getTemplateId()));
          log.warn("MIN_DAMAGE = " + String.valueOf(totalMin));
          log.warn("MAX_DAMAGE = " + String.valueOf(totalMax));
        }
        float knowledge = attacker.getGameStats().getKnowledge().getCurrent() * 0.01f;
        int diff = Math.round((totalMax - totalMin) * knowledge / 2);
        resultDamage =
            mAttack.getBonus()
                + getMovementModifier(attacker, StatEnum.MAGICAL_ATTACK, mAttack.getBase());
        resultDamage += Rnd.get(-diff, diff);

        if (attacker.isInState(CreatureState.POWERSHARD)) {
          Item firstShard = equipment.getMainHandPowerShard();
          Item secondShard = equipment.getOffHandPowerShard();
          if (firstShard != null) {
            equipment.usePowerShard(firstShard, 1);
            resultDamage += firstShard.getItemTemplate().getWeaponBoost();
          }

          if (secondShard != null) {
            equipment.usePowerShard(secondShard, 1);
            resultDamage += secondShard.getItemTemplate().getWeaponBoost();
          }
        }
      }
    }

    if (element != SkillElement.NONE) {
      float elementalDef =
          getMovementModifier(
              target,
              SkillElement.getResistanceForElement(element),
              target.getGameStats().getMagicalDefenseFor(element));
      resultDamage = Math.round(resultDamage * (1 - elementalDef / 1300f));
    }

    if (resultDamage <= 0) {
      resultDamage = 1;
    }

    return Math.round(resultDamage);
  }
  /**
   * @param player
   * @param target
   * @param effectTemplate
   * @param skillDamages
   * @return Damage made to target (-hp value)
   */
  public static int calculatePhysicalAttackDamage(
      Creature attacker, Creature target, boolean isMainHand) {
    Stat2 pAttack;
    if (isMainHand) {
      pAttack = attacker.getGameStats().getMainHandPAttack();
    } else {
      pAttack = ((Player) attacker).getGameStats().getOffHandPAttack();
    }
    float resultDamage = pAttack.getCurrent();
    float baseDamage = pAttack.getBase();
    if (attacker instanceof Player) {
      Equipment equipment = ((Player) attacker).getEquipment();
      Item weapon;
      if (isMainHand) {
        weapon = equipment.getMainHandWeapon();
      } else {
        weapon = equipment.getOffHandWeapon();
      }

      if (weapon != null) {
        WeaponStats weaponStat = weapon.getItemTemplate().getWeaponStats();
        if (weaponStat == null) {
          return 0;
        }
        int totalMin = weaponStat.getMinDamage();
        int totalMax = weaponStat.getMaxDamage();
        if (totalMax - totalMin < 1) {
          log.warn("Weapon stat MIN_MAX_DAMAGE resulted average zero in main-hand calculation");
          log.warn(
              "Weapon ID: "
                  + String.valueOf(
                      equipment.getMainHandWeapon().getItemTemplate().getTemplateId()));
          log.warn("MIN_DAMAGE = " + String.valueOf(totalMin));
          log.warn("MAX_DAMAGE = " + String.valueOf(totalMax));
        }
        float power = attacker.getGameStats().getPower().getCurrent() * 0.01f;
        int diff = Math.round((totalMax - totalMin) * power / 2);
        resultDamage = pAttack.getBonus() + baseDamage;

        // adjust with value from WeaponDualEffect
        // it makes lower cap of damage lower, so damage is more random on offhand
        int negativeDiff = diff;
        if (!isMainHand) {
          negativeDiff =
              (int) Math.round((200 - ((Player) attacker).getDualEffectValue()) * 0.01 * diff);
        }

        resultDamage += Rnd.get(-negativeDiff, diff);

        // add powerShard damage
        if (attacker.isInState(CreatureState.POWERSHARD)) {
          Item firstShard;
          Item secondShard = null;
          if (isMainHand) {
            firstShard = equipment.getMainHandPowerShard();
            if (weapon.getItemTemplate().isTwoHandWeapon()) {
              secondShard = equipment.getOffHandPowerShard();
            }
          } else {
            firstShard = equipment.getOffHandPowerShard();
          }

          if (firstShard != null) {
            equipment.usePowerShard(firstShard, 1);
            resultDamage += firstShard.getItemTemplate().getWeaponBoost();
          }

          if (secondShard != null) {
            equipment.usePowerShard(secondShard, 1);
            resultDamage += secondShard.getItemTemplate().getWeaponBoost();
          }
        }
      } else { // if hand attack
        int totalMin = 16;
        int totalMax = 20;

        float power = attacker.getGameStats().getPower().getCurrent() * 0.01f;
        int diff = Math.round((totalMax - totalMin) * power / 2);
        resultDamage = pAttack.getBonus() + baseDamage;
        resultDamage += Rnd.get(-diff, diff);
      }
    } else {
      int rnd = (int) (resultDamage * 0.25);
      resultDamage += Rnd.get(-rnd, rnd);
    }

    // subtract defense
    float pDef =
        target.getGameStats().getPDef().getBonus()
            + getMovementModifier(
                target, StatEnum.PHYSICAL_DEFENSE, target.getGameStats().getPDef().getBase());
    resultDamage -= (pDef * 0.10f);

    if (resultDamage <= 0) {
      resultDamage = 1;
    }

    return Math.round(resultDamage);
  }