Beispiel #1
0
  @Override
  public boolean useAdminCommand(String command, L2PcInstance activeChar) {
    if (command.equals("admin_tvt_add")) {
      L2Object target = activeChar.getTarget();

      if (!(target instanceof L2PcInstance)) {
        activeChar.sendMessage("You should select a player!");
        return true;
      }

      add(activeChar, (L2PcInstance) target);
    } else if (command.equals("admin_tvt_remove")) {
      L2Object target = activeChar.getTarget();

      if (!(target instanceof L2PcInstance)) {
        activeChar.sendMessage("You should select a player!");
        return true;
      }

      remove(activeChar, (L2PcInstance) target);
    } else if (command.equals("admin_tvt_advance")) {
      TvTManager.getInstance().skipDelay();
    }

    return true;
  }
  /**
   * Manage actions when a player click on this L2PcInstance.<br>
   * <br>
   * <B><U> Actions on first click on the L2PcInstance (Select it)</U> :</B><br>
   * <br>
   * <li>Set the target of the player
   * <li>Send a Server->Client packet MyTargetSelected to the player (display the select window)<br>
   *     <br>
   *     <B><U> Actions on second click on the L2PcInstance (Follow it/Attack it/Intercat with
   *     it)</U> :</B><br>
   *     <br>
   * <li>Send a Server->Client packet MyTargetSelected to the player (display the select window)
   * <li>If target L2PcInstance has a Private Store, notify the player AI with AI_INTENTION_INTERACT
   * <li>If target L2PcInstance is autoAttackable, notify the player AI with AI_INTENTION_ATTACK<br>
   *     <br>
   * <li>If target L2PcInstance is NOT autoAttackable, notify the player AI with AI_INTENTION_FOLLOW
   *     <br>
   *     <br>
   *     <B><U> Example of use </U> :</B><br>
   *     <br>
   * <li>Client packet : Action, AttackRequest<br>
   *     <br>
   *
   * @param activeChar The player that start an action on target L2PcInstance
   */
  public boolean action(L2PcInstance activeChar, L2Object target, boolean interact) {
    // See description in TvTEvent.java
    if (!TvTEvent.onAction(activeChar, target.getObjectId())) return false;

    // Check if the L2PcInstance is confused
    if (activeChar.isOutOfControl()) return false;

    // Aggression target lock effect
    if (activeChar.isLockedTarget() && activeChar.getLockedTarget() != target) {
      activeChar.sendPacket(new SystemMessage(SystemMessageId.FAILED_CHANGE_TARGET));
      return false;
    }

    // Check if the activeChar already target this L2PcInstance
    if (activeChar.getTarget() != target) {
      // Set the target of the activeChar
      activeChar.setTarget(target);

      // Send a Server->Client packet MyTargetSelected to the activeChar
      // The color to display in the select window is White
      activeChar.sendPacket(new MyTargetSelected(target.getObjectId(), 0));
      if (activeChar != target) activeChar.sendPacket(new ValidateLocation((L2Character) target));
    } else if (interact) {
      if (activeChar != target) activeChar.sendPacket(new ValidateLocation((L2Character) target));
      // Check if this L2PcInstance has a Private Store
      if (((L2PcInstance) target).getPrivateStoreType() != 0) {
        activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, target);
      } else {
        // Check if this L2PcInstance is autoAttackable
        if (target.isAutoAttackable(activeChar)) {
          // activeChar with lvl < 21 can't attack a cursed weapon holder
          // And a cursed weapon holder  can't attack activeChars with lvl < 21
          if ((((L2PcInstance) target).isCursedWeaponEquipped() && activeChar.getLevel() < 21)
              || (activeChar.isCursedWeaponEquipped() && ((L2Character) target).getLevel() < 21)) {
            activeChar.sendPacket(ActionFailed.STATIC_PACKET);
          } else {
            if (Config.GEODATA > 0) {
              if (GeoData.getInstance().canSeeTarget(activeChar, target)) {
                activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
                activeChar.onActionRequest();
              }
            } else {
              activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
              activeChar.onActionRequest();
            }
          }
        } else {
          // This Action Failed packet avoids activeChar getting stuck when clicking three or more
          // times
          activeChar.sendPacket(ActionFailed.STATIC_PACKET);
          if (Config.GEODATA > 0) {
            if (GeoData.getInstance().canSeeTarget(activeChar, target))
              activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, target);
          } else activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, target);
        }
      }
    }
    return true;
  }
  /**
   * Cast a skill for active summon.<br>
   * Target is retrieved from owner's target, then validated by overloaded method useSkill(int,
   * L2Character).
   *
   * @param skillName the skill name to use
   * @param pet if {@code true} it'll validate a pet, if {@code false} it will validate a servitor
   */
  private void useSkill(String skillName, boolean pet) {
    final L2PcInstance activeChar = getActiveChar();
    if (activeChar == null) {
      return;
    }

    useSkill(skillName, activeChar.getTarget(), pet);
  }
  private void spawnMonster(
      L2PcInstance activeChar, String monsterId, int respawnTime, int mobCount, boolean permanent) {
    L2Object target = activeChar.getTarget();
    if (target == null) {
      target = activeChar;
    }

    L2NpcTemplate template1;
    if (monsterId.matches("[0-9]*")) {
      // First parameter was an ID number
      int monsterTemplate = Integer.parseInt(monsterId);
      template1 = NpcData.getInstance().getTemplate(monsterTemplate);
    } else {
      // First parameter wasn't just numbers so go by name not ID
      monsterId = monsterId.replace('_', ' ');
      template1 = NpcData.getInstance().getTemplateByName(monsterId);
    }

    try {
      L2Spawn spawn = new L2Spawn(template1);
      if (Config.SAVE_GMSPAWN_ON_CUSTOM) {
        spawn.setCustom(true);
      }
      spawn.setX(target.getX());
      spawn.setY(target.getY());
      spawn.setZ(target.getZ());
      spawn.setAmount(mobCount);
      spawn.setHeading(activeChar.getHeading());
      spawn.setRespawnDelay(respawnTime);
      if (activeChar.getInstanceId() > 0) {
        spawn.setInstanceId(activeChar.getInstanceId());
        permanent = false;
      } else {
        spawn.setInstanceId(0);
      }
      // TODO add checks for GrandBossSpawnManager
      if (RaidBossSpawnManager.getInstance().isDefined(spawn.getId())) {
        activeChar.sendMessage("You cannot spawn another instance of " + template1.getName() + ".");
      } else {
        if (RaidBossSpawnManager.getInstance().getValidTemplate(spawn.getId()) != null) {
          spawn.setRespawnMinDelay(43200);
          spawn.setRespawnMaxDelay(129600);
          RaidBossSpawnManager.getInstance()
              .addNewSpawn(spawn, 0, template1.getBaseHpMax(), template1.getBaseMpMax(), permanent);
        } else {
          SpawnTable.getInstance().addNewSpawn(spawn, permanent);
          spawn.init();
        }
        if (!permanent) {
          spawn.stopRespawn();
        }
        activeChar.sendMessage("Created " + template1.getName() + " on " + target.getObjectId());
      }
    } catch (Exception e) {
      activeChar.sendPacket(SystemMessageId.TARGET_CANT_FOUND);
    }
  }
  @Override
  public boolean useAdminCommand(String command, L2PcInstance activeChar) {
    String[] parts = command.split(" ");
    if (parts.length == 2) {
      try {
        int lvl = Integer.parseInt(parts[1]);
        if (activeChar.getTarget() instanceof L2PcInstance) {
          onlineChange(activeChar, (L2PcInstance) activeChar.getTarget(), lvl);
        } else {
          activeChar.sendPacket(SystemMessageId.INCORRECT_TARGET);
        }
      } catch (Exception e) {
        activeChar.sendMessage("Usage: //changelvl <target_new_level> | <player_name> <new_level>");
      }
    } else if (parts.length == 3) {
      String name = parts[1];
      int lvl = Integer.parseInt(parts[2]);
      L2PcInstance player = L2World.getInstance().getPlayer(name);
      if (player != null) {
        onlineChange(activeChar, player, lvl);
      } else {
        try (Connection con = ConnectionFactory.getInstance().getConnection();
            PreparedStatement ps =
                con.prepareStatement("UPDATE characters SET accesslevel=? WHERE char_name=?")) {
          ps.setInt(1, lvl);
          ps.setString(2, name);
          ps.execute();

          if (ps.getUpdateCount() == 0) {
            activeChar.sendMessage("角色不在线或者权限等级没有变化.");
          } else {
            activeChar.sendMessage("将角色的权限等级谁定为 " + lvl);
          }
        } catch (SQLException se) {
          activeChar.sendMessage("角色权限等级变化时SQL异常");
          if (Config.DEBUG) {
            se.printStackTrace();
          }
        }
      }
    }
    return true;
  }
  @Override
  protected void runImpl() {
    L2PcInstance activeChar = getClient().getActiveChar();
    if (activeChar == null) {
      return;
    }

    String command = "admin_" + _command.split(" ")[0];

    IAdminCommandHandler ach = AdminCommandHandler.getInstance().getHandler(command);

    if (ach == null) {
      if (activeChar.isGM()) {
        activeChar.sendMessage("指令「" + command.substring(6) + "」不存在!");
      }

      _log.warning("No handler registered for admin command '" + command + "'");
      return;
    }

    if (!AdminData.getInstance().hasAccess(command, activeChar.getAccessLevel())) {
      activeChar.sendMessage("没有相关权限");
      _log.warning(
          "Character "
              + activeChar.getName()
              + " tryed to use admin command "
              + command
              + ", but have no access to it!");
      return;
    }

    if (Config.GMAUDIT) {
      GMAudit.auditGMAction(
          activeChar.getName() + " [" + activeChar.getObjectId() + "]",
          _command,
          (activeChar.getTarget() != null ? activeChar.getTarget().getName() : "no-target"));
    }

    ach.useAdminCommand("admin_" + _command, activeChar);
  }
  /**
   * @see
   *     com.l2jserver.gameserver.handler.IItemHandler#useItem(com.l2jserver.gameserver.model.actor.L2Playable,
   *     com.l2jserver.gameserver.model.L2ItemInstance)
   */
  public void useItem(L2Playable playable, L2ItemInstance _item) {
    if (!(playable instanceof L2PcInstance)) return;

    if (CastleManorManager.getInstance().isDisabled()) return;

    _activeChar = (L2PcInstance) playable;

    if (!(_activeChar.getTarget() instanceof L2MonsterInstance)) {
      _activeChar.sendPacket(new SystemMessage(SystemMessageId.INCORRECT_TARGET));
      _activeChar.sendPacket(ActionFailed.STATIC_PACKET);
      return;
    }

    _target = (L2MonsterInstance) _activeChar.getTarget();

    if (_target == null || !_target.isDead()) {
      _activeChar.sendPacket(ActionFailed.STATIC_PACKET);
      return;
    }

    L2Skill skill = SkillTable.getInstance().getInfo(2098, 1); // harvesting skill
    if (skill != null) _activeChar.useMagic(skill, false, false);
  }
 /**
  * Manage actions when a player click on the L2ArtefactInstance.<br>
  * <br>
  * <B><U> Actions</U> :</B><br>
  * <br>
  * <li>Set the L2NpcInstance as target of the L2PcInstance player (if necessary)
  * <li>Send a Server->Client packet MyTargetSelected to the L2PcInstance player (display the
  *     select window)
  * <li>Send a Server->Client packet ValidateLocation to correct the L2NpcInstance position and
  *     heading on the client<br>
  *     <br>
  *     <B><U> Example of use </U> :</B><br>
  *     <br>
  * <li>Client packet : Action, AttackRequest<br>
  *     <br>
  */
 @Override
 public boolean action(L2PcInstance activeChar, L2Object target, boolean interact) {
   if (!((L2Npc) target).canTarget(activeChar)) {
     return false;
   }
   if (activeChar.getTarget() != target) {
     activeChar.setTarget(target);
   } else if (interact) {
     // Calculate the distance between the L2PcInstance and the L2NpcInstance
     if (!((L2Npc) target).canInteract(activeChar)) {
       // Notify the L2PcInstance AI with AI_INTENTION_INTERACT
       activeChar.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, target);
     }
   }
   return true;
 }
Beispiel #9
0
  @Override
  public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) {
    if (event.equals("assist_player")) {
      final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
      if ((tmpworld == null) || !(tmpworld instanceof MDWorld)) {
        return null;
      }
      final MDWorld world = (MDWorld) tmpworld;

      world.toyron.setIsRunning(true);
      if (player.isInCombat()
          && (player.getTarget() != null)
          && player.getTarget().isMonster()
          && !((L2MonsterInstance) player.getTarget()).isAlikeDead()) {
        if (world.toyron.calculateDistance(player.getTarget(), false, false) > 50) {
          world
              .toyron
              .getAI()
              .setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, player.getTarget().getLocation());
          broadcastNpcSay(
              world.toyron, ChatType.NPC_GENERAL, NpcStringId.ENOUGH_OF_THIS_COME_AT_ME);
        } else if (world.toyron.getTarget() != player.getTarget()) {
          world.toyron.addDamageHate((L2Character) player.getTarget(), 0, 1000);
        }
      } else {
        world.toyron.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player);
      }

      if (world.thiefSpawns.get(0).isDead() && world.thiefSpawns.get(1).isDead()) {
        final QuestState qs =
            player.getQuestState(Q10327_IntruderWhoWantsTheBookOfGiants.class.getSimpleName());
        if ((qs != null) && qs.isCond(2)) {
          qs.setCond(3, true);
          showOnScreenMsg(
              player,
              NpcStringId.TALK_TO_TOYRON_TO_RETURN_TO_THE_MUSEUM_LOBBY,
              ExShowScreenMessage.TOP_CENTER,
              5000);
        }
      } else {
        startQuestTimer("assist_player", 1000, world.toyron, player);
      }
    } else if (event.equals("enter_instance")) {
      if (npc.getId() != PANTHEON) {
        return null;
      }
      enterInstance(player, new MDWorld(), "MuseumDungeon.xml", TEMPLATE_ID);
    }
    return super.onAdvEvent(event, npc, player);
  }
Beispiel #10
0
  @Override
  public boolean useUserCommand(int id, L2PcInstance activeChar) {
    if (id != COMMAND_IDS[0]) {
      return false;
    }

    int nobleObjId = activeChar.getObjectId();
    final L2Object target = activeChar.getTarget();
    if (target != null) {
      if (target.isPlayer() && target.getActingPlayer().isNoble()) {
        nobleObjId = target.getObjectId();
      } else {
        activeChar.sendPacket(SystemMessageId.NOBLESSE_ONLY);
        return false;
      }
    } else if (!activeChar.isNoble()) {
      activeChar.sendPacket(SystemMessageId.NOBLESSE_ONLY);
      return false;
    }

    final SystemMessage sm =
        SystemMessage.getSystemMessage(
            SystemMessageId
                .THE_CURRENT_RECORD_FOR_THIS_OLYMPIAD_SESSION_IS_S1_MATCHES_S2_WINS_S3_DEFEATS_YOU_HAVE_EARNED_S4_OLYMPIAD_POINTS);
    sm.addInt(Olympiad.getInstance().getCompetitionDone(nobleObjId));
    sm.addInt(Olympiad.getInstance().getCompetitionWon(nobleObjId));
    sm.addInt(Olympiad.getInstance().getCompetitionLost(nobleObjId));
    sm.addInt(Olympiad.getInstance().getNoblePoints(nobleObjId));
    activeChar.sendPacket(sm);

    final SystemMessage sm2 =
        SystemMessage.getSystemMessage(
            SystemMessageId
                .YOU_HAVE_S1_MATCHES_REMAINING_THAT_YOU_CAN_PARTECIPATE_IN_THIS_WEEK_S2_CLASSED_S3_NON_CLASSED_S4_TEAM);
    sm2.addInt(Olympiad.getInstance().getRemainingWeeklyMatches(nobleObjId));
    sm2.addInt(Olympiad.getInstance().getRemainingWeeklyMatchesClassed(nobleObjId));
    sm2.addInt(Olympiad.getInstance().getRemainingWeeklyMatchesNonClassed(nobleObjId));
    sm2.addInt(Olympiad.getInstance().getRemainingWeeklyMatchesTeam(nobleObjId));
    activeChar.sendPacket(sm2);
    return true;
  }
  /**
   * Cast a skill for all active summon.<br>
   * Target is retrieved from owner's target
   *
   * @param skillId the skill Id to use
   */
  private void useServitorsSkill(int skillId) {
    final L2PcInstance activeChar = getActiveChar();
    if (activeChar == null) {
      return;
    }

    activeChar
        .getServitors()
        .values()
        .forEach(
            servitor -> {
              if (!validateSummon(servitor, false)) {
                return;
              }

              final int lvl = SummonSkillsTable.getInstance().getAvailableLevel(servitor, skillId);

              if (lvl > 0) {
                servitor.setTarget(activeChar.getTarget());
                servitor.useMagic(
                    SkillData.getInstance().getSkill(skillId, lvl), _ctrlPressed, _shiftPressed);
              }
            });
  }
  @Override
  protected void runImpl() {
    if (_items == null) {
      return;
    }

    // Get the current player and return if null
    L2PcInstance activeChar = getClient().getActiveChar();
    if (activeChar == null) {
      return;
    }

    if (!getClient().getFloodProtectors().getTransaction().tryPerformAction("buy")) {
      activeChar.sendMessage("You are buying too fast.");
      return;
    }

    // If Alternate rule Karma punishment is set to true, forbid Wear to player with Karma
    if (!Config.ALT_GAME_KARMA_PLAYER_CAN_SHOP && (activeChar.getKarma() > 0)) {
      return;
    }

    // Check current target of the player and the INTERACTION_DISTANCE
    L2Object target = activeChar.getTarget();
    if (!activeChar.isGM()
        && ((target == null // No target (i.e. GM Shop)
            )
            || !((target instanceof L2MerchantInstance)) // Target not a merchant
            || !activeChar.isInsideRadius(
                target, L2Npc.INTERACTION_DISTANCE, false, false) // Distance is too far
        )) {
      return;
    }

    if ((_count < 1) || (_listId >= 4000000)) {
      sendPacket(ActionFailed.STATIC_PACKET);
      return;
    }

    // Get the current merchant targeted by the player
    final L2MerchantInstance merchant =
        (target instanceof L2MerchantInstance) ? (L2MerchantInstance) target : null;
    if (merchant == null) {
      _log.warning(getClass().getName() + " Null merchant!");
      return;
    }

    final L2BuyList buyList = BuyListData.getInstance().getBuyList(_listId);
    if (buyList == null) {
      Util.handleIllegalPlayerAction(
          activeChar,
          "Warning!! Character "
              + activeChar.getName()
              + " of account "
              + activeChar.getAccountName()
              + " sent a false BuyList list_id "
              + _listId,
          Config.DEFAULT_PUNISH);
      return;
    }

    long totalPrice = 0;
    Map<Integer, Integer> itemList = new HashMap<>();

    for (int i = 0; i < _count; i++) {
      int itemId = _items[i];

      final Product product = buyList.getProductByItemId(itemId);
      if (product == null) {
        Util.handleIllegalPlayerAction(
            activeChar,
            "Warning!! Character "
                + activeChar.getName()
                + " of account "
                + activeChar.getAccountName()
                + " sent a false BuyList list_id "
                + _listId
                + " and item_id "
                + itemId,
            Config.DEFAULT_PUNISH);
        return;
      }

      L2Item template = product.getItem();
      if (template == null) {
        continue;
      }

      int slot = Inventory.getPaperdollIndex(template.getBodyPart());
      if (slot < 0) {
        continue;
      }

      if (template instanceof L2Weapon) {
        if (activeChar.getRace().ordinal() == 5) {
          if (template.getItemType() == WeaponType.NONE) {
            continue;
          } else if ((template.getItemType() == WeaponType.RAPIER)
              || (template.getItemType() == WeaponType.CROSSBOW)
              || (template.getItemType() == WeaponType.ANCIENTSWORD)) {
            continue;
          }
        }
      } else if (template instanceof L2Armor) {
        if (activeChar.getRace().ordinal() == 5) {
          if ((template.getItemType() == ArmorType.HEAVY)
              || (template.getItemType() == ArmorType.MAGIC)) {
            continue;
          }
        }
      }

      if (itemList.containsKey(slot)) {
        activeChar.sendPacket(SystemMessageId.YOU_CAN_NOT_TRY_THOSE_ITEMS_ON_AT_THE_SAME_TIME);
        return;
      }

      itemList.put(slot, itemId);
      totalPrice += Config.WEAR_PRICE;
      if (totalPrice > Inventory.MAX_ADENA) {
        Util.handleIllegalPlayerAction(
            activeChar,
            "Warning!! Character "
                + activeChar.getName()
                + " of account "
                + activeChar.getAccountName()
                + " tried to purchase over "
                + Inventory.MAX_ADENA
                + " adena worth of goods.",
            Config.DEFAULT_PUNISH);
        return;
      }
    }

    // Charge buyer and add tax to castle treasury if not owned by npc clan because a Try On is not
    // Free
    if ((totalPrice < 0)
        || !activeChar.reduceAdena("Wear", totalPrice, activeChar.getLastFolkNPC(), true)) {
      activeChar.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
      return;
    }

    if (!itemList.isEmpty()) {
      activeChar.sendPacket(new ShopPreviewInfo(itemList));
      // Schedule task
      ThreadPoolManager.getInstance()
          .scheduleGeneral(new RemoveWearItemsTask(activeChar), Config.WEAR_DELAY * 1000);
    }
  }
  @Override
  protected void runImpl() {
    final L2PcInstance activeChar = getActiveChar();
    if (activeChar == null) {
      return;
    }

    if (Config.DEBUG) {
      _log.info(
          getType()
              + ": "
              + activeChar
              + " requested action use ID: "
              + _actionId
              + " Ctrl pressed:"
              + _ctrlPressed
              + " Shift pressed:"
              + _shiftPressed);
    }

    // Don't do anything if player is dead or confused
    if ((activeChar.isFakeDeath() && (_actionId != 0))
        || activeChar.isDead()
        || activeChar.isOutOfControl()) {
      sendPacket(ActionFailed.STATIC_PACKET);
      return;
    }

    final BuffInfo info =
        activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
    if (info != null) {
      for (AbstractEffect effect : info.getEffects()) {
        if (!effect.checkCondition(_actionId)) {
          activeChar.sendPacket(
              SystemMessageId
                  .YOU_HAVE_BEEN_REPORTED_AS_AN_ILLEGAL_PROGRAM_USER_SO_YOUR_ACTIONS_HAVE_BEEN_RESTRICTED);
          activeChar.sendPacket(ActionFailed.STATIC_PACKET);
          return;
        }
      }
    }

    // Don't allow to do some action if player is transformed
    if (activeChar.isTransformed()) {
      int[] allowedActions =
          activeChar.isTransformed()
              ? ExBasicActionList.ACTIONS_ON_TRANSFORM
              : ExBasicActionList.DEFAULT_ACTION_LIST;
      if (!(Arrays.binarySearch(allowedActions, _actionId) >= 0)) {
        sendPacket(ActionFailed.STATIC_PACKET);
        _log.warning(
            "Player "
                + activeChar
                + " used action which he does not have! Id = "
                + _actionId
                + " transform: "
                + activeChar.getTransformation());
        return;
      }
    }

    final L2Summon pet = activeChar.getPet();
    final L2Summon servitor = activeChar.getAnyServitor();
    final L2Object target = activeChar.getTarget();
    switch (_actionId) {
      case 0: // Sit/Stand
        if (activeChar.isSitting() || !activeChar.isMoving() || activeChar.isFakeDeath()) {
          useSit(activeChar, target);
        } else {
          // Sit when arrive using next action.
          // Creating next action class.
          final NextAction nextAction =
              new NextAction(
                  CtrlEvent.EVT_ARRIVED,
                  CtrlIntention.AI_INTENTION_MOVE_TO,
                  () -> useSit(activeChar, target));

          // Binding next action to AI.
          activeChar.getAI().setNextAction(nextAction);
        }
        break;
      case 1: // Walk/Run
        if (activeChar.isRunning()) {
          activeChar.setWalking();
        } else {
          activeChar.setRunning();
        }
        break;
      case 10: // Private Store - Sell
        activeChar.tryOpenPrivateSellStore(false);
        break;
      case 15: // Change Movement Mode (Pets)
        if (validateSummon(pet, true)) {
          ((L2SummonAI) pet.getAI()).notifyFollowStatusChange();
        }
        break;
      case 16: // Attack (Pets)
        if (validateSummon(pet, true)) {
          if (pet.canAttack(_ctrlPressed)) {
            pet.doAttack();
          }
        }
        break;
      case 17: // Stop (Pets)
        if (validateSummon(pet, true)) {
          pet.cancelAction();
        }
        break;
      case 19: // Unsummon Pet
        if (!validateSummon(pet, true)) {
          break;
        }

        if (pet.isDead()) {
          sendPacket(SystemMessageId.DEAD_PETS_CANNOT_BE_RETURNED_TO_THEIR_SUMMONING_ITEM);
          break;
        }

        if (pet.isAttackingNow() || pet.isInCombat() || pet.isMovementDisabled()) {
          sendPacket(SystemMessageId.A_PET_CANNOT_BE_UNSUMMONED_DURING_BATTLE);
          break;
        }

        if (pet.isHungry()) {
          if (!((L2PetInstance) pet).getPetData().getFood().isEmpty()) {
            sendPacket(SystemMessageId.YOU_MAY_NOT_RESTORE_A_HUNGRY_PET);
          } else {
            sendPacket(
                SystemMessageId
                    .THE_MINION_PET_CANNOT_BE_RETURNED_BECAUSE_THERE_IS_NOT_MUCH_TIME_REMAINING_UNTIL_IT_LEAVES);
          }
          break;
        }

        pet.unSummon(activeChar);
        break;
      case 21: // Change Movement Mode (Servitors)
        if (validateSummon(servitor, false)) {
          ((L2SummonAI) servitor.getAI()).notifyFollowStatusChange();
        }
        break;
      case 22: // Attack (Servitors)
        if (validateSummon(servitor, false)) {
          if (servitor.canAttack(_ctrlPressed)) {
            servitor.doAttack();
          }
        }
        break;
      case 23: // Stop (Servitors)
        if (validateSummon(servitor, false)) {
          servitor.cancelAction();
        }
        break;
      case 28: // Private Store - Buy
        activeChar.tryOpenPrivateBuyStore();
        break;
      case 32: // Wild Hog Cannon - Wild Cannon
        useSkill("DDMagic", false);
        break;
      case 36: // Soulless - Toxic Smoke
        useSkill("RangeDebuff", false);
        break;
      case 37: // Dwarven Manufacture
        if (activeChar.isAlikeDead()) {
          sendPacket(ActionFailed.STATIC_PACKET);
          return;
        }
        if (activeChar.getPrivateStoreType() != PrivateStoreType.NONE) {
          activeChar.setPrivateStoreType(PrivateStoreType.NONE);
          activeChar.broadcastUserInfo();
        }
        if (activeChar.isSitting()) {
          activeChar.standUp();
        }

        sendPacket(new RecipeShopManageList(activeChar, true));
        break;
      case 38: // Mount/Dismount
        activeChar.mountPlayer(pet);
        break;
      case 39: // Soulless - Parasite Burst
        useSkill("RangeDD", false);
        break;
      case 41: // Wild Hog Cannon - Attack
        if (validateSummon(servitor, false)) {
          if ((target != null) && (target.isDoor() || (target instanceof L2SiegeFlagInstance))) {
            useSkill(4230, false);
          } else {
            sendPacket(SystemMessageId.INVALID_TARGET);
          }
        }
        break;
      case 42: // Kai the Cat - Self Damage Shield
        useSkill("HealMagic", false);
        break;
      case 43: // Merrow the Unicorn - Hydro Screw
        useSkill("DDMagic", false);
        break;
      case 44: // Big Boom - Boom Attack
        useSkill("DDMagic", false);
        break;
      case 45: // Boxer the Unicorn - Master Recharge
        useSkill("HealMagic", activeChar, false);
        break;
      case 46: // Mew the Cat - Mega Storm Strike
        useSkill("DDMagic", false);
        break;
      case 47: // Silhouette - Steal Blood
        useSkill("DDMagic", false);
        break;
      case 48: // Mechanic Golem - Mech. Cannon
        useSkill("DDMagic", false);
        break;
      case 51: // General Manufacture
        // Player shouldn't be able to set stores if he/she is alike dead (dead or fake death)
        if (activeChar.isAlikeDead()) {
          sendPacket(ActionFailed.STATIC_PACKET);
          return;
        }
        if (activeChar.getPrivateStoreType() != PrivateStoreType.NONE) {
          activeChar.setPrivateStoreType(PrivateStoreType.NONE);
          activeChar.broadcastUserInfo();
        }
        if (activeChar.isSitting()) {
          activeChar.standUp();
        }

        sendPacket(new RecipeShopManageList(activeChar, false));
        break;
      case 52: // Unsummon Servitor
        if (validateSummon(servitor, false)) {
          if (servitor.isAttackingNow() || servitor.isInCombat()) {
            sendPacket(SystemMessageId.A_SERVITOR_WHOM_IS_ENGAGED_IN_BATTLE_CANNOT_BE_DE_ACTIVATED);
            break;
          }
          servitor.unSummon(activeChar);
        }
        break;
      case 53: // Move to target (Servitors)
        if (validateSummon(servitor, false)) {
          if ((target != null) && (servitor != target) && !servitor.isMovementDisabled()) {
            servitor.setFollowStatus(false);
            servitor.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, target.getLocation());
          }
        }
        break;
      case 54: // Move to target (Pets)
        if (validateSummon(pet, true)) {
          if ((target != null) && (pet != target) && !pet.isMovementDisabled()) {
            pet.setFollowStatus(false);
            pet.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, target.getLocation());
          }
        }
        break;
      case 61: // Private Store Package Sell
        activeChar.tryOpenPrivateSellStore(true);
        break;
      case 65: // Bot Report Button
        if (Config.BOTREPORT_ENABLE) {
          BotReportTable.getInstance().reportBot(activeChar);
        } else {
          activeChar.sendMessage("This feature is disabled.");
        }
        break;
      case 67: // Steer
        if (activeChar.isInAirShip()) {
          if (activeChar.getAirShip().setCaptain(activeChar)) {
            activeChar.broadcastUserInfo();
          }
        }
        break;
      case 68: // Cancel Control
        if (activeChar.isInAirShip() && activeChar.getAirShip().isCaptain(activeChar)) {
          if (activeChar.getAirShip().setCaptain(null)) {
            activeChar.broadcastUserInfo();
          }
        }
        break;
      case 69: // Destination Map
        AirShipManager.getInstance().sendAirShipTeleportList(activeChar);
        break;
      case 70: // Exit Airship
        if (activeChar.isInAirShip()) {
          if (activeChar.getAirShip().isCaptain(activeChar)) {
            if (activeChar.getAirShip().setCaptain(null)) {
              activeChar.broadcastUserInfo();
            }
          } else if (activeChar.getAirShip().isInDock()) {
            activeChar.getAirShip().oustPlayer(activeChar);
          }
        }
        break;
      case 71:
      case 72:
      case 73:
        useCoupleSocial(_actionId - 55);
        break;
      case 78:
      case 79:
      case 80:
      case 81:
        if ((activeChar.getParty() != null)
            && (activeChar.getTarget() != null)
            && (activeChar.getTarget().isCharacter())) {
          activeChar
              .getParty()
              .addTacticalSign(_actionId - 77, (L2Character) activeChar.getTarget());
        } else {
          sendPacket(ActionFailed.STATIC_PACKET);
        }
        break;
      case 82:
      case 83:
      case 84:
      case 85:
        if (activeChar.getParty() != null) {
          activeChar.getParty().setTargetBasedOnTacticalSignId(activeChar, _actionId - 81);
        } else {
          sendPacket(ActionFailed.STATIC_PACKET);
        }
        break;
      case 90: // /instancedzone action since Lindvior
        activeChar.sendPacket(new ExInzoneWaiting(activeChar));
        break;
      case 1000: // Siege Golem - Siege Hammer
        if ((target != null) && target.isDoor()) {
          useSkill(4079, false);
        }
        break;
      case 1001: // Sin Eater - Ultimate Bombastic Buster
        if (validateSummon(pet, true) && (pet.getId() == SIN_EATER_ID)) {
          pet.broadcastPacket(
              new NpcSay(
                  pet.getObjectId(),
                  ChatType.NPC_GENERAL,
                  pet.getId(),
                  NPC_STRINGS[Rnd.get(NPC_STRINGS.length)]));
        }
        break;
      case 1003: // Wind Hatchling/Strider - Wild Stun
        useSkill("PhysicalSpecial", true);
        break;
      case 1004: // Wind Hatchling/Strider - Wild Defense
        useSkill("Buff", activeChar, true);
        break;
      case 1005: // Star Hatchling/Strider - Bright Burst
        useSkill("DDMagic", true);
        break;
      case 1006: // Star Hatchling/Strider - Bright Heal
        useSkill("Heal", activeChar, true);
        break;
      case 1007: // Feline Queen - Blessing of Queen
        useSkill("Buff1", activeChar, false);
        break;
      case 1008: // Feline Queen - Gift of Queen
        useSkill("Buff2", activeChar, false);
        break;
      case 1009: // Feline Queen - Cure of Queen
        useSkill("DDMagic", false);
        break;
      case 1010: // Unicorn Seraphim - Blessing of Seraphim
        useSkill("Buff1", activeChar, false);
        break;
      case 1011: // Unicorn Seraphim - Gift of Seraphim
        useSkill("Buff2", activeChar, false);
        break;
      case 1012: // Unicorn Seraphim - Cure of Seraphim
        useSkill("DDMagic", false);
        break;
      case 1013: // Nightshade - Curse of Shade
        useSkill("DeBuff1", false);
        break;
      case 1014: // Nightshade - Mass Curse of Shade
        useSkill("DeBuff2", false);
        break;
      case 1015: // Nightshade - Shade Sacrifice
        useSkill("Heal", false);
        break;
      case 1016: // Cursed Man - Cursed Blow
        useSkill("PhysicalSpecial1", false);
        break;
      case 1017: // Cursed Man - Cursed Strike
        useSkill("PhysicalSpecial2", false);
        break;
      case 1031: // Feline King - Slash
        useSkill("PhysicalSpecial1", false);
        break;
      case 1032: // Feline King - Spinning Slash
        useSkill("PhysicalSpecial2", false);
        break;
      case 1033: // Feline King - Hold of King
        useSkill("PhysicalSpecial3", false);
        break;
      case 1034: // Magnus the Unicorn - Whiplash
        useSkill("PhysicalSpecial1", false);
        break;
      case 1035: // Magnus the Unicorn - Tridal Wave
        useSkill("PhysicalSpecial2", false);
        break;
      case 1036: // Spectral Lord - Corpse Kaboom
        useSkill("PhysicalSpecial1", false);
        break;
      case 1037: // Spectral Lord - Dicing Death
        useSkill("PhysicalSpecial2", false);
        break;
      case 1038: // Spectral Lord - Dark Curse
        useSkill("PhysicalSpecial3", false);
        break;
      case 1039: // Swoop Cannon - Cannon Fodder
        useSkill(5110, false);
        break;
      case 1040: // Swoop Cannon - Big Bang
        useSkill(5111, false);
        break;
      case 1041: // Great Wolf - Bite Attack
        useSkill("Skill01", true);
        break;
      case 1042: // Great Wolf - Maul
        useSkill("Skill03", true);
        break;
      case 1043: // Great Wolf - Cry of the Wolf
        useSkill("Skill02", true);
        break;
      case 1044: // Great Wolf - Awakening
        useSkill("Skill04", true);
        break;
      case 1045: // Great Wolf - Howl
        useSkill(5584, true);
        break;
      case 1046: // Strider - Roar
        useSkill(5585, true);
        break;
      case 1047: // Divine Beast - Bite
        useSkill(5580, false);
        break;
      case 1048: // Divine Beast - Stun Attack
        useSkill(5581, false);
        break;
      case 1049: // Divine Beast - Fire Breath
        useSkill(5582, false);
        break;
      case 1050: // Divine Beast - Roar
        useSkill(5583, false);
        break;
      case 1051: // Feline Queen - Bless The Body
        useSkill("buff3", false);
        break;
      case 1052: // Feline Queen - Bless The Soul
        useSkill("buff4", false);
        break;
      case 1053: // Feline Queen - Haste
        useSkill("buff5", false);
        break;
      case 1054: // Unicorn Seraphim - Acumen
        useSkill("buff3", false);
        break;
      case 1055: // Unicorn Seraphim - Clarity
        useSkill("buff4", false);
        break;
      case 1056: // Unicorn Seraphim - Empower
        useSkill("buff5", false);
        break;
      case 1057: // Unicorn Seraphim - Wild Magic
        useSkill("buff6", false);
        break;
      case 1058: // Nightshade - Death Whisper
        useSkill("buff3", false);
        break;
      case 1059: // Nightshade - Focus
        useSkill("buff4", false);
        break;
      case 1060: // Nightshade - Guidance
        useSkill("buff5", false);
        break;
      case 1061: // Wild Beast Fighter, White Weasel - Death blow
        useSkill(5745, true);
        break;
      case 1062: // Wild Beast Fighter - Double attack
        useSkill(5746, true);
        break;
      case 1063: // Wild Beast Fighter - Spin attack
        useSkill(5747, true);
        break;
      case 1064: // Wild Beast Fighter - Meteor Shower
        useSkill(5748, true);
        break;
      case 1065: // Fox Shaman, Wild Beast Fighter, White Weasel, Fairy Princess - Awakening
        useSkill(5753, true);
        break;
      case 1066: // Fox Shaman, Spirit Shaman - Thunder Bolt
        useSkill(5749, true);
        break;
      case 1067: // Fox Shaman, Spirit Shaman - Flash
        useSkill(5750, true);
        break;
      case 1068: // Fox Shaman, Spirit Shaman - Lightning Wave
        useSkill(5751, true);
        break;
      case 1069: // Fox Shaman, Fairy Princess - Flare
        useSkill(5752, true);
        break;
      case 1070: // White Weasel, Fairy Princess, Improved Baby Buffalo, Improved Baby Kookaburra,
        // Improved Baby Cougar, Spirit Shaman, Toy Knight, Turtle Ascetic - Buff control
        useSkill(5771, true);
        break;
      case 1071: // Tigress - Power Strike
        useSkill("DDMagic", true);
        break;
      case 1072: // Toy Knight - Piercing attack
        useSkill(6046, true);
        break;
      case 1073: // Toy Knight - Whirlwind
        useSkill(6047, true);
        break;
      case 1074: // Toy Knight - Lance Smash
        useSkill(6048, true);
        break;
      case 1075: // Toy Knight - Battle Cry
        useSkill(6049, true);
        break;
      case 1076: // Turtle Ascetic - Power Smash
        useSkill(6050, true);
        break;
      case 1077: // Turtle Ascetic - Energy Burst
        useSkill(6051, true);
        break;
      case 1078: // Turtle Ascetic - Shockwave
        useSkill(6052, true);
        break;
      case 1079: // Turtle Ascetic - Howl
        useSkill(6053, true);
        break;
      case 1080: // Phoenix Rush
        useSkill(6041, false);
        break;
      case 1081: // Phoenix Cleanse
        useSkill(6042, false);
        break;
      case 1082: // Phoenix Flame Feather
        useSkill(6043, false);
        break;
      case 1083: // Phoenix Flame Beak
        useSkill(6044, false);
        break;
      case 1084: // Switch State
        if (pet instanceof L2BabyPetInstance) {
          useSkill(SWITCH_STANCE_ID, true);
        }
        break;
      case 1086: // Panther Cancel
        useSkill(6094, false);
        break;
      case 1087: // Panther Dark Claw
        useSkill(6095, false);
        break;
      case 1088: // Panther Fatal Claw
        useSkill(6096, false);
        break;
      case 1089: // Deinonychus - Tail Strike
        useSkill(6199, true);
        break;
      case 1090: // Guardian's Strider - Strider Bite
        useSkill(6205, true);
        break;
      case 1091: // Guardian's Strider - Strider Fear
        useSkill(6206, true);
        break;
      case 1092: // Guardian's Strider - Strider Dash
        useSkill(6207, true);
        break;
      case 1093: // Maguen - Maguen Strike
        useSkill(6618, true);
        break;
      case 1094: // Maguen - Maguen Wind Walk
        useSkill(6681, true);
        break;
      case 1095: // Elite Maguen - Maguen Power Strike
        useSkill(6619, true);
        break;
      case 1096: // Elite Maguen - Elite Maguen Wind Walk
        useSkill(6682, true);
        break;
      case 1097: // Maguen - Maguen Return
        useSkill(6683, true);
        break;
      case 1098: // Elite Maguen - Maguen Party Return
        useSkill(6684, true);
        break;
      case 1099: // All servitor attack
        activeChar
            .getServitors()
            .values()
            .forEach(
                s -> {
                  if (validateSummon(s, false)) {
                    if (s.canAttack(_ctrlPressed)) {
                      s.doAttack();
                    }
                  }
                });
        break;
      case 1100: // All servitor move to
        activeChar
            .getServitors()
            .values()
            .forEach(
                s -> {
                  if (validateSummon(s, false)) {
                    if ((target != null) && (s != target) && !s.isMovementDisabled()) {
                      s.setFollowStatus(false);
                      s.getAI()
                          .setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, target.getLocation());
                    }
                  }
                });
        break;
      case 1101: // All servitor stop
        activeChar
            .getServitors()
            .values()
            .forEach(
                summon -> {
                  if (validateSummon(summon, false)) {
                    summon.cancelAction();
                  }
                });
        break;
      case 1102: // Unsummon all servitors
        boolean canUnsummon = true;
        OUT:
        for (L2Summon s : activeChar.getServitors().values()) {
          if (validateSummon(s, false)) {
            if (s.isAttackingNow() || s.isInCombat()) {
              sendPacket(
                  SystemMessageId.A_SERVITOR_WHOM_IS_ENGAGED_IN_BATTLE_CANNOT_BE_DE_ACTIVATED);
              canUnsummon = false;
              break OUT;
            }
            s.unSummon(activeChar);
          }
        }
        if (canUnsummon) {
          activeChar
              .getServitors()
              .values()
              .stream()
              .forEach(
                  s -> {
                    s.unSummon(activeChar);
                  });
        }
        break;
      case 1103: // seems to be passive mode
        break;
      case 1104: // seems to be defend mode
        break;
      case 1106: // Cute Bear - Bear Claw
        useServitorsSkill(11278);
        break;
      case 1107: // Cute Bear - Bear Tumbling
        useServitorsSkill(11279);
        break;
      case 1108: // Saber Tooth Cougar- Cougar Bite
        useServitorsSkill(11280);
        break;
      case 1109: // Saber Tooth Cougar - Cougar Pounce
        useServitorsSkill(11281);
        break;
      case 1110: // Grim Reaper - Reaper Touch
        useServitorsSkill(11282);
        break;
      case 1111: // Grim Reaper - Reaper Power
        useServitorsSkill(11283);
        break;
      case 1113: // Golden Lion - Lion Roar
        useSkill(10051, false);
        break;
      case 1114: // Golden Lion - Lion Claw
        useSkill(10052, false);
        break;
      case 1115: // Golden Lion - Lion Dash
        useSkill(10053, false);
        break;
      case 1116: // Golden Lion - Lion Flame
        useSkill(10054, false);
        break;
      case 1117: // Thunder Hawk - Thunder Flight
        useSkill(10794, false);
        break;
      case 1118: // Thunder Hawk - Thunder Purity
        useSkill(10795, false);
        break;
      case 1120: // Thunder Hawk - Thunder Feather Blast
        useSkill(10797, false);
        break;
      case 1121: // Thunder Hawk - Thunder Sharp Claw
        useSkill(10798, false);
        break;
      case 1122: // Tree of Life - Blessing of Tree
        useServitorsSkill(11806);
        break;
      case 1124: // Wynn Kai the Cat - Feline Aggression
        useServitorsSkill(11323);
        break;
      case 1125: // Wynn Kai the Cat - Feline Stun
        useServitorsSkill(11324);
        break;
      case 1126: // Wynn Feline King - Feline Bite
        useServitorsSkill(11325);
        break;
      case 1127: // Wynn Feline King - Feline Pounce
        useServitorsSkill(11326);
        break;
      case 1128: // Wynn Feline Queen - Feline Touch
        useServitorsSkill(11327);
        break;
      case 1129: // Wynn Feline Queen - Feline Power
        useServitorsSkill(11328);
        break;
      case 1130: // Wynn Merrow - Unicorn's Aggression
        useServitorsSkill(11332);
        break;
      case 1131: // Wynn Merrow - Unicorn's Stun
        useServitorsSkill(11333);
        break;
      case 1132: // Wynn Magnus - Unicorn's Bite
        useServitorsSkill(11334);
        break;
      case 1133: // Wynn Magnus - Unicorn's Pounce
        useServitorsSkill(11335);
        break;
      case 1134: // Wynn Seraphim - Unicorn's Touch
        useServitorsSkill(11336);
        break;
      case 1135: // Wynn Seraphim - Unicorn's Power
        useServitorsSkill(11337);
        break;
      case 1136: // Wynn Nightshade - Phantom Aggression
        useServitorsSkill(11341);
        break;
      case 1137: // Wynn Nightshade - Phantom Stun
        useServitorsSkill(11342);
        break;
      case 1138: // Wynn Spectral Lord - Phantom Bite
        useServitorsSkill(11343);
        break;
      case 1139: // Wynn Spectral Lord - Phantom Pounce
        useServitorsSkill(11344);
        break;
      case 1140: // Wynn Soulless - Phantom Touch
        useServitorsSkill(11345);
        break;
      case 1141: // Wynn Soulless - Phantom Power
        useServitorsSkill(11346);
        break;
      case 1142: // Blood Panther - Panther Roar
        useServitorsSkill(10087);
        break;
      case 1143: // Blood Panther - Panther Rush
        useServitorsSkill(10088);
        break;
      case 5000: // Baby Rudolph - Reindeer Scratch
        useSkill(23155, true);
        break;
      case 5001: // Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum - Rosy Seduction
        useSkill(23167, true);
        break;
      case 5002: // Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum - Critical Seduction
        useSkill(23168, true);
        break;
      case 5003: // Hyum, Lapham, Hyum, Lapham - Thunder Bolt
        useSkill(5749, true);
        break;
      case 5004: // Hyum, Lapham, Hyum, Lapham - Flash
        useSkill(5750, true);
        break;
      case 5005: // Hyum, Lapham, Hyum, Lapham - Lightning Wave
        useSkill(5751, true);
        break;
      case 5006: // Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum, Deseloph, Hyum, Rekang, Lilias,
        // Lapham, Mafum - Buff Control
        useSkill(5771, true);
        break;
      case 5007: // Deseloph, Lilias, Deseloph, Lilias - Piercing Attack
        useSkill(6046, true);
        break;
      case 5008: // Deseloph, Lilias, Deseloph, Lilias - Spin Attack
        useSkill(6047, true);
        break;
      case 5009: // Deseloph, Lilias, Deseloph, Lilias - Smash
        useSkill(6048, true);
        break;
      case 5010: // Deseloph, Lilias, Deseloph, Lilias - Ignite
        useSkill(6049, true);
        break;
      case 5011: // Rekang, Mafum, Rekang, Mafum - Power Smash
        useSkill(6050, true);
        break;
      case 5012: // Rekang, Mafum, Rekang, Mafum - Energy Burst
        useSkill(6051, true);
        break;
      case 5013: // Rekang, Mafum, Rekang, Mafum - Shockwave
        useSkill(6052, true);
        break;
      case 5014: // Rekang, Mafum, Rekang, Mafum - Ignite
        useSkill(6053, true);
        break;
      case 5015: // Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum, Deseloph, Hyum, Rekang, Lilias,
        // Lapham, Mafum - Switch Stance
        useSkill(6054, true);
        break;
        // Social Packets
      case 12: // Greeting
        tryBroadcastSocial(2);
        break;
      case 13: // Victory
        tryBroadcastSocial(3);
        break;
      case 14: // Advance
        tryBroadcastSocial(4);
        break;
      case 24: // Yes
        tryBroadcastSocial(6);
        break;
      case 25: // No
        tryBroadcastSocial(5);
        break;
      case 26: // Bow
        tryBroadcastSocial(7);
        break;
      case 29: // Unaware
        tryBroadcastSocial(8);
        break;
      case 30: // Social Waiting
        tryBroadcastSocial(9);
        break;
      case 31: // Laugh
        tryBroadcastSocial(10);
        break;
      case 33: // Applaud
        tryBroadcastSocial(11);
        break;
      case 34: // Dance
        tryBroadcastSocial(12);
        break;
      case 35: // Sorrow
        tryBroadcastSocial(13);
        break;
      case 62: // Charm
        tryBroadcastSocial(14);
        break;
      case 66: // Shyness
        tryBroadcastSocial(15);
        break;
      case 87: // Propose
        tryBroadcastSocial(28);
        break;
      case 88: // Provoke
        tryBroadcastSocial(29);
        break;
      case 89: // Beauty Shop
        tryBroadcastSocial(30);
        activeChar.broadcastInfo();
        break;
      default:
        _log.warning(activeChar.getName() + ": unhandled action type " + _actionId);
        break;
    }
  }
  /**
   * Perform a couple social action.
   *
   * @param id the couple social action Id
   */
  private void useCoupleSocial(final int id) {
    final L2PcInstance requester = getActiveChar();
    if (requester == null) {
      return;
    }

    final L2Object target = requester.getTarget();
    if ((target == null) || !target.isPlayer()) {
      sendPacket(SystemMessageId.INVALID_TARGET);
      return;
    }

    final int distance = (int) requester.calculateDistance(target, false, false);
    if ((distance > 125) || (distance < 15) || (requester.getObjectId() == target.getObjectId())) {
      sendPacket(
          SystemMessageId
              .THE_REQUEST_CANNOT_BE_COMPLETED_BECAUSE_THE_TARGET_DOES_NOT_MEET_LOCATION_REQUIREMENTS);
      return;
    }

    SystemMessage sm;
    if (requester.isInStoreMode() || requester.isInCraftMode()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_IN_PRIVATE_STORE_MODE_OR_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(requester);
      sendPacket(sm);
      return;
    }

    if (requester.isInCombat()
        || requester.isInDuel()
        || AttackStanceTaskManager.getInstance().hasAttackStanceTask(requester)) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId.C1_IS_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(requester);
      sendPacket(sm);
      return;
    }

    if (requester.isFishing()) {
      sendPacket(SystemMessageId.YOU_CANNOT_DO_THAT_WHILE_FISHING);
      return;
    }

    if (requester.getReputation() < 0) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId.C1_IS_IN_A_CHAOTIC_STATE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(requester);
      sendPacket(sm);
      return;
    }

    if (requester.isInOlympiadMode()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_PARTICIPATING_IN_THE_OLYMPIAD_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(requester);
      sendPacket(sm);
      return;
    }

    if (requester.isInSiege()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId.C1_IS_IN_A_CASTLE_SIEGE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(requester);
      sendPacket(sm);
      return;
    }

    if (requester.isInHideoutSiege()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_PARTICIPATING_IN_A_CLAN_HALL_SIEGE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(requester);
      sendPacket(sm);
    }

    if (requester.isMounted()
        || requester.isFlyingMounted()
        || requester.isInBoat()
        || requester.isInAirShip()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_RIDING_A_SHIP_STEED_OR_STRIDER_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(requester);
      sendPacket(sm);
      return;
    }

    if (requester.isTransformed()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_CURRENTLY_TRANSFORMING_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(requester);
      sendPacket(sm);
      return;
    }

    if (requester.isAlikeDead()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId.C1_IS_CURRENTLY_DEAD_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(requester);
      sendPacket(sm);
      return;
    }

    // Checks for partner.
    final L2PcInstance partner = target.getActingPlayer();
    if (partner.isInStoreMode() || partner.isInCraftMode()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_IN_PRIVATE_STORE_MODE_OR_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.isInCombat()
        || partner.isInDuel()
        || AttackStanceTaskManager.getInstance().hasAttackStanceTask(partner)) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId.C1_IS_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.getMultiSociaAction() > 0) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_ALREADY_PARTICIPATING_IN_A_COUPLE_ACTION_AND_CANNOT_BE_REQUESTED_FOR_ANOTHER_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.isFishing()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId.C1_IS_FISHING_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.getReputation() < 0) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId.C1_IS_IN_A_CHAOTIC_STATE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.isInOlympiadMode()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_PARTICIPATING_IN_THE_OLYMPIAD_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.isInHideoutSiege()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_PARTICIPATING_IN_A_CLAN_HALL_SIEGE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.isInSiege()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId.C1_IS_IN_A_CASTLE_SIEGE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.isMounted()
        || partner.isFlyingMounted()
        || partner.isInBoat()
        || partner.isInAirShip()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_RIDING_A_SHIP_STEED_OR_STRIDER_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.isTeleporting()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_CURRENTLY_TELEPORTING_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.isTransformed()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId
                  .C1_IS_CURRENTLY_TRANSFORMING_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (partner.isAlikeDead()) {
      sm =
          SystemMessage.getSystemMessage(
              SystemMessageId.C1_IS_CURRENTLY_DEAD_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
      sm.addPcName(partner);
      sendPacket(sm);
      return;
    }

    if (requester.isAllSkillsDisabled() || partner.isAllSkillsDisabled()) {
      sendPacket(SystemMessageId.THE_COUPLE_ACTION_WAS_CANCELLED);
      return;
    }

    requester.setMultiSocialAction(id, partner.getObjectId());
    sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_REQUESTED_A_COUPLE_ACTION_WITH_C1);
    sm.addPcName(partner);
    sendPacket(sm);

    if ((requester.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)
        || (partner.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)) {
      final NextAction nextAction =
          new NextAction(
              CtrlEvent.EVT_ARRIVED,
              CtrlIntention.AI_INTENTION_MOVE_TO,
              () -> partner.sendPacket(new ExAskCoupleAction(requester.getObjectId(), id)));
      requester.getAI().setNextAction(nextAction);
      return;
    }

    if (requester.isCastingNow() || requester.isCastingSimultaneouslyNow()) {
      final NextAction nextAction =
          new NextAction(
              CtrlEvent.EVT_FINISH_CASTING,
              CtrlIntention.AI_INTENTION_CAST,
              () -> partner.sendPacket(new ExAskCoupleAction(requester.getObjectId(), id)));
      requester.getAI().setNextAction(nextAction);
      return;
    }

    partner.sendPacket(new ExAskCoupleAction(requester.getObjectId(), id));
  }
 @Override
 public boolean useAdminCommand(String command, L2PcInstance activeChar) {
   if (command.equals("admin_show_spawns")) {
     AdminHtml.showAdminHtml(activeChar, "spawns.htm");
   } else if (command.equalsIgnoreCase("admin_spawn_debug_menu")) {
     AdminHtml.showAdminHtml(activeChar, "spawns_debug.htm");
   } else if (command.startsWith("admin_spawn_debug_print")) {
     StringTokenizer st = new StringTokenizer(command, " ");
     L2Object target = activeChar.getTarget();
     if (target instanceof L2Npc) {
       try {
         st.nextToken();
         int type = Integer.parseInt(st.nextToken());
         printSpawn((L2Npc) target, type);
         if (command.contains("_menu")) {
           AdminHtml.showAdminHtml(activeChar, "spawns_debug.htm");
         }
       } catch (Exception e) {
       }
     } else {
       activeChar.sendPacket(SystemMessageId.INCORRECT_TARGET);
     }
   } else if (command.startsWith("admin_spawn_index")) {
     StringTokenizer st = new StringTokenizer(command, " ");
     try {
       st.nextToken();
       int level = Integer.parseInt(st.nextToken());
       int from = 0;
       try {
         from = Integer.parseInt(st.nextToken());
       } catch (NoSuchElementException nsee) {
       }
       showMonsters(activeChar, level, from);
     } catch (Exception e) {
       AdminHtml.showAdminHtml(activeChar, "spawns.htm");
     }
   } else if (command.equals("admin_show_npcs")) {
     AdminHtml.showAdminHtml(activeChar, "npcs.htm");
   } else if (command.startsWith("admin_npc_index")) {
     StringTokenizer st = new StringTokenizer(command, " ");
     try {
       st.nextToken();
       String letter = st.nextToken();
       int from = 0;
       try {
         from = Integer.parseInt(st.nextToken());
       } catch (NoSuchElementException nsee) {
       }
       showNpcs(activeChar, letter, from);
     } catch (Exception e) {
       AdminHtml.showAdminHtml(activeChar, "npcs.htm");
     }
   } else if (command.startsWith("admin_instance_spawns")) {
     StringTokenizer st = new StringTokenizer(command, " ");
     try {
       st.nextToken();
       int instance = Integer.parseInt(st.nextToken());
       if (instance >= 300000) {
         final StringBuilder html =
             StringUtil.startAppend(
                 500 + 1000,
                 "<html><table width=\"100%\"><tr><td width=45><button value=\"Main\" action=\"bypass -h admin_admin\" width=45 height=21 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td><td width=180><center>",
                 "<font color=\"LEVEL\">Spawns for " + String.valueOf(instance) + "</font>",
                 "</td><td width=45><button value=\"Back\" action=\"bypass -h admin_current_player\" width=45 height=21 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table><br>",
                 "<table width=\"100%\"><tr><td width=200>NpcName</td><td width=70>Action</td></tr>");
         int counter = 0;
         int skiped = 0;
         Instance inst = InstanceManager.getInstance().getInstance(instance);
         if (inst != null) {
           for (L2Npc npc : inst.getNpcs()) {
             if (!npc.isDead()) {
               // Only 50 because of client html limitation
               if (counter < 50) {
                 StringUtil.append(
                     html,
                     "<tr><td>" + npc.getName() + "</td><td>",
                     "<a action=\"bypass -h admin_move_to "
                         + npc.getX()
                         + " "
                         + npc.getY()
                         + " "
                         + npc.getZ()
                         + "\">Go</a>",
                     "</td></tr>");
                 counter++;
               } else {
                 skiped++;
               }
             }
           }
           StringUtil.append(
               html,
               "<tr><td>Skipped:</td><td>"
                   + String.valueOf(skiped)
                   + "</td></tr></table></body></html>");
           final NpcHtmlMessage ms = new NpcHtmlMessage();
           ms.setHtml(html.toString());
           activeChar.sendPacket(ms);
         } else {
           activeChar.sendMessage("Cannot find instance " + instance);
         }
       } else {
         activeChar.sendMessage("Invalid instance number.");
       }
     } catch (Exception e) {
       activeChar.sendMessage("Usage //instance_spawns <instance_number>");
     }
   } else if (command.startsWith("admin_unspawnall")) {
     Broadcast.toAllOnlinePlayers(
         SystemMessage.getSystemMessage(SystemMessageId.NPC_SERVER_NOT_OPERATING));
     RaidBossSpawnManager.getInstance().cleanUp();
     DayNightSpawnManager.getInstance().cleanUp();
     L2World.getInstance().deleteVisibleNpcSpawns();
     AdminTable.getInstance().broadcastMessageToGMs("NPC Unspawn completed!");
   } else if (command.startsWith("admin_spawnday")) {
     DayNightSpawnManager.getInstance().spawnDayCreatures();
   } else if (command.startsWith("admin_spawnnight")) {
     DayNightSpawnManager.getInstance().spawnNightCreatures();
   } else if (command.startsWith("admin_respawnall") || command.startsWith("admin_spawn_reload")) {
     // make sure all spawns are deleted
     RaidBossSpawnManager.getInstance().cleanUp();
     DayNightSpawnManager.getInstance().cleanUp();
     L2World.getInstance().deleteVisibleNpcSpawns();
     // now respawn all
     NpcData.getInstance().load();
     SpawnTable.getInstance().load();
     RaidBossSpawnManager.getInstance().load();
     AutoSpawnHandler.getInstance().reload();
     SevenSigns.getInstance().spawnSevenSignsNPC();
     QuestManager.getInstance().reloadAllScripts();
     AdminTable.getInstance().broadcastMessageToGMs("NPC Respawn completed!");
   } else if (command.startsWith("admin_spawn_monster") || command.startsWith("admin_spawn")) {
     StringTokenizer st = new StringTokenizer(command, " ");
     try {
       String cmd = st.nextToken();
       String id = st.nextToken();
       int respawnTime = 0;
       int mobCount = 1;
       if (st.hasMoreTokens()) {
         mobCount = Integer.parseInt(st.nextToken());
       }
       if (st.hasMoreTokens()) {
         respawnTime = Integer.parseInt(st.nextToken());
       }
       if (cmd.equalsIgnoreCase("admin_spawn_once")) {
         spawnMonster(activeChar, id, respawnTime, mobCount, false);
       } else {
         spawnMonster(activeChar, id, respawnTime, mobCount, true);
       }
     } catch (Exception e) { // Case of wrong or missing monster data
       AdminHtml.showAdminHtml(activeChar, "spawns.htm");
     }
   } else if (command.startsWith("admin_list_spawns")
       || command.startsWith("admin_list_positions")) {
     int npcId = 0;
     int teleportIndex = -1;
     try { // admin_list_spawns x[xxxx] x[xx]
       String[] params = command.split(" ");
       Pattern pattern = Pattern.compile("[0-9]*");
       Matcher regexp = pattern.matcher(params[1]);
       if (regexp.matches()) {
         npcId = Integer.parseInt(params[1]);
       } else {
         params[1] = params[1].replace('_', ' ');
         npcId = NpcData.getInstance().getTemplateByName(params[1]).getId();
       }
       if (params.length > 2) {
         teleportIndex = Integer.parseInt(params[2]);
       }
     } catch (Exception e) {
       activeChar.sendMessage("Command format is //list_spawns <npcId|npc_name> [tele_index]");
     }
     if (command.startsWith("admin_list_positions")) {
       findNPCInstances(activeChar, npcId, teleportIndex, true);
     } else {
       findNPCInstances(activeChar, npcId, teleportIndex, false);
     }
   }
   return true;
 }
  private void setEnchant(L2PcInstance activeChar, int ench, int armorType) {
    // get the target
    L2Object target = activeChar.getTarget();
    if (target == null) {
      target = activeChar;
    }
    L2PcInstance player = null;
    if (target instanceof L2PcInstance) {
      player = (L2PcInstance) target;
    } else {
      activeChar.sendPacket(SystemMessageId.INCORRECT_TARGET);
      return;
    }

    // now we need to find the equipped weapon of the targeted character...
    int curEnchant = 0; // display purposes only
    L2ItemInstance itemInstance = null;

    // only attempt to enchant if there is a weapon equipped
    L2ItemInstance parmorInstance = player.getInventory().getPaperdollItem(armorType);
    if ((parmorInstance != null) && (parmorInstance.getLocationSlot() == armorType)) {
      itemInstance = parmorInstance;
    }

    if (itemInstance != null) {
      curEnchant = itemInstance.getEnchantLevel();

      // set enchant value
      player.getInventory().unEquipItemInSlot(armorType);
      itemInstance.setEnchantLevel(ench);
      player.getInventory().equipItem(itemInstance);

      // send packets
      InventoryUpdate iu = new InventoryUpdate();
      iu.addModifiedItem(itemInstance);
      player.sendPacket(iu);
      player.broadcastPacket(new CharInfo(player));
      player.sendPacket(new UserInfo(player));
      player.broadcastPacket(new ExBrExtraUserInfo(player));

      // informations
      activeChar.sendMessage(
          "Changed enchantment of "
              + player.getName()
              + "'s "
              + itemInstance.getItem().getName()
              + " from "
              + curEnchant
              + " to "
              + ench
              + ".");
      player.sendMessage(
          "Admin has changed the enchantment of your "
              + itemInstance.getItem().getName()
              + " from "
              + curEnchant
              + " to "
              + ench
              + ".");
    }
  }
  @Override
  public boolean useAdminCommand(String command, L2PcInstance activeChar) {
    StringTokenizer st = new StringTokenizer(command, " ");
    command = st.nextToken(); // Get actual command

    // Get fort
    Fort fort = null;
    int fortId = 0;
    if (st.hasMoreTokens()) {
      fortId = Integer.parseInt(st.nextToken());
      fort = FortManager.getInstance().getFortById(fortId);
    }
    // Get fort
    if (((fort == null) || (fortId == 0))) {
      // No fort specified
      showFortSelectPage(activeChar);
    } else {
      L2Object target = activeChar.getTarget();
      L2PcInstance player = null;
      if (target instanceof L2PcInstance) {
        player = (L2PcInstance) target;
      }

      if (command.equalsIgnoreCase("admin_add_fortattacker")) {
        if (player == null) {
          activeChar.sendPacket(SystemMessageId.TARGET_IS_INCORRECT);
        } else {
          if (fort.getSiege().addAttacker(player, false) == 4) {
            final SystemMessage sm =
                SystemMessage.getSystemMessage(SystemMessageId.REGISTERED_TO_S1_FORTRESS_BATTLE);
            sm.addCastleId(fort.getResidenceId());
            player.sendPacket(sm);
          } else {
            player.sendMessage("During registering error occurred!");
          }
        }
      } else if (command.equalsIgnoreCase("admin_clear_fortsiege_list")) {
        fort.getSiege().clearSiegeClan();
      } else if (command.equalsIgnoreCase("admin_endfortsiege")) {
        fort.getSiege().endSiege();
      } else if (command.equalsIgnoreCase("admin_list_fortsiege_clans")) {
        activeChar.sendMessage("Not implemented yet.");
      } else if (command.equalsIgnoreCase("admin_setfort")) {
        if ((player == null) || (player.getClan() == null)) {
          activeChar.sendPacket(SystemMessageId.TARGET_IS_INCORRECT);
        } else {
          fort.endOfSiege(player.getClan());
        }
      } else if (command.equalsIgnoreCase("admin_removefort")) {
        L2Clan clan = fort.getOwnerClan();
        if (clan != null) {
          fort.removeOwner(true);
        } else {
          activeChar.sendMessage("Unable to remove fort");
        }
      } else if (command.equalsIgnoreCase("admin_spawn_fortdoors")) {
        fort.resetDoors();
      } else if (command.equalsIgnoreCase("admin_startfortsiege")) {
        fort.getSiege().startSiege();
      }

      showFortSiegePage(activeChar, fort);
    }
    return true;
  }
Beispiel #18
0
  @Override
  public void runImpl() {
    final L2PcInstance player = getClient().getActiveChar();
    if (player == null) {
      return;
    }

    if (!getClient().getFloodProtectors().getMultiSell().tryPerformAction("multisell choose")) {
      player.setMultiSell(null);
      return;
    }

    if ((_amount < 1) || (_amount > 5000)) {
      player.setMultiSell(null);
      return;
    }

    PreparedListContainer list = player.getMultiSell();
    if ((list == null) || (list.getListId() != _listId)) {
      player.setMultiSell(null);
      return;
    }

    final L2Npc npc = player.getLastFolkNPC();
    if (((npc != null) && !list.isNpcAllowed(npc.getId())) || ((npc == null) && list.isNpcOnly())) {
      player.setMultiSell(null);
      return;
    }

    if (!player.isGM() && (npc != null)) {
      if (!player.isInsideRadius(npc, INTERACTION_DISTANCE, true, false)
          || (player.getInstanceId() != npc.getInstanceId())) {
        player.setMultiSell(null);
        return;
      }
    }

    for (Entry entry : list.getEntries()) {
      if (entry.getEntryId() == _entryId) {
        if (!entry.isStackable() && (_amount > 1)) {
          _log.severe(
              "Character: "
                  + player.getName()
                  + " is trying to set amount > 1 on non-stackable multisell, id:"
                  + _listId
                  + ":"
                  + _entryId);
          player.setMultiSell(null);
          return;
        }

        final PcInventory inv = player.getInventory();

        int slots = 0;
        int weight = 0;
        for (Ingredient e : entry.getProducts()) {
          if (e.getItemId() < 0) {
            continue;
          }

          if (!e.isStackable()) {
            slots += e.getItemCount() * _amount;
          } else if (player.getInventory().getItemByItemId(e.getItemId()) == null) {
            slots++;
          }
          weight += e.getItemCount() * _amount * e.getWeight();
        }

        if (!inv.validateWeight(weight)) {
          player.sendPacket(SystemMessageId.WEIGHT_LIMIT_EXCEEDED);
          return;
        }

        if (!inv.validateCapacity(slots)) {
          player.sendPacket(SystemMessageId.SLOTS_FULL);
          return;
        }

        ArrayList<Ingredient> ingredientsList = new ArrayList<>(entry.getIngredients().size());
        // Generate a list of distinct ingredients and counts in order to check if the correct
        // item-counts
        // are possessed by the player
        boolean newIng;
        for (Ingredient e : entry.getIngredients()) {
          newIng = true;
          // at this point, the template has already been modified so that enchantments are properly
          // included
          // whenever they need to be applied. Uniqueness of items is thus judged by item id AND
          // enchantment level
          for (int i = ingredientsList.size(); --i >= 0; ) {
            Ingredient ex = ingredientsList.get(i);
            // if the item was already added in the list, merely increment the count
            // this happens if 1 list entry has the same ingredient twice (example 2 swords = 1
            // dual)
            if ((ex.getItemId() == e.getItemId())
                && (ex.getEnchantLevel() == e.getEnchantLevel())) {
              if ((ex.getItemCount() + e.getItemCount()) > Integer.MAX_VALUE) {
                player.sendPacket(SystemMessageId.YOU_HAVE_EXCEEDED_QUANTITY_THAT_CAN_BE_INPUTTED);
                return;
              }
              // two same ingredients, merge into one and replace old
              final Ingredient ing = ex.getCopy();
              ing.setItemCount(ex.getItemCount() + e.getItemCount());
              ingredientsList.set(i, ing);
              newIng = false;
              break;
            }
          }
          if (newIng) {
            // if it's a new ingredient, just store its info directly (item id, count, enchantment)
            ingredientsList.add(e);
          }
        }

        // now check if the player has sufficient items in the inventory to cover the ingredients'
        // expences
        for (Ingredient e : ingredientsList) {
          if ((e.getItemCount() * _amount) > Integer.MAX_VALUE) {
            player.sendPacket(SystemMessageId.YOU_HAVE_EXCEEDED_QUANTITY_THAT_CAN_BE_INPUTTED);
            return;
          }
          if (e.getItemId() < 0) {
            if (!MultisellData.hasSpecialIngredient(
                e.getItemId(), e.getItemCount() * _amount, player)) {
              return;
            }
          } else {
            // if this is not a list that maintains enchantment, check the count of all items that
            // have the given id.
            // otherwise, check only the count of items with exactly the needed enchantment level
            final long required =
                ((Config.ALT_BLACKSMITH_USE_RECIPES || !e.getMaintainIngredient())
                    ? (e.getItemCount() * _amount)
                    : e.getItemCount());
            if (inv.getInventoryItemCount(
                    e.getItemId(), list.getMaintainEnchantment() ? e.getEnchantLevel() : -1, false)
                < required) {
              SystemMessage sm =
                  SystemMessage.getSystemMessage(SystemMessageId.S2_UNIT_OF_THE_ITEM_S1_REQUIRED);
              sm.addItemName(e.getTemplate());
              sm.addLong(required);
              player.sendPacket(sm);
              return;
            }
          }
        }

        List<L2Augmentation> augmentation = new ArrayList<>();
        Elementals[] elemental = null;
        /** All ok, remove items and add final product */
        for (Ingredient e : entry.getIngredients()) {
          if (e.getItemId() < 0) {
            if (!MultisellData.takeSpecialIngredient(
                e.getItemId(), e.getItemCount() * _amount, player)) {
              return;
            }
          } else {
            L2ItemInstance itemToTake =
                inv.getItemByItemId(
                    e.getItemId()); // initialize and initial guess for the item to take.
            if (itemToTake
                == null) { // this is a cheat, transaction will be aborted and if any items already
                           // taken will not be returned back to inventory!
              _log.severe(
                  "Character: "
                      + player.getName()
                      + " is trying to cheat in multisell, id:"
                      + _listId
                      + ":"
                      + _entryId);
              player.setMultiSell(null);
              return;
            }

            // if (itemToTake.isEquipped())
            // {
            // this is a cheat, transaction will be aborted and if any items already taken will not
            // be returned back to inventory!
            // _log.severe("Character: " + player.getName() + " is trying to cheat in multisell,
            // exchanging equipped item, merchatnt id:" + merchant.getNpcId());
            // player.setMultiSell(null);
            // return;
            // }

            if (Config.ALT_BLACKSMITH_USE_RECIPES || !e.getMaintainIngredient()) {
              // if it's a stackable item, just reduce the amount from the first (only) instance
              // that is found in the inventory
              if (itemToTake.isStackable()) {
                if (!player.destroyItem(
                    "Multisell",
                    itemToTake.getObjectId(),
                    (e.getItemCount() * _amount),
                    player.getTarget(),
                    true)) {
                  player.setMultiSell(null);
                  return;
                }
              } else {
                // for non-stackable items, one of two scenaria are possible:
                // a) list maintains enchantment: get the instances that exactly match the requested
                // enchantment level
                // b) list does not maintain enchantment: get the instances with the LOWEST
                // enchantment level

                // a) if enchantment is maintained, then get a list of items that exactly match this
                // enchantment
                if (list.getMaintainEnchantment()) {
                  // loop through this list and remove (one by one) each item until the required
                  // amount is taken.
                  L2ItemInstance[] inventoryContents =
                      inv.getAllItemsByItemId(e.getItemId(), e.getEnchantLevel(), false);
                  for (int i = 0; i < (e.getItemCount() * _amount); i++) {
                    if (inventoryContents[i].isAugmented()) {
                      augmentation.add(inventoryContents[i].getAugmentation());
                    }
                    if (inventoryContents[i].getElementals() != null) {
                      elemental = inventoryContents[i].getElementals();
                    }
                    if (!player.destroyItem(
                        "Multisell",
                        inventoryContents[i].getObjectId(),
                        1,
                        player.getTarget(),
                        true)) {
                      player.setMultiSell(null);
                      return;
                    }
                  }
                } else
                // b) enchantment is not maintained. Get the instances with the LOWEST enchantment
                // level
                {
                  // NOTE: There are 2 ways to achieve the above goal.
                  // 1) Get all items that have the correct itemId, loop through them until the
                  // lowest enchantment
                  // level is found. Repeat all this for the next item until proper count of items
                  // is reached.
                  // 2) Get all items that have the correct itemId, sort them once based on
                  // enchantment level,
                  // and get the range of items that is necessary.
                  // Method 1 is faster for a small number of items to be exchanged.
                  // Method 2 is faster for large amounts.
                  //
                  // EXPLANATION:
                  // Worst case scenario for algorithm 1 will make it run in a number of cycles
                  // given by:
                  // m*(2n-m+1)/2 where m is the number of items to be exchanged and n is the total
                  // number of inventory items that have a matching id.
                  // With algorithm 2 (sort), sorting takes n*log(n) time and the choice is done in
                  // a single cycle
                  // for case b (just grab the m first items) or in linear time for case a (find the
                  // beginning of items
                  // with correct enchantment, index x, and take all items from x to x+m).
                  // Basically, whenever m > log(n) we have: m*(2n-m+1)/2 = (2nm-m*m+m)/2 >
                  // (2nlogn-logn*logn+logn)/2 = nlog(n) - log(n*n) + log(n) = nlog(n) + log(n/n*n)
                  // =
                  // nlog(n) + log(1/n) = nlog(n) - log(n) = (n-1)log(n)
                  // So for m < log(n) then m*(2n-m+1)/2 > (n-1)log(n) and m*(2n-m+1)/2 > nlog(n)
                  //
                  // IDEALLY:
                  // In order to best optimize the performance, choose which algorithm to run, based
                  // on whether 2^m > n
                  // if ( (2<<(e.getItemCount()// _amount)) < inventoryContents.length )
                  // // do Algorithm 1, no sorting
                  // else
                  // // do Algorithm 2, sorting
                  //
                  // CURRENT IMPLEMENTATION:
                  // In general, it is going to be very rare for a person to do a massive exchange
                  // of non-stackable items
                  // For this reason, we assume that algorithm 1 will always suffice and we keep
                  // things simple.
                  // If, in the future, it becomes necessary that we optimize, the above discussion
                  // should make it clear
                  // what optimization exactly is necessary (based on the comments under "IDEALLY").
                  //

                  // choice 1. Small number of items exchanged. No sorting.
                  for (int i = 1; i <= (e.getItemCount() * _amount); i++) {
                    L2ItemInstance[] inventoryContents =
                        inv.getAllItemsByItemId(e.getItemId(), false);

                    itemToTake = inventoryContents[0];
                    // get item with the LOWEST enchantment level from the inventory...
                    // +0 is lowest by default...
                    if (itemToTake.getEnchantLevel() > 0) {
                      for (L2ItemInstance item : inventoryContents) {
                        if (item.getEnchantLevel() < itemToTake.getEnchantLevel()) {
                          itemToTake = item;
                          // nothing will have enchantment less than 0. If a zero-enchanted
                          // item is found, just take it
                          if (itemToTake.getEnchantLevel() == 0) {
                            break;
                          }
                        }
                      }
                    }
                    if (!player.destroyItem(
                        "Multisell", itemToTake.getObjectId(), 1, player.getTarget(), true)) {
                      player.setMultiSell(null);
                      return;
                    }
                  }
                }
              }
            }
          }
        }

        // Generate the appropriate items
        for (Ingredient e : entry.getProducts()) {
          if (e.getItemId() < 0) {
            MultisellData.giveSpecialProduct(e.getItemId(), e.getItemCount() * _amount, player);
          } else {
            if (e.isStackable()) {
              inv.addItem(
                  "Multisell",
                  e.getItemId(),
                  e.getItemCount() * _amount,
                  player,
                  player.getTarget());
            } else {
              L2ItemInstance product = null;
              for (int i = 0; i < (e.getItemCount() * _amount); i++) {
                product = inv.addItem("Multisell", e.getItemId(), 1, player, player.getTarget());
                if ((product != null) && list.getMaintainEnchantment()) {
                  if (i < augmentation.size()) {
                    product.setAugmentation(
                        new L2Augmentation(augmentation.get(i).getAugmentationId()));
                  }
                  if (elemental != null) {
                    for (Elementals elm : elemental) {
                      product.setElementAttr(elm.getElement(), elm.getValue());
                    }
                  }
                  product.setEnchantLevel(e.getEnchantLevel());
                  product.updateDatabase();
                }
              }
            }
            // msg part
            SystemMessage sm;

            if ((e.getItemCount() * _amount) > 1) {
              sm = SystemMessage.getSystemMessage(SystemMessageId.EARNED_S2_S1_S);
              sm.addItemName(e.getItemId());
              sm.addLong(e.getItemCount() * _amount);
              player.sendPacket(sm);
            } else {
              if (list.getMaintainEnchantment() && (e.getEnchantLevel() > 0)) {
                sm = SystemMessage.getSystemMessage(SystemMessageId.ACQUIRED_S1_S2);
                sm.addLong(e.getEnchantLevel());
                sm.addItemName(e.getItemId());
              } else {
                sm = SystemMessage.getSystemMessage(SystemMessageId.EARNED_ITEM_S1);
                sm.addItemName(e.getItemId());
              }
              player.sendPacket(sm);
            }
          }
        }
        player.sendPacket(new ItemList(player, false));

        StatusUpdate su = new StatusUpdate(player);
        su.addAttribute(StatusUpdate.CUR_LOAD, player.getCurrentLoad());
        player.sendPacket(su);

        // finally, give the tax to the castle...
        if ((npc != null) && (entry.getTaxAmount() > 0)) {
          npc.getCastle().addToTreasury(entry.getTaxAmount() * _amount);
        }
        break;
      }
    }
  }