Package com.l2jfrozen.gameserver.ai

Source Code of com.l2jfrozen.gameserver.ai.AbstractAI$FollowTask

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* http://www.gnu.org/copyleft/gpl.html
*/
package com.l2jfrozen.gameserver.ai;

import static com.l2jfrozen.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
import static com.l2jfrozen.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
import static com.l2jfrozen.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;

import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.controllers.GameTimeController;
import com.l2jfrozen.gameserver.model.L2Attackable;
import com.l2jfrozen.gameserver.model.L2Character;
import com.l2jfrozen.gameserver.model.L2Object;
import com.l2jfrozen.gameserver.model.L2Skill;
import com.l2jfrozen.gameserver.model.L2Summon;
import com.l2jfrozen.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2PcInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2PlayableInstance;
import com.l2jfrozen.gameserver.model.actor.position.L2CharPosition;
import com.l2jfrozen.gameserver.model.extender.BaseExtender.EventType;
import com.l2jfrozen.gameserver.network.serverpackets.ActionFailed;
import com.l2jfrozen.gameserver.network.serverpackets.AutoAttackStart;
import com.l2jfrozen.gameserver.network.serverpackets.AutoAttackStop;
import com.l2jfrozen.gameserver.network.serverpackets.CharMoveToLocation;
import com.l2jfrozen.gameserver.network.serverpackets.Die;
import com.l2jfrozen.gameserver.network.serverpackets.MoveToLocationInVehicle;
import com.l2jfrozen.gameserver.network.serverpackets.MoveToPawn;
import com.l2jfrozen.gameserver.network.serverpackets.StopMove;
import com.l2jfrozen.gameserver.network.serverpackets.StopRotation;
import com.l2jfrozen.gameserver.taskmanager.AttackStanceTaskManager;
import com.l2jfrozen.gameserver.thread.ThreadPoolManager;

/**
* Mother class of all objects AI in the world.<BR>
* <BR>
* AbastractAI :<BR>
* <BR>
* <li>L2CharacterAI</li><BR>
* <BR>
*/
abstract class AbstractAI implements Ctrl
{

  protected static final Logger _log = Logger.getLogger(AbstractAI.class.getName());

  class FollowTask implements Runnable
  {
    protected int _range = 60;
    protected boolean newtask = true;

    public FollowTask()
    {
    //null
    }

    public FollowTask(int range)
    {
      _range = range;
    }

    @Override
    public void run()
    {
      try
      {
        if(_followTask == null)
          return;
       
        final L2Character follow = getFollowTarget();

        if(follow == null)
        {
          stopFollow();
          return;
        }
        if(!_actor.isInsideRadius(follow, _range, true, false))
        {
          moveToPawn(follow, _range);
        }
        else if(newtask)
        {
          newtask = false;
          _actor.broadcastPacket(new MoveToPawn(_actor, follow, _range));
        }
      }
      catch(Throwable t)
      {
        if(Config.ENABLE_ALL_EXCEPTIONS)
          t.printStackTrace();
       
        _log.log(Level.WARNING, "", t);
      }
    }
  }

  /** The character that this AI manages */
  protected final L2Character _actor;

  /** An accessor for private methods of the actor */
  protected final L2Character.AIAccessor _accessor;

  /** Current long-term intention */
  private CtrlIntention _intention = AI_INTENTION_IDLE;
  /** Current long-term intention parameter */
  private Object _intentionArg0 = null;
  /** Current long-term intention parameter */
  private Object _intentionArg1 = null;

  /** Flags about client's state, in order to know which messages to send */
  protected boolean _clientMoving;
  /** Flags about client's state, in order to know which messages to send */
  protected boolean _clientAutoAttacking;
  /** Flags about client's state, in order to know which messages to send */
  protected int _clientMovingToPawnOffset;

  /** Different targets this AI maintains */
  private L2Object _target;
  private L2Character _castTarget;
  private L2Character _attackTarget;
  private L2Character _followTarget;

 
  /** Diferent internal state flags */
  private int _moveToPawnTimeout;

  protected Future<?> _followTask = null;
  private static final int FOLLOW_INTERVAL = 1000;
  private static final int ATTACK_FOLLOW_INTERVAL = 500;

  /**
   * Constructor of AbstractAI.<BR>
   * <BR>
   *
   * @param accessor The AI accessor of the L2Character
   */
  protected AbstractAI(L2Character.AIAccessor accessor)
  {
    _accessor = accessor;

    // Get the L2Character managed by this Accessor AI
    _actor = accessor.getActor();
  }

  /**
   * Return the L2Character managed by this Accessor AI.<BR>
   * <BR>
   */
  @Override
  public L2Character getActor()
  {
    return _actor;
  }

  /**
   * Set the Intention of this AbstractAI.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method is USED by AI classes</B></FONT><BR>
   * <BR>
   * <B><U> Overriden in </U> : </B><BR>
   * <B>L2AttackableAI</B> : Create an AI Task executed every 1s (if necessary)<BR>
   * <B>L2PlayerAI</B> : Stores the current AI intention parameters to later restore it if necessary<BR>
   * <BR>
   *
   * @param intention The new Intention to set to the AI
   * @param arg0 The first parameter of the Intention
   * @param arg1 The second parameter of the Intention
   */
  public synchronized void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
  {
    /*
     if (Config.DEBUG)
     _log.warning("AbstractAI: changeIntention -> " + intention + " " + arg0 + " " + arg1);
     */

    _intention = intention;
    _intentionArg0 = arg0;
    _intentionArg1 = arg1;
  }

  /**
   * Launch the L2CharacterAI onIntention method corresponding to the new Intention.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Stop the FOLLOW mode if necessary</B></FONT><BR>
   * <BR>
   *
   * @param intention The new Intention to set to the AI
   */
  @Override
  public final void setIntention(CtrlIntention intention)
  {
    setIntention(intention, null, null);
  }

  /**
   * Launch the L2CharacterAI onIntention method corresponding to the new Intention.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Stop the FOLLOW mode if necessary</B></FONT><BR>
   * <BR>
   *
   * @param intention The new Intention to set to the AI
   * @param arg0 The first parameter of the Intention (optional target)
   */
  @Override
  public final void setIntention(CtrlIntention intention, Object arg0)
  {
    setIntention(intention, arg0, null);
  }

  /**
   * Launch the L2CharacterAI onIntention method corresponding to the new Intention.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Stop the FOLLOW mode if necessary</B></FONT><BR>
   * <BR>
   *
   * @param intention The new Intention to set to the AI
   * @param arg0 The first parameter of the Intention (optional target)
   * @param arg1 The second parameter of the Intention (optional target)
   */
  @Override
  public final void setIntention(CtrlIntention intention, Object arg0, Object arg1)
  {
    if(!_actor.isVisible() || !_actor.hasAI())
      return;

    /*
     if (Config.DEBUG)
     _log.warning("AbstractAI: setIntention -> " + intention + " " + arg0 + " " + arg1);
     */

    // Stop the follow mode if necessary
    if(intention != AI_INTENTION_FOLLOW && intention != AI_INTENTION_ATTACK)
    {
      stopFollow();
    }

    // Launch the onIntention method of the L2CharacterAI corresponding to the new Intention
    switch(intention)
    {
      case AI_INTENTION_IDLE:
        onIntentionIdle();
        break;
      case AI_INTENTION_ACTIVE:
        onIntentionActive();
        break;
      case AI_INTENTION_REST:
        onIntentionRest();
        break;
      case AI_INTENTION_ATTACK:
        onIntentionAttack((L2Character) arg0);
        break;
      case AI_INTENTION_CAST:
        onIntentionCast((L2Skill) arg0, (L2Object) arg1);
        break;
      case AI_INTENTION_MOVE_TO:
        onIntentionMoveTo((L2CharPosition) arg0);
        break;
      case AI_INTENTION_MOVE_TO_IN_A_BOAT:
        onIntentionMoveToInABoat((L2CharPosition) arg0, (L2CharPosition) arg1);
        break;
      case AI_INTENTION_FOLLOW:
        onIntentionFollow((L2Character) arg0);
        break;
      case AI_INTENTION_PICK_UP:
        onIntentionPickUp((L2Object) arg0);
        break;
      case AI_INTENTION_INTERACT:
        onIntentionInteract((L2Object) arg0);
        break;
    }
    _actor.fireEvent(EventType.SETINTENTION.name, new Object[]
    {
      intention
    });
  }

  /**
   * Launch the L2CharacterAI onEvt method corresponding to the Event.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : The current general intention won't be change (ex : If the character
   * attack and is stunned, he will attack again after the stunned periode)</B></FONT><BR>
   * <BR>
   *
   * @param evt The event whose the AI must be notified
   */
  @Override
  public final void notifyEvent(CtrlEvent evt)
  {
    notifyEvent(evt, null, null);
  }

  /**
   * Launch the L2CharacterAI onEvt method corresponding to the Event.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : The current general intention won't be change (ex : If the character
   * attack and is stunned, he will attack again after the stunned periode)</B></FONT><BR>
   * <BR>
   *
   * @param evt The event whose the AI must be notified
   * @param arg0 The first parameter of the Event (optional target)
   */
  @Override
  public final void notifyEvent(CtrlEvent evt, Object arg0)
  {
    notifyEvent(evt, arg0, null);
  }

  /**
   * Launch the L2CharacterAI onEvt method corresponding to the Event.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : The current general intention won't be change (ex : If the character
   * attack and is stunned, he will attack again after the stunned periode)</B></FONT><BR>
   * <BR>
   *
   * @param evt The event whose the AI must be notified
   * @param arg0 The first parameter of the Event (optional target)
   * @param arg1 The second parameter of the Event (optional target)
   */
  @Override
  public final void notifyEvent(CtrlEvent evt, Object arg0, Object arg1)
  {
    if(!_actor.isVisible() || !_actor.hasAI() || (_actor instanceof L2PcInstance && ((L2PcInstance)_actor).isOffline()))
      return;

    /*
     if (Config.DEBUG)
     _log.warning("AbstractAI: notifyEvent -> " + evt + " " + arg0 + " " + arg1);
     */

    switch(evt)
    {
      case EVT_THINK:
        onEvtThink();
        break;
      case EVT_ATTACKED:
        onEvtAttacked((L2Character) arg0);
        break;
      case EVT_AGGRESSION:
        onEvtAggression((L2Character) arg0, ((Number) arg1).intValue());
        break;
      case EVT_STUNNED:
        onEvtStunned((L2Character) arg0);
        break;
      case EVT_SLEEPING:
        onEvtSleeping((L2Character) arg0);
        break;
      case EVT_ROOTED:
        onEvtRooted((L2Character) arg0);
        break;
      case EVT_CONFUSED:
        onEvtConfused((L2Character) arg0);
        break;
      case EVT_MUTED:
        onEvtMuted((L2Character) arg0);
        break;
      case EVT_READY_TO_ACT:
        onEvtReadyToAct();
        break;
      case EVT_USER_CMD:
        onEvtUserCmd(arg0, arg1);
        break;
      case EVT_ARRIVED:
        onEvtArrived();
        break;
      case EVT_ARRIVED_REVALIDATE:
        onEvtArrivedRevalidate();
        break;
      case EVT_ARRIVED_BLOCKED:
        onEvtArrivedBlocked((L2CharPosition) arg0);
        break;
      case EVT_FORGET_OBJECT:
        onEvtForgetObject((L2Object) arg0);
        break;
      case EVT_CANCEL:
        onEvtCancel();
        break;
      case EVT_DEAD:
        onEvtDead();
        break;
      case EVT_FAKE_DEATH:
        onEvtFakeDeath();
        break;
      case EVT_FINISH_CASTING:
        onEvtFinishCasting();
        break;
    }
  }

  protected abstract void onIntentionIdle();

  protected abstract void onIntentionActive();

  protected abstract void onIntentionRest();

  protected abstract void onIntentionAttack(L2Character target);

  protected abstract void onIntentionCast(L2Skill skill, L2Object target);

  protected abstract void onIntentionMoveTo(L2CharPosition destination);

  protected abstract void onIntentionMoveToInABoat(L2CharPosition destination, L2CharPosition origin);

  protected abstract void onIntentionFollow(L2Character target);

  protected abstract void onIntentionPickUp(L2Object item);

  protected abstract void onIntentionInteract(L2Object object);

  protected abstract void onEvtThink();

  protected abstract void onEvtAttacked(L2Character attacker);

  protected abstract void onEvtAggression(L2Character target, int aggro);

  protected abstract void onEvtStunned(L2Character attacker);

  protected abstract void onEvtSleeping(L2Character attacker);

  protected abstract void onEvtRooted(L2Character attacker);

  protected abstract void onEvtConfused(L2Character attacker);

  protected abstract void onEvtMuted(L2Character attacker);

  protected abstract void onEvtReadyToAct();

  protected abstract void onEvtUserCmd(Object arg0, Object arg1);

  protected abstract void onEvtArrived();

  protected abstract void onEvtArrivedRevalidate();

  protected abstract void onEvtArrivedBlocked(L2CharPosition blocked_at_pos);

  protected abstract void onEvtForgetObject(L2Object object);

  protected abstract void onEvtCancel();

  protected abstract void onEvtDead();

  protected abstract void onEvtFakeDeath();

  protected abstract void onEvtFinishCasting();

  /**
   * Cancel action client side by sending Server->Client packet ActionFailed to the L2PcInstance actor.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
   * <BR>
   */
  protected void clientActionFailed()
  {
    if(_actor instanceof L2PcInstance)
    {
      _actor.sendPacket(ActionFailed.STATIC_PACKET);
    }
  }

  /**
   * Move the actor to Pawn server side AND client side by sending Server->Client packet MoveToPawn
   * <I>(broadcast)</I>.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
   * <BR>
   * @param pawn
   * @param offset
   */
  public void moveToPawn(L2Object pawn, int offset)
  {
    // Chek if actor can move
    if(!_actor.isMovementDisabled())
    {
      if(offset < 10)
      {
        offset = 10;
      }

      // prevent possible extra calls to this function (there is none?),
      // also don't send movetopawn packets too often
      boolean sendPacket = true;
      if(_clientMoving && getTarget() == pawn)
      {
        if(_clientMovingToPawnOffset == offset)
        {
          if(GameTimeController.getGameTicks() < _moveToPawnTimeout)
            return;

          sendPacket = false;
        }
        else if(_actor.isOnGeodataPath())
        {
          // minimum time to calculate new route is 2 seconds
          if(GameTimeController.getGameTicks() < _moveToPawnTimeout + 10)
            return;
        }
      }

      // Set AI movement data
      _clientMoving = true;
      _clientMovingToPawnOffset = offset;
     
      setTarget(pawn);
     
      _moveToPawnTimeout = GameTimeController.getGameTicks();
      _moveToPawnTimeout += /*1000*/200 / GameTimeController.MILLIS_IN_TICK;

      if(pawn == null || _accessor == null)
        return;

      // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
      _accessor.moveTo(pawn.getX(), pawn.getY(), pawn.getZ(), offset);

      if(!_actor.isMoving())
      {
        _actor.sendPacket(ActionFailed.STATIC_PACKET);
        return;
      }

      // Send a Server->Client packet MoveToPawn/CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
      if(pawn instanceof L2Character)
      {
        if(_actor.isOnGeodataPath())
        {
          _actor.broadcastPacket(new CharMoveToLocation(_actor));
          _clientMovingToPawnOffset = 0;
        }
        else if(sendPacket)
        {
          _actor.broadcastPacket(new MoveToPawn(_actor, (L2Character) pawn, offset));
        }
      }
      else
      {
        _actor.broadcastPacket(new CharMoveToLocation(_actor));
      }
    }
    else
    {
      _actor.sendPacket(ActionFailed.STATIC_PACKET);
    }
  }

  /**
   * Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet
   * CharMoveToLocation <I>(broadcast)</I>.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
   * <BR>
   * @param x
   * @param y
   * @param z
   */
  public void moveTo(int x, int y, int z)
  {
    // Chek if actor can move
    if(!_actor.isMovementDisabled())
    {
      // Set AI movement data
      _clientMoving = true;
      _clientMovingToPawnOffset = 0;

      // Calculate movement data for a move to location action and add the actor to movingObjects of GameTimeController
      _accessor.moveTo(x, y, z);

      // Send a Server->Client packet CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
      CharMoveToLocation msg = new CharMoveToLocation(_actor);
      _actor.broadcastPacket(msg);
      msg = null;

    }
    else
    {
      _actor.sendPacket(ActionFailed.STATIC_PACKET);
    }
  }

  protected void moveToInABoat(L2CharPosition destination, L2CharPosition origin)
  {
    // Chek if actor can move
    if(!_actor.isMovementDisabled())
    {
      // Send a Server->Client packet CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
      //CharMoveToLocation msg = new CharMoveToLocation(_actor);
      if(((L2PcInstance) _actor).getBoat() != null)
      {
        MoveToLocationInVehicle msg = new MoveToLocationInVehicle(_actor, destination, origin);
        _actor.broadcastPacket(msg);
        msg = null;
      }

    }
    else
    {
      _actor.sendPacket(ActionFailed.STATIC_PACKET);
    }
  }

  /**
   * Stop the actor movement server side AND client side by sending Server->Client packet StopMove/StopRotation
   * <I>(broadcast)</I>.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
   * <BR>
   * @param pos
   */
  protected void clientStopMoving(L2CharPosition pos)
  {
    /*
    if (true && _actor instanceof L2PcInstance){
      _log.warning("clientStopMoving();");
      Thread.dumpStack();
    }
    */

    // Stop movement of the L2Character
    if(_actor.isMoving())
    {
      _accessor.stopMove(pos);
    }

    _clientMovingToPawnOffset = 0;

    if(_clientMoving || pos != null)
    {
      _clientMoving = false;

      // Send a Server->Client packet StopMove to the actor and all L2PcInstance in its _knownPlayers
      StopMove msg = new StopMove(_actor);
      _actor.broadcastPacket(msg);
      msg = null;

      if(pos != null)
      {
        // Send a Server->Client packet StopRotation to the actor and all L2PcInstance in its _knownPlayers
        StopRotation sr = new StopRotation(_actor, pos.heading, 0);
        _actor.sendPacket(sr);
        _actor.broadcastPacket(sr);
        sr = null;
      }
    }
  }

  // Client has already arrived to target, no need to force StopMove packet
  protected void clientStoppedMoving()
  {
    if(_clientMovingToPawnOffset > 0) // movetoPawn needs to be stopped
    {
      _clientMovingToPawnOffset = 0;
      StopMove msg = new StopMove(_actor);
      _actor.broadcastPacket(msg);
      msg = null;
    }
    _clientMoving = false;
  }

  /**
   * Start the actor Auto Attack client side by sending Server->Client packet AutoAttackStart <I>(broadcast)</I>.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
   * <BR>
   */
  /*
  public void clientStartAutoAttack()
  {
    if(!isAutoAttacking())
    {
      // Send a Server->Client packet AutoAttackStart to the actor and all L2PcInstance in its _knownPlayers
      _actor.broadcastPacket(new AutoAttackStart(_actor.getObjectId()));
      setAutoAttacking(true);
    }
    AttackStanceTaskManager.getInstance().addAttackStanceTask(_actor);
  }
  */

  /**
   * Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop <I>(broadcast)</I>.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
   * <BR>
   */
  /*
  public void clientStopAutoAttack()
  {
    if(_actor instanceof L2PcInstance)
    {
      if(!AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor) && isAutoAttacking())
      {
        AttackStanceTaskManager.getInstance().addAttackStanceTask(_actor);
      }
    }
    else if(isAutoAttacking())
    {
      _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
    }
    setAutoAttacking(false);
  }
  */
  /**
   * Start the actor Auto Attack client side by sending Server->Client packet AutoAttackStart <I>(broadcast)</I>.<BR><BR>
   *
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
   *
   */
  public void clientStartAutoAttack()
  {
    if(((_actor instanceof L2NpcInstance
      && !(_actor instanceof L2Attackable))
      && !(_actor instanceof L2PlayableInstance))){
      return;
    }
   
    if (_actor instanceof L2Summon)
    {
      L2Summon summon = (L2Summon) _actor;
      if (summon.getOwner() != null)
        summon.getOwner().getAI().clientStartAutoAttack();
      return;
    }
    if (!isAutoAttacking())
    {
      if (_actor instanceof L2PcInstance && ((L2PcInstance)_actor).getPet() != null)
        ((L2PcInstance)_actor).getPet().broadcastPacket(new AutoAttackStart(((L2PcInstance)_actor).getPet().getObjectId()));
      // Send a Server->Client packet AutoAttackStart to the actor and all L2PcInstance in its _knownPlayers
      _actor.broadcastPacket(new AutoAttackStart(_actor.getObjectId()));
      setAutoAttacking(true);
    }
    AttackStanceTaskManager.getInstance().addAttackStanceTask(_actor);
  }
 
  /**
   * Stop the actor auto-attack client side by sending Server->Client packet AutoAttackStop <I>(broadcast)</I>.<BR><BR>
   *
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR><BR>
   *
   */
  public void clientStopAutoAttack()
  {
    if (_actor instanceof L2Summon)
    {
      L2Summon summon = (L2Summon) _actor;
      if (summon.getOwner() != null)
        summon.getOwner().getAI().clientStopAutoAttack();
      return;
    }
   
    final boolean isAutoAttacking = isAutoAttacking();
   
    if (_actor instanceof L2PcInstance)
    {
      if (!AttackStanceTaskManager.getInstance().getAttackStanceTask(_actor) && isAutoAttacking)
        AttackStanceTaskManager.getInstance().addAttackStanceTask(_actor);
    }
    else if (isAutoAttacking)
    {
      _actor.broadcastPacket(new AutoAttackStop(_actor.getObjectId()));
      setAutoAttacking(false);
    }
  }
 

  /**
   * Kill the actor client side by sending Server->Client packet AutoAttackStop, StopMove/StopRotation, Die
   * <I>(broadcast)</I>.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
   * <BR>
   */
  protected void clientNotifyDead()
  {
    // Send a Server->Client packet Die to the actor and all L2PcInstance in its _knownPlayers
    Die msg = new Die(_actor);
    _actor.broadcastPacket(msg);
    msg = null;

    // Init AI
    setIntention(AI_INTENTION_IDLE);
    setTarget(null);
    setAttackTarget(null);
    setCastTarget(null);
   
    // Cancel the follow task if necessary
    stopFollow();
  }

  /**
   * Update the state of this actor client side by sending Server->Client packet MoveToPawn/CharMoveToLocation and
   * AutoAttackStart to the L2PcInstance player.<BR>
   * <BR>
   * <FONT COLOR=#FF0000><B> <U>Caution</U> : Low level function, used by AI subclasses</B></FONT><BR>
   * <BR>
   *
   * @param player The L2PcIstance to notify with state of this L2Character
   */
  public void describeStateToPlayer(L2PcInstance player)
  {
    if(_clientMoving)
    {
      final L2Character follow = getFollowTarget();
     
      if(_clientMovingToPawnOffset != 0 &&  follow!= null)
      {
        // Send a Server->Client packet MoveToPawn to the actor and all L2PcInstance in its _knownPlayers
        MoveToPawn msg = new MoveToPawn(_actor, follow, _clientMovingToPawnOffset);
        player.sendPacket(msg);
        msg = null;
      }
      else
      {
        // Send a Server->Client packet CharMoveToLocation to the actor and all L2PcInstance in its _knownPlayers
        CharMoveToLocation msg = new CharMoveToLocation(_actor);
        player.sendPacket(msg);
        msg = null;
      }
    }
  }

  /**
   * Create and Launch an AI Follow Task to execute every 1s.<BR>
   * <BR>
   *
   * @param target The L2Character to follow
   */
  public synchronized void startFollow(L2Character target)
  {
    if(_followTask != null)
    {
      _followTask.cancel(false);
      _followTask = null;
    }

    // Create and Launch an AI Follow Task to execute every 1s
    _followTarget = target;
    _followTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new FollowTask(), 5, FOLLOW_INTERVAL);
  }

  /**
   * Create and Launch an AI Follow Task to execute every 0.5s, following at specified range.<BR>
   * <BR>
   *
   * @param target The L2Character to follow
   * @param range
   */
  public synchronized void startFollow(L2Character target, int range)
  {
    if(_followTask != null)
    {
      _followTask.cancel(false);
      _followTask = null;
    }

    _followTarget = target;
    _followTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new FollowTask(range), 5, ATTACK_FOLLOW_INTERVAL);
  }

  /**
   * Stop an AI Follow Task.<BR>
   * <BR>
   */
  public synchronized void stopFollow()
  {
    if(_followTask != null)
    {
      // Stop the Follow Task
      _followTask.cancel(false);
      _followTask = null;
    }
    _followTarget = null;
  }

  protected synchronized L2Character getFollowTarget()
  {
    return _followTarget;
  }

  protected synchronized L2Object getTarget()
  {
    return _target;
  }

  protected synchronized void setTarget(L2Object target)
  {
    _target = target;
  }
 
  protected synchronized void setCastTarget(L2Character target)
  {
    _castTarget = target;
  }

  /**
   * @return the current cast target.
   */
  public synchronized L2Character getCastTarget()
  {
    return _castTarget;
  }

  protected synchronized void setAttackTarget(L2Character target)
  {
    _attackTarget = target;
  }

  /**
   * Return current attack target.<BR>
   * <BR>
   */
  @Override
  public synchronized L2Character getAttackTarget()
  {
    return _attackTarget;
  }

  public synchronized  boolean isAutoAttacking()
  {
    return _clientAutoAttacking;
  }

  public synchronized void setAutoAttacking(boolean isAutoAttacking)
  {
    _clientAutoAttacking = isAutoAttacking;
  }

 
  /**
   * @return the _intentionArg0
   */
  public synchronized Object get_intentionArg0()
  {
    return _intentionArg0;
  }

  /**
   * @param _intentionArg0 the _intentionArg0 to set
   */
  public synchronized void set_intentionArg0(Object _intentionArg0)
  {
    this._intentionArg0 = _intentionArg0;
  }

  /**
   * @return the _intentionArg1
   */
  public synchronized Object get_intentionArg1()
  {
    return _intentionArg1;
  }

  /**
   * @param _intentionArg1 the _intentionArg1 to set
   */
  public synchronized void set_intentionArg1(Object _intentionArg1)
  {
    this._intentionArg1 = _intentionArg1;
  }

  /**
   * Return the current Intention.<BR>
   * <BR>
   */
  @Override
  public synchronized CtrlIntention getIntention()
  {
    return _intention;
  }

 
}
TOP

Related Classes of com.l2jfrozen.gameserver.ai.AbstractAI$FollowTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.