
06.04.2016, 03:37
|
|
Участник форума
Регистрация: 05.04.2016
Сообщений: 222
С нами:
5318817
Репутация:
0
|
|
PlayableAI.java
Сообщение от Спойлер
PHP:
Код:
package l2p.gameserver.ai;
import l2p.commons.threading.RunnableImpl;
import l2p.gameserver.ThreadPoolManager;
import l2p.gameserver.geodata.GeoEngine;
import l2p.gameserver.model.Creature;
import l2p.gameserver.model.GameObject;
import l2p.gameserver.model.Playable;
import l2p.gameserver.model.Player;
import l2p.gameserver.model.Skill;
import l2p.gameserver.model.Skill.NextAction;
import l2p.gameserver.model.Skill.SkillType;
import l2p.gameserver.model.Summon;
import l2p.gameserver.serverpackets.MyTargetSelected;
import l2p.gameserver.serverpackets.components.SystemMsg;
import l2p.gameserver.utils.Location;
import java.util.concurrent.ScheduledFuture;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
public class PlayableAI extends CharacterAI
{
private volatile int thinking = 0; // to prevent recursive thinking
protected Object _intention_arg0 = null, _intention_arg1 = null;
protected Skill _skill;
private nextAction _nextAction;
private Object _nextAction_arg0;
private Object _nextAction_arg1;
private boolean _nextAction_arg2;
private boolean _nextAction_arg3;
protected boolean _forceUse;
private boolean _dontMove;
private ScheduledFuture
_followTask;
public PlayableAI(Playable actor)
{
super(actor);
}
public enum nextAction
{
ATTACK,
CAST,
MOVE,
REST,
PICKUP,
INTERACT
}
@Override
public void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
{
super.changeIntention(intention, arg0, arg1);
_intention_arg0 = arg0;
_intention_arg1 = arg1;
}
@Override
public void setIntention(CtrlIntention intention, Object arg0, Object arg1)
{
_intention_arg0 = null;
_intention_arg1 = null;
super.setIntention(intention, arg0, arg1);
}
@Override
protected void onIntentionCast(Skill skill, Creature target)
{
_skill = skill;
super.onIntentionCast(skill, target);
}
@Override
public void setNextAction(nextAction action, Object arg0, Object arg1, boolean arg2, boolean arg3)
{
_nextAction = action;
_nextAction_arg0 = arg0;
_nextAction_arg1 = arg1;
_nextAction_arg2 = arg2;
_nextAction_arg3 = arg3;
}
public boolean setNextIntention()
{
nextAction nextAction = _nextAction;
Object nextAction_arg0 = _nextAction_arg0;
Object nextAction_arg1 = _nextAction_arg1;
boolean nextAction_arg2 = _nextAction_arg2;
boolean nextAction_arg3 = _nextAction_arg3;
Playable actor = getActor();
if(nextAction == null || actor.isActionsDisabled())
return false;
Skill skill;
Creature target;
GameObject object;
switch(nextAction)
{
case ATTACK:
if(nextAction_arg0 == null)
return false;
target = (Creature) nextAction_arg0;
_forceUse = nextAction_arg2;
_dontMove = nextAction_arg3;
clearNextAction();
setIntention(AI_INTENTION_ATTACK, target);
break;
case CAST:
if(nextAction_arg0 == null || nextAction_arg1 == null)
return false;
skill = (Skill) nextAction_arg0;
target = (Creature) nextAction_arg1;
_forceUse = nextAction_arg2;
_dontMove = nextAction_arg3;
clearNextAction();
if(!skill.checkCondition(actor, target, _forceUse, _dontMove, true))
{
if(skill.getNextAction() == NextAction.ATTACK && !actor.equals(target))
{
setNextAction(PlayableAI.nextAction.ATTACK, target, null, _forceUse, false);
return setNextIntention();
}
return false;
}
setIntention(AI_INTENTION_CAST, skill, target);
break;
case MOVE:
if(nextAction_arg0 == null || nextAction_arg1 == null)
return false;
Location loc = (Location) nextAction_arg0;
Integer offset = (Integer) nextAction_arg1;
clearNextAction();
actor.moveToLocation(loc, offset, nextAction_arg2);
break;
case REST:
actor.sitDown(null);
break;
case INTERACT:
if(nextAction_arg0 == null)
return false;
object = (GameObject) nextAction_arg0;
clearNextAction();
onIntentionInteract(object);
break;
case PICKUP:
if(nextAction_arg0 == null)
return false;
object = (GameObject) nextAction_arg0;
clearNextAction();
onIntentionPickUp(object);
break;
default:
return false;
}
return true;
}
@Override
public void clearNextAction()
{
_nextAction = null;
_nextAction_arg0 = null;
_nextAction_arg1 = null;
_nextAction_arg2 = false;
_nextAction_arg3 = false;
}
@Override
protected void onEvtFinishCasting()
{
if(!setNextIntention())
setIntention(AI_INTENTION_ACTIVE);
}
@Override
protected void onEvtReadyToAct()
{
if(!setNextIntention())
onEvtThink();
}
@Override
protected void onEvtArrived()
{
if(!setNextIntention())
if(getIntention() == AI_INTENTION_INTERACT || getIntention() == AI_INTENTION_PICK_UP)
onEvtThink();
else
changeIntention(AI_INTENTION_ACTIVE, null, null);
}
@Override
protected void onEvtArrivedTarget()
{
switch(getIntention())
{
case AI_INTENTION_ATTACK:
thinkAttack(false);
break;
case AI_INTENTION_CAST:
thinkCast(false);
break;
case AI_INTENTION_FOLLOW:
thinkFollow();
break;
default:
onEvtThink();
break;
}
}
@Override
protected final void onEvtThink()
{
Playable actor = getActor();
if(actor.isActionsDisabled())
return;
try
{
if(thinking++ > 1)
return;
switch(getIntention())
{
case AI_INTENTION_ACTIVE:
thinkActive();
break;
case AI_INTENTION_ATTACK:
thinkAttack(true);
break;
case AI_INTENTION_CAST:
thinkCast(true);
break;
case AI_INTENTION_PICK_UP:
thinkPickUp();
break;
case AI_INTENTION_INTERACT:
thinkInteract();
break;
case AI_INTENTION_FOLLOW:
thinkFollow();
break;
}
}
catch(Exception e)
{
_log.error("Unexpected error in PlayableAI.onEvtThink()", e);
}
finally
{
thinking--;
}
}
protected void thinkActive()
{
}
protected void thinkFollow()
{
Playable actor = getActor();
Creature target = (Creature) _intention_arg0;
Integer offset = (Integer) _intention_arg1;
//Находимся слишком далеко цели, либо цель не пригодна для следования
if(target == null || target.isAlikeDead() || actor.getDistance(target) > 4000 || offset == null)
{
clientActionFailed();
return;
}
//Уже следуем за этой целью
if(actor.isFollow && actor.getFollowTarget() == target)
{
clientActionFailed();
return;
}
//Находимся достаточно близко или не можем двигаться - побежим потом ?
if(actor.isInRange(target, offset + 20) || actor.isMovementDisabled())
clientActionFailed();
if(_followTask != null)
{
_followTask.cancel(false);
_followTask = null;
}
_followTask = ThreadPoolManager.getInstance().schedule(new ThinkFollow(), 250L);
}
protected class ThinkFollow extends RunnableImpl
{
@Override
public void runImpl() throws Exception
{
Playable actor = getActor();
if(getIntention() != AI_INTENTION_FOLLOW)
{
// Если пет прекратил преследование, меняем статус, чтобы не пришлось щелкать на кнопку следования 2 раза.
if((actor.isPet() || actor.isSummon()) && getIntention() == AI_INTENTION_ACTIVE)
((Summon) actor).setFollowMode(false);
return;
}
Creature target = (Creature) _intention_arg0;
int offset = _intention_arg1 instanceof Integer ? (Integer) _intention_arg1 : 0;
if(target == null || !target.isVisible() || target.isAlikeDead() || actor.getDistance(target) > 4000)
{
setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
return;
}
Player player = actor.getPlayer();
if(player == null || player.isLogoutStarted() || (actor.isPet() || actor.isSummon()) && player.getPet() != actor)
{
setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
return;
}
if(!actor.isInRange(target, offset + 20) && (!actor.isFollow || actor.getFollowTarget() != target))
actor.followToCharacter(target, offset, false);
_followTask = ThreadPoolManager.getInstance().schedule(this, 250L);
}
}
protected class ExecuteFollow extends RunnableImpl
{
private Creature _target;
private int _range;
public ExecuteFollow(Creature target, int range)
{
_target = target;
_range = range;
}
@Override
public void runImpl()
{
if(_target.isDoor())
_actor.moveToLocation(_target.getLoc(), 40, true);
else
_actor.followToCharacter(_target, _range, true);
}
}
@Override
protected void onIntentionInteract(GameObject object)
{
Playable actor = getActor();
if(actor.isActionsDisabled())
{
setNextAction(nextAction.INTERACT, object, null, false, false);
clientActionFailed();
return;
}
clearNextAction();
changeIntention(AI_INTENTION_INTERACT, object, null);
onEvtThink();
}
protected void thinkInteract()
{
Playable actor = getActor();
GameObject target = (GameObject) _intention_arg0;
if(target == null)
{
setIntention(AI_INTENTION_ACTIVE);
return;
}
int range = (int) (Math.max(30, actor.getMinDistance(target)) + 20);
if(actor.isInRangeZ(target, range))
{
if(actor.isPlayer())
((Player) actor).doInteract(target);
setIntention(AI_INTENTION_ACTIVE);
}
else
{
actor.moveToLocation(target.getLoc(), 40, true);
setNextAction(nextAction.INTERACT, target, null, false, false);
}
}
@Override
protected void onIntentionPickUp(GameObject object)
{
Playable actor = getActor();
if(actor.isActionsDisabled())
{
setNextAction(nextAction.PICKUP, object, null, false, false);
clientActionFailed();
return;
}
clearNextAction();
changeIntention(AI_INTENTION_PICK_UP, object, null);
onEvtThink();
}
protected void thinkPickUp()
{
final Playable actor = getActor();
final GameObject target = (GameObject) _intention_arg0;
if(target == null)
{
setIntention(AI_INTENTION_ACTIVE);
return;
}
if(actor.isInRange(target, 30) && Math.abs(actor.getZ() - target.getZ()) 200 || Math.abs(actor.getZ() - attack_target.getZ()) > 200))
{
actor.sendPacket(SystemMsg.CANNOT_SEE_TARGET);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
range += actor.getMinDistance(attack_target);
if(actor.isFakeDeath())
actor.breakFakeDeath();
if(actor.isInRangeZ(attack_target, range))
{
if(!canSee)
{
actor.sendPacket(SystemMsg.CANNOT_SEE_TARGET);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
clientStopMoving(false);
actor.doAttack(attack_target);
}
else if(!_dontMove)
ThreadPoolManager.getInstance().execute(new ExecuteFollow(attack_target, range - 20));
else
actor.sendActionFailed();
}
protected void thinkCast(boolean checkRange)
{
Playable actor = getActor();
Creature target = getAttackTarget();
if(_skill.getSkillType() == SkillType.CRAFT || _skill.isToggle())
{
if(_skill.checkCondition(actor, target, _forceUse, _dontMove, true))
actor.doCast(_skill, target, _forceUse);
return;
}
if(target == null || target.isDead() != _skill.getCorpse() && !_skill.isNotTargetAoE())
{
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
if(!checkRange)
{
// Если скилл имеет следующее действие, назначим это действие после окончания действия скилла
if(_skill.getNextAction() == NextAction.ATTACK && !actor.equals(target))
setNextAction(nextAction.ATTACK, target, null, _forceUse, false);
else
clearNextAction();
clientStopMoving();
if(_skill.checkCondition(actor, target, _forceUse, _dontMove, true))
actor.doCast(_skill, target, _forceUse);
else
{
setNextIntention();
if(getIntention() == CtrlIntention.AI_INTENTION_ATTACK)
thinkAttack(true);
}
return;
}
int range = actor.getMagicalAttackRange(_skill);
if(range 200 || Math.abs(actor.getZ() - target.getZ()) > 200))
{
actor.sendPacket(SystemMsg.CANNOT_SEE_TARGET);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
range += actor.getMinDistance(target);
if(actor.isFakeDeath())
actor.breakFakeDeath();
if(actor.isInRangeZ(target, range) || noRangeSkill)
{
if(!noRangeSkill && !canSee)
{
actor.sendPacket(SystemMsg.CANNOT_SEE_TARGET);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
// Если скилл имеет следующее действие, назначим это действие после окончания действия скилла
if(_skill.getNextAction() == NextAction.ATTACK && !actor.equals(target) && !_forceUse)
{
//clearNextAction();
setNextAction(nextAction.ATTACK, target, null, _forceUse, false);
}
else
clearNextAction();
if(_skill.checkCondition(actor, target, _forceUse, _dontMove, true))
{
clientStopMoving(false);
actor.doCast(_skill, target, _forceUse);
}
else
{
setNextIntention();
if(getIntention() == CtrlIntention.AI_INTENTION_ATTACK)
thinkAttack(true);
}
}
else if(!_dontMove)
ThreadPoolManager.getInstance().execute(new ExecuteFollow(target, range - 20));
else
{
actor.sendPacket(SystemMsg.YOUR_TARGET_IS_OUT_OF_RANGE);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
}
}
@Override
protected void onEvtDead(Creature killer)
{
clearNextAction();
super.onEvtDead(killer);
}
@Override
protected void onEvtFakeDeath()
{
clearNextAction();
super.onEvtFakeDeath();
}
public void lockTarget(Creature target)
{
Playable actor = getActor();
if(target == null || target.isDead())
actor.setAggressionTarget(null);
else if(actor.getAggressionTarget() == null)
{
GameObject actorStoredTarget = actor.getTarget();
actor.setAggressionTarget(target);
actor.setTarget(target);
clearNextAction();
// DS: агрессия только перекидывает видимую цель, но не обрывает текущую атаку/каст
/*if (getIntention() == CtrlIntention.AI_INTENTION_ATTACK)
setAttackTarget(target);
switch(getIntention())
{
case AI_INTENTION_ATTACK:
setAttackTarget(target);
break;
case AI_INTENTION_CAST:
L2Skill skill = actor.getCastingSkill();
if(skill == null)
skill = _skill;
if(skill != null && !skill.isUsingWhileCasting())
switch(skill.getTargetType())
{
case TARGET_ONE:
case TARGET_AREA:
case TARGET_MULTIFACE:
case TARGET_TUNNEL:
setAttackTarget(target);
actor.setCastingTarget(target);
break;
}
break;
}*/
if(actorStoredTarget != target)
actor.sendPacket(new MyTargetSelected(target.getObjectId(), 0));
}
}
@Override
public void Attack(GameObject target, boolean forceUse, boolean dontMove)
{
Playable actor = getActor();
if(target.isCreature() && (actor.isActionsDisabled() || actor.isAttackingDisabled()))
{
// Если не можем атаковать, то атаковать позже
setNextAction(nextAction.ATTACK, target, null, forceUse, false);
actor.sendActionFailed();
return;
}
_dontMove = dontMove;
_forceUse = forceUse;
clearNextAction();
setIntention(AI_INTENTION_ATTACK, target);
}
@Override
public void Cast(Skill skill, Creature target, boolean forceUse, boolean dontMove)
{
Playable actor = getActor();
// Если скилл альтернативного типа (например, бутылка на хп),
// то он может использоваться во время каста других скиллов, или во время атаки, или на бегу.
// Поэтому пропускаем дополнительные проверки.
if(skill.altUse() || skill.isToggle())
{
if((skill.isToggle() || skill.isHandler()) && (actor.isOutOfControl() || actor.isStunned() || actor.isSleeping() || actor.isParalyzed() || actor.isAlikeDead()))
clientActionFailed();
else
actor.altUseSkill(skill, target);
return;
}
// Если не можем кастовать, то использовать скилл позже
if(actor.isActionsDisabled())
{
//if(!actor.isSkillDisabled(skill.getId()))
setNextAction(nextAction.CAST, skill, target, forceUse, dontMove);
clientActionFailed();
return;
}
//_actor.stopMove(null);
_forceUse = forceUse;
_dontMove = dontMove;
clearNextAction();
setIntention(CtrlIntention.AI_INTENTION_CAST, skill, target);
}
@Override
public Playable getActor()
{
return (Playable) super.getActor();
}
}
Сообщение от Спойлер
PHP:
Код:
package l2p.gameserver.ai;
import static java.lang.Math.abs;
import static java.lang.Math.max;
import java.util.concurrent.ScheduledFuture;
import l2p.commons.threading.RunnableImpl;
import static l2p.gameserver.ThreadPoolManager.getInstance;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
import static l2p.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
import static l2p.gameserver.ai.PlayableAI.nextAction.ATTACK;
import static l2p.gameserver.ai.PlayableAI.nextAction.CAST;
import static l2p.gameserver.ai.PlayableAI.nextAction.INTERACT;
import static l2p.gameserver.ai.PlayableAI.nextAction.PICKUP;
import static l2p.gameserver.geodata.GeoEngine.canSeeTarget;
import l2p.gameserver.model.Creature;
import l2p.gameserver.model.GameObject;
import l2p.gameserver.model.Playable;
import l2p.gameserver.model.Player;
import l2p.gameserver.model.Skill;
import static l2p.gameserver.model.Skill.SkillType.CRAFT;
import static l2p.gameserver.model.Skill.SkillType.TAKECASTLE;
import static l2p.gameserver.model.Skill.SkillType.TAKEFORTRESS;
import l2p.gameserver.model.Summon;
import l2p.gameserver.serverpackets.MyTargetSelected;
import static l2p.gameserver.serverpackets.components.SystemMsg.CANNOT_SEE_TARGET;
import static l2p.gameserver.serverpackets.components.SystemMsg.YOUR_TARGET_IS_OUT_OF_RANGE;
import l2p.gameserver.utils.Location;
public class PlayableAI extends CharacterAI
{
private volatile int thinking = 0; // to prevent recursive thinking
private Object _intention_arg0 = null;
private Object _intention_arg1 = null;
private Skill _skill;
private nextAction _nextAction;
private Object _nextAction_arg0;
private Object _nextAction_arg1;
private boolean _nextAction_arg2;
private boolean _nextAction_arg3;
private boolean _forceUse;
private boolean _dontMove;
private ScheduledFuture
_followTask;
public PlayableAI(Playable actor)
{
super(actor);
}
/**
* @return the thinking
*/
public int getThinking() {
return thinking;
}
/**
* @param thinking the thinking to set
*/
public void setThinking(int thinking) {
this.thinking = thinking;
}
/**
* @return the _intention_arg0
*/
public Object getIntention_arg0() {
return _intention_arg0;
}
/**
* @param _intention_arg0 the _intention_arg0 to set
*/
public void setIntention_arg0(Object _intention_arg0) {
this._intention_arg0 = _intention_arg0;
}
/**
* @return the _intention_arg1
*/
public Object getIntention_arg1() {
return _intention_arg1;
}
/**
* @param _intention_arg1 the _intention_arg1 to set
*/
public void setIntention_arg1(Object _intention_arg1) {
this._intention_arg1 = _intention_arg1;
}
/**
* @return the _skill
*/
public Skill getSkill() {
return _skill;
}
/**
* @param _skill the _skill to set
*/
public void setSkill(Skill _skill) {
this._skill = _skill;
}
/**
* @return the _nextAction
*/
public nextAction getNextAction() {
return _nextAction;
}
/**
* @param _nextAction the _nextAction to set
*/
public void setNextAction(nextAction _nextAction) {
this._nextAction = _nextAction;
}
/**
* @return the _nextAction_arg0
*/
public Object getNextAction_arg0() {
return _nextAction_arg0;
}
/**
* @param _nextAction_arg0 the _nextAction_arg0 to set
*/
public void setNextAction_arg0(Object _nextAction_arg0) {
this._nextAction_arg0 = _nextAction_arg0;
}
/**
* @return the _nextAction_arg1
*/
public Object getNextAction_arg1() {
return _nextAction_arg1;
}
/**
* @param _nextAction_arg1 the _nextAction_arg1 to set
*/
public void setNextAction_arg1(Object _nextAction_arg1) {
this._nextAction_arg1 = _nextAction_arg1;
}
/**
* @return the _nextAction_arg2
*/
public boolean isNextAction_arg2() {
return _nextAction_arg2;
}
/**
* @param _nextAction_arg2 the _nextAction_arg2 to set
*/
public void setNextAction_arg2(boolean _nextAction_arg2) {
this._nextAction_arg2 = _nextAction_arg2;
}
/**
* @return the _nextAction_arg3
*/
public boolean isNextAction_arg3() {
return _nextAction_arg3;
}
/**
* @param _nextAction_arg3 the _nextAction_arg3 to set
*/
public void setNextAction_arg3(boolean _nextAction_arg3) {
this._nextAction_arg3 = _nextAction_arg3;
}
/**
* @return the _forceUse
*/
public boolean isForceUse() {
return _forceUse;
}
/**
* @param _forceUse the _forceUse to set
*/
public void setForceUse(boolean _forceUse) {
this._forceUse = _forceUse;
}
/**
* @return the _dontMove
*/
public boolean isDontMove() {
return _dontMove;
}
/**
* @param _dontMove the _dontMove to set
*/
public void setDontMove(boolean _dontMove) {
this._dontMove = _dontMove;
}
/**
* @return the _followTask
*/
public ScheduledFuture
getFollowTask() {
return _followTask;
}
/**
* @param _followTask the _followTask to set
*/
public void setFollowTask(ScheduledFuture
_followTask) {
this._followTask = _followTask;
}
public enum nextAction
{
ATTACK,
CAST,
MOVE,
REST,
PICKUP,
INTERACT
}
@Override
public void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
{
super.changeIntention(intention, arg0, arg1);
setIntention_arg0(arg0);
setIntention_arg1(arg1);
}
@Override
public void setIntention(CtrlIntention intention, Object arg0, Object arg1)
{
setIntention_arg0(null);
setIntention_arg1(null);
super.setIntention(intention, arg0, arg1);
}
@Override
protected void onIntentionCast(Skill skill, Creature target)
{
setSkill(skill);
super.onIntentionCast(skill, target);
}
@Override
public void setNextAction(nextAction action, Object arg0, Object arg1, boolean arg2, boolean arg3)
{
setNextAction(action);
setNextAction_arg0(arg0);
setNextAction_arg1(arg1);
setNextAction_arg2(arg2);
setNextAction_arg3(arg3);
}
public boolean setNextIntention()
{
nextAction nextAction = getNextAction();
Object nextAction_arg0 = getNextAction_arg0();
Object nextAction_arg1 = getNextAction_arg1();
boolean nextAction_arg2 = isNextAction_arg2();
boolean nextAction_arg3 = isNextAction_arg3();
Playable actor = getActor();
if(nextAction == null || actor.isActionsDisabled())
return false;
Skill skill;
Creature target;
GameObject object;
switch(nextAction)
{
case ATTACK:
if(nextAction_arg0 == null)
return false;
target = (Creature) nextAction_arg0;
setForceUse(nextAction_arg2);
setDontMove(nextAction_arg3);
clearNextAction();
setIntention(AI_INTENTION_ATTACK, target);
break;
case CAST:
if(nextAction_arg0 == null || nextAction_arg1 == null)
return false;
skill = (Skill) nextAction_arg0;
target = (Creature) nextAction_arg1;
setForceUse(nextAction_arg2);
setDontMove(nextAction_arg3);
clearNextAction();
if(!skill.checkCondition(actor, target, _forceUse, _dontMove, true))
{
if(skill.getNextAction() == ATTACK && !actor.equals(target))
{
setNextAction(ATTACK, target, null, isForceUse(), false);
return setNextIntention();
}
return false;
}
setIntention(AI_INTENTION_CAST, skill, target);
break;
case MOVE:
if(nextAction_arg0 == null || nextAction_arg1 == null)
return false;
Location loc = (Location) nextAction_arg0;
Integer offset = (Integer) nextAction_arg1;
clearNextAction();
actor.moveToLocation(loc, offset, nextAction_arg2);
break;
case REST:
actor.sitDown(null);
break;
case INTERACT:
if(nextAction_arg0 == null)
return false;
object = (GameObject) nextAction_arg0;
clearNextAction();
onIntentionInteract(object);
break;
case PICKUP:
if(nextAction_arg0 == null)
return false;
object = (GameObject) nextAction_arg0;
clearNextAction();
onIntentionPickUp(object);
break;
default:
return false;
}
return true;
}
@Override
public void clearNextAction()
{
setNextAction(null);
setNextAction_arg0(null);
setNextAction_arg1(null);
setNextAction_arg2(false);
setNextAction_arg3(false);
}
@Override
protected void onEvtFinishCasting()
{
if(!setNextIntention())
setIntention(AI_INTENTION_ACTIVE);
}
@Override
protected void onEvtReadyToAct()
{
if(!setNextIntention())
onEvtThink();
}
@Override
protected void onEvtArrived()
{
if(!setNextIntention())
if(getIntention() == AI_INTENTION_INTERACT || getIntention() == AI_INTENTION_PICK_UP)
onEvtThink();
else
changeIntention(AI_INTENTION_ACTIVE, null, null);
}
@Override
protected void onEvtArrivedTarget()
{
switch(getIntention())
{
case AI_INTENTION_ATTACK:
thinkAttack(false);
break;
case AI_INTENTION_CAST:
thinkCast(false);
break;
case AI_INTENTION_FOLLOW:
thinkFollow();
break;
default:
onEvtThink();
break;
}
}
@Override
protected final void onEvtThink()
{
Playable actor = getActor();
if(actor.isActionsDisabled())
return;
try
{
if(thinking++ > 1)
return;
switch(getIntention())
{
case AI_INTENTION_ACTIVE:
thinkActive();
break;
case AI_INTENTION_ATTACK:
thinkAttack(true);
break;
case AI_INTENTION_CAST:
thinkCast(true);
break;
case AI_INTENTION_PICK_UP:
thinkPickUp();
break;
case AI_INTENTION_INTERACT:
thinkInteract();
break;
case AI_INTENTION_FOLLOW:
thinkFollow();
break;
}
}
catch(Exception e)
{
_log.error("Unexpected error in PlayableAI.onEvtThink()", e);
}
finally
{
setThinking(getThinking() - 1);
}
}
protected void thinkActive()
{
}
protected void thinkFollow()
{
Playable actor = getActor();
Creature target = (Creature) getIntention_arg0();
Integer offset = (Integer) getIntention_arg1();
//Находимся слишком далеко цели, либо цель не пригодна для следования
if(target == null || target.isAlikeDead() || actor.getDistance(target) > 4000 || offset == null)
{
clientActionFailed();
return;
}
//Уже следуем за этой целью
if(actor.isFollow && actor.getFollowTarget() == target)
{
clientActionFailed();
return;
}
//Находимся достаточно близко или не можем двигаться - побежим потом ?
if(actor.isInRange(target, offset + 20) || actor.isMovementDisabled())
clientActionFailed();
if(getFollowTask() != null)
{
getFollowTask().cancel(false);
setFollowTask(null);
}
setFollowTask(getInstance().schedule(new ThinkFollow(), 250L));
}
protected class ThinkFollow extends RunnableImpl
{
@Override
public void runImpl() throws Exception
{
Playable actor = getActor();
if(getIntention() != AI_INTENTION_FOLLOW)
{
// Если пет прекратил преследование, меняем статус, чтобы не пришлось щелкать на кнопку следования 2 раза.
if((actor.isPet() || actor.isSummon()) && getIntention() == AI_INTENTION_ACTIVE)
((Summon) actor).setFollowMode(false);
return;
}
Creature target = (Creature) getIntention_arg0();
int offset = getIntention_arg1() instanceof Integer ? (Integer) getIntention_arg1() : 0;
if(target == null || !target.isVisible() || target.isAlikeDead() || actor.getDistance(target) > 4000)
{
setIntention(AI_INTENTION_ACTIVE);
return;
}
Player player = actor.getPlayer();
if(player == null || player.isLogoutStarted() || (actor.isPet() || actor.isSummon()) && player.getPet() != actor)
{
setIntention(AI_INTENTION_ACTIVE);
return;
}
if(!actor.isInRange(target, offset + 20) && (!actor.isFollow || actor.getFollowTarget() != target))
actor.followToCharacter(target, offset, false);
setFollowTask(getInstance().schedule(this, 250L));
}
}
protected class ExecuteFollow extends RunnableImpl
{
private final Creature _target;
private final int _range;
public ExecuteFollow(Creature target, int range)
{
_target = target;
_range = range;
}
@Override
public void runImpl()
{
if(_target.isDoor())
_actor.moveToLocation(_target.getLoc(), 40, true);
else
_actor.followToCharacter(_target, _range, true);
}
}
@Override
protected void onIntentionInteract(GameObject object)
{
Playable actor = getActor();
if(actor.isActionsDisabled())
{
setNextAction(INTERACT, object, null, false, false);
clientActionFailed();
return;
}
clearNextAction();
changeIntention(AI_INTENTION_INTERACT, object, null);
onEvtThink();
}
protected void thinkInteract()
{
Playable actor = getActor();
GameObject target = (GameObject) getIntention_arg0();
if(target == null)
{
setIntention(AI_INTENTION_ACTIVE);
return;
}
int range = (int) (max(30, actor.getMinDistance(target)) + 20);
if(actor.isInRangeZ(target, range))
{
if(actor.isPlayer())
((Player) actor).doInteract(target);
setIntention(AI_INTENTION_ACTIVE);
}
else
{
actor.moveToLocation(target.getLoc(), 40, true);
setNextAction(INTERACT, target, null, false, false);
}
}
@Override
protected void onIntentionPickUp(GameObject object)
{
Playable actor = getActor();
if(actor.isActionsDisabled())
{
setNextAction(PICKUP, object, null, false, false);
clientActionFailed();
return;
}
clearNextAction();
changeIntention(AI_INTENTION_PICK_UP, object, null);
onEvtThink();
}
protected void thinkPickUp()
{
final Playable actor = getActor();
final GameObject target = (GameObject) getIntention_arg0();
if(target == null)
{
setIntention(AI_INTENTION_ACTIVE);
return;
}
if(actor.isInRange(target, 30) && abs(actor.getZ() - target.getZ()) 200 || abs(actor.getZ() - attack_target.getZ()) > 200))
{
actor.sendPacket(CANNOT_SEE_TARGET);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
range += actor.getMinDistance(attack_target);
if(actor.isFakeDeath())
actor.breakFakeDeath();
if(actor.isInRangeZ(attack_target, range))
{
if(!canSee)
{
actor.sendPacket(CANNOT_SEE_TARGET);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
clientStopMoving(false);
actor.doAttack(attack_target);
}
else if(!isDontMove())
getInstance().execute(new ExecuteFollow(attack_target, range - 20));
else
actor.sendActionFailed();
}
protected void thinkCast(boolean checkRange)
{
Playable actor = getActor();
Creature target = getAttackTarget();
if(getSkill().getSkillType() == CRAFT || getSkill().isToggle())
{
if(getSkill().checkCondition(actor, target, isForceUse(), isDontMove(), true))
actor.doCast(getSkill(), target, isForceUse());
return;
}
if(target == null || target.isDead() != getSkill().getCorpse() && !_skill.isNotTargetAoE())
{
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
if(!checkRange)
{
// Если скилл имеет следующее действие, назначим это действие после окончания действия скилла
if(getSkill().getNextAction() == ATTACK && !actor.equals(target))
setNextAction(ATTACK, target, null, isForceUse(), false);
else
clearNextAction();
clientStopMoving();
if(getSkill().checkCondition(actor, target, isForceUse(), isDontMove(), true))
actor.doCast(getSkill(), target, isForceUse());
else
{
setNextIntention();
if(getIntention() == AI_INTENTION_ATTACK)
thinkAttack(true);
}
return;
}
int range = actor.getMagicalAttackRange(getSkill());
if(range 200 || abs(actor.getZ() - target.getZ()) > 200))
{
actor.sendPacket(CANNOT_SEE_TARGET);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
range += actor.getMinDistance(target);
if(actor.isFakeDeath())
actor.breakFakeDeath();
if(actor.isInRangeZ(target, range) || noRangeSkill)
{
if(!noRangeSkill && !canSee)
{
actor.sendPacket(CANNOT_SEE_TARGET);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
return;
}
// Если скилл имеет следующее действие, назначим это действие после окончания действия скилла
if(getSkill().getNextAction() == ATTACK && !actor.equals(target) && !isForceUse())
{
//clearNextAction();
setNextAction(ATTACK, target, null, isForceUse(), false);
}
else
clearNextAction();
if(getSkill().checkCondition(actor, target, isForceUse(), isDontMove(), true))
{
clientStopMoving(false);
actor.doCast(getSkill(), target, isForceUse());
}
else
{
setNextIntention();
if(getIntention() == AI_INTENTION_ATTACK)
thinkAttack(true);
}
}
else if(!isDontMove())
getInstance().execute(new ExecuteFollow(target, range - 20));
else
{
actor.sendPacket(YOUR_TARGET_IS_OUT_OF_RANGE);
setIntention(AI_INTENTION_ACTIVE);
actor.sendActionFailed();
}
}
@Override
protected void onEvtDead(Creature killer)
{
clearNextAction();
super.onEvtDead(killer);
}
@Override
protected void onEvtFakeDeath()
{
clearNextAction();
super.onEvtFakeDeath();
}
public void lockTarget(Creature target)
{
Playable actor = getActor();
if(target == null || target.isDead())
actor.setAggressionTarget(null);
else if(actor.getAggressionTarget() == null)
{
GameObject actorStoredTarget = actor.getTarget();
actor.setAggressionTarget(target);
actor.setTarget(target);
clearNextAction();
// DS: агрессия только перекидывает видимую цель, но не обрывает текущую атаку/каст
/*if (getIntention() == CtrlIntention.AI_INTENTION_ATTACK)
setAttackTarget(target);
switch(getIntention())
{
case AI_INTENTION_ATTACK:
setAttackTarget(target);
break;
case AI_INTENTION_CAST:
L2Skill skill = actor.getCastingSkill();
if(skill == null)
skill = _skill;
if(skill != null && !skill.isUsingWhileCasting())
switch(skill.getTargetType())
{
case TARGET_ONE:
case TARGET_AREA:
case TARGET_MULTIFACE:
case TARGET_TUNNEL:
setAttackTarget(target);
actor.setCastingTarget(target);
break;
}
break;
}*/
if(actorStoredTarget != target)
actor.sendPacket(new MyTargetSelected(target.getObjectId(), 0));
}
}
@Override
public void Attack(GameObject target, boolean forceUse, boolean dontMove)
{
Playable actor = getActor();
if(target.isCreature() && (actor.isActionsDisabled() || actor.isAttackingDisabled()))
{
// Если не можем атаковать, то атаковать позже
setNextAction(ATTACK, target, null, forceUse, false);
actor.sendActionFailed();
return;
}
setDontMove(dontMove);
setForceUse(forceUse);
clearNextAction();
setIntention(AI_INTENTION_ATTACK, target);
}
@Override
public void Cast(Skill skill, Creature target, boolean forceUse, boolean dontMove)
{
Playable actor = getActor();
// Если скилл альтернативного типа (например, бутылка на хп),
// то он может использоваться во время каста других скиллов, или во время атаки, или на бегу.
// Поэтому пропускаем дополнительные проверки.
if(skill.altUse() || skill.isToggle())
{
if((skill.isToggle() || skill.isHandler()) && (actor.isOutOfControl() || actor.isStunned() || actor.isSleeping() || actor.isParalyzed() || actor.isAlikeDead()))
clientActionFailed();
else
actor.altUseSkill(skill, target);
return;
}
// Если не можем кастовать, то использовать скилл позже
if(actor.isActionsDisabled())
{
//if(!actor.isSkillDisabled(skill.getId()))
setNextAction(CAST, skill, target, forceUse, dontMove);
clientActionFailed();
return;
}
//_actor.stopMove(null);
setForceUse(forceUse);
setDontMove(dontMove);
clearNextAction();
setIntention(AI_INTENTION_CAST, skill, target);
}
@Override
public Playable getActor()
{
return (Playable) super.getActor();
}
}
|
|
|
|
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|