Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
- */
- package com.l2jserver.gameserver.ai.ext.tasks;
- import com.l2jserver.Config;
- import com.l2jserver.gameserver.GeoData;
- import com.l2jserver.gameserver.ai.ext.AI_TaskQueue;
- import com.l2jserver.gameserver.ai.ext.struct.holder.PawnEvaluationHolder;
- import com.l2jserver.gameserver.ai.ext.struct.position.BasePositionData;
- import com.l2jserver.gameserver.ai.ext.struct.stat_watchers.PawnEvaluationData;
- import com.l2jserver.gameserver.ai.ext.struct.task.AITaskSimpleVar;
- import com.l2jserver.gameserver.ext.util.ExtUtil;
- import com.l2jserver.gameserver.model.actor.L2Character;
- import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
- import com.l2jserver.gameserver.util.Point3D;
- import com.l2jserver.util.Rnd;
- import java.util.Collection;
- /**
- * ==============================================<br>
- * AttackRepositionTask - This tasks is active, when AI is in combat mode. Task probes
- * target surroundings, and repositions character accordingly, to Vector Engine
- * position calculations, taking into consideration other attackers (if exist). This
- * task is also responsible, for remembering valid char->target position vector, when
- * is found. Task additionally scouts possible "move to" positions, if they are
- * better than current. If not, movement is not performed..<br>
- * ==============================================<br>
- * @author Deedlit(deedlit@protonmail.com)
- */
- public class AttackRepositionTask extends AbstractAITask
- {
- private L2Character _target;
- private boolean _forceMove = false;
- public AttackRepositionTask(L2Character cha, L2Character target)
- {
- super(cha.getTaskQueue(), 0, false, true, 0, cha);
- _target = target;
- }
- @Override
- protected void initTaskTypeName()
- {
- _name = "AttackRepositionTask";
- }
- private BasePositionData _pawnBasePositionData;
- public L2Character getTarget()
- {
- L2Character newTarget = getAI().getAttackTarget();
- if (_target != newTarget || _pawnBasePositionData == null)
- {
- _pawnBasePositionData = getActor().getRangesCalc().getPawnRangeInfo(newTarget);
- }
- _target = newTarget;
- return _target;
- }
- @Override
- public boolean valid()
- {
- return /*getTarget() != null &&*/ hasAI() && /*getTarget().hasAI() &&*/ getAI().getIntention().isAttackingMode() && !getActor().isDead() && !getActor().isPlayable()
- && !getActor().getRangesCalc().isLongRangeType();// && getAI().getAttackTarget() == getTarget();
- }
- @Override
- public boolean waiting(int taskRunCycle)
- {
- return (getTarget() == null || !hasAI() || !getTarget().hasAI() || getActor().isCastingNow() || (getActor().isAttackingNow() && getActor().hitBroadcasted)
- || (getActor().getTimeToDestination() > 6000 && getActor().getMyLocation().calculateTimeToMoveTo(getTarget().getMyLocation(), getActor(), getActor().isFloating() || getTarget().isFloating()) > 9000)
- || getTarget().isMoving() || (getAI().isFollowing() && getActor().getRangesCalc().canSee(getTarget())) || getActor().isMovementDisabled()) || !getActor().getRangesCalc().canSee(getTarget());
- }
- @Override
- public boolean ready()
- {
- return (getAI().getAtkMovTimestamp() >= 0 && System.currentTimeMillis() - getAI().getAtkMovTimestamp() > 15000 && getTarget().getCombatData().countAttackers() > 5) || shouldReposition()|| (!getActor().getRangesCalc().canSee(getTarget()) && !getActor().isMoving());
- }
- private boolean shouldReposition()
- {
- try
- {
- if (_pawnBasePositionData != null)
- {
- PawnEvaluationData ed = _pawnBasePositionData.getPawnEvaluationData();
- if (ed.isActorAttacking() || !ed.isActorCanMove() || (ed.isPawnFloating() && !ed.isActorCanFloat()) || !ed.isActorCanSeePawn())
- return false;
- if (ed.isWithinMaxOffsetNoMoveExtent())
- {
- // ---
- }
- // w zasiΔgu
- if (ed.isWithinMaxOffset())
- {
- if (ed.isMovingInOppositeDirections())
- {
- int whenWeMeet = ed.getActorTimeToMoveToPawn();
- if (ed.isBothMoving())
- whenWeMeet = Math.abs(ed.getActorPosition().calculateTimeToMoveTo(ed.getPawnPosition(), getTarget(), ed.isFloatingAny()) - ed.getActorTimeToMoveToPawn())/2;
- }
- else if (ed.isMovingInSameDirection())
- {
- }
- }
- }
- if (getActor().getRangesCalc().isWithinMaxOffset(getTarget()) && !(getTarget().getAI().getAtkMovTimestamp() <= 0
- || (getTarget().getAI().getAtkMovTimestamp() > 0 && System.currentTimeMillis() - getTarget().getAI().getAtkMovTimestamp() > 500)))
- return false;
- boolean ready = getTarget() != null && hasAI() && getTarget().hasAI() && ((!getActor().getRangesCalc().isWithinMaxOffset(getTarget()) && (getActor().getTimeToDestination() < 1000
- || getActor().getMyDestinationLocation().calculateDistanceTo(getTarget().getMyLocation(), getActor().isFloating()
- || getTarget().isFloating()) > getActor().getMyLocation().calculateDistanceTo(getTarget().getMyLocation(), getActor().isFloating() || getTarget().isFloating())
- || getActor().getRangesCalc().needToCalcNewPositionAroundPawn(getTarget())))
- || (/*getActor().isMoving() != getTarget().isMoving() ||*/ ((getActor().isMoving() || (getAI().getAtkMovTimestamp() <= 0 || System.currentTimeMillis() - getAI().getAtkMovTimestamp() > 1000)))
- && (/*!getTarget().isMoving() ||*/ (getTarget().getAI().getAtkMovTimestamp() <= 0 || (System.currentTimeMillis() - getTarget().getAI().getAtkMovTimestamp() > 1000
- || getTarget().getMyLocation().calculateTimeToMoveTo(getActor().getMyLocation(), getActor(), getActor().isFloating() || getTarget().isFloating()) > 2000)))))
- && getActor().getRangesCalc().canSee(getTarget());
- if (!ready && !getActor().isMoving() && !getTarget().isMoving() && !getActor().getRangesCalc().getPawnRangeInfo(getTarget()).isRegistered())
- {
- BasePositionData bpd = getActor().getRangesCalc().getPawnRangeInfo(getTarget());
- if (bpd != null && !bpd.isRegistered())
- bpd.tryKeepingPositionVector();
- }
- return ready;
- }
- catch (Exception e)
- {
- return false;
- }
- }
- /**
- * Returning always true, to not forcibly push this task, on the queue top.
- * @return
- */
- @Override
- public boolean run()
- {
- _forceMove = false; // reset if forced exec
- final L2Character target = getTarget();
- if (target == null)
- return false;
- final L2Character cha = getActor();
- final int collision = (int)cha.getCollisionRadius();
- if (_pawnBasePositionData == null)
- return false;
- if (/*!cha.isMoving() && */_pawnBasePositionData.canSee())
- {
- int attackers = target.getAI().getCombatData().countAttackers();
- if ((!cha.isMoving() && getAI().getAtkMovTimestamp() > 0 && System.currentTimeMillis() - getAI().getAtkMovTimestamp() > 15000 && attackers > 5
- && !_pawnBasePositionData.needToCalcNewPositionAroundPawn()) && Rnd.qchance(Math.min(25 + attackers, 45))) /* If not moved for over 25s, try going randomly some. */
- {
- int x1, y1, z1, x = _pawnBasePositionData.getPawnEvaluationData().getPawnPosition().x, y = _pawnBasePositionData.getPawnEvaluationData().getPawnPosition().y;
- int drange = /*Rnd.qchance(15) ? 350 : 50*/0;
- int tries = 3, range = drange + getAI().getRangesCalc().getMaxOffset(target);
- while (tries > 0)
- {
- tries--;
- x1 = Rnd.qnextInt(range * 2); // x
- y1 = Rnd.qget(x1, range * 2); // distance
- y1 = (int) Math.sqrt(y1 * y1 - x1 * x1); // y
- x1 += x - range;
- y1 += y - range;
- z1 = GeoData.getInstance().getSpawnHeight(x1, y1, cha.getZ() - 30, cha.getZ() + 50, null);
- Point3D t = new Point3D(x1, y1, z1);
- if (t.calculateDistanceTo(cha.getMyLocation(), false) < 32 || GeoData.getInstance().getNSWE(t) != 15 || !GeoData.getInstance().canMoveFromToTarget(cha.getMyLocation(), t))
- continue;
- if (cha.isAttackingNow() && !cha.isAttackAborted())
- cha.abortAttack();
- getAI().moveTo(t);
- if (cha.isMoving())
- return true;
- }
- }
- boolean lastResort = false;
- if (!target.isMoving()) /* Main reposition routine, checking nearby area and destination position befor moving. */
- {
- try
- {
- int maxChance = 0; int reposM = 1;
- boolean targetNear = _pawnBasePositionData.needToCalcNewPositionAroundPawn();
- boolean playersNear = false;
- if ((!targetNear || !target.isPlayer()) && !cha.isMoving())
- {
- Collection<L2PcInstance> _players = cha.getKnownList().getKnownPlayersInRadius(collision + collision + 10);
- if (target.isPlayer() && _players.contains(target.getActingPlayer()))
- _players.remove(target.getActingPlayer());
- playersNear = !_players.isEmpty();
- }
- boolean charsNear = false, chance = false;
- if ((!targetNear && !playersNear) && !cha.isMoving())
- {
- double cmul = cha.getCollisionRadius() / 10.;
- if (target.getCombatData() != null)
- {
- if (attackers < 13 / cmul)
- maxChance = 17;
- else if (attackers < 15 / cmul)
- maxChance = 15;
- else if (attackers < 17 / cmul)
- maxChance = 12;
- else if (attackers < 19 / cmul)
- maxChance = 9;
- else if (attackers < 23 / cmul)
- maxChance = 6;
- else
- maxChance = 3;
- }
- charsNear = !cha.getKnownList().getKnownCharactersInRadius(collision + collision + 10, false).isEmpty();
- if (!charsNear)
- {
- final int[] _dest = _pawnBasePositionData.calcNewPositionAroundPawn();
- if (_dest != null && _dest[4] == 1)
- {
- final Point3D d = new Point3D(_dest[0], _dest[1], _dest[2]);
- if (!cha.isMoving() && !target.isMoving() && ExtUtil.calculateDistance(d, cha.getMyLocation(), false) <= collision / 4)
- _pawnBasePositionData.tryKeepingPositionVector();
- }
- }
- else if (maxChance > 0)
- chance = Rnd.qchance(maxChance);
- }
- if ((charsNear && chance) || targetNear || playersNear)
- {
- if (playersNear && System.currentTimeMillis() - getAI().getLastToPawnCoordRecalc() < 2500)
- playersNear = false;
- int[] _dest = _pawnBasePositionData.calcNewPositionAroundPawn(playersNear, Config.SL2_MOD_AI_USE_ATK_INDEX_FOR_PAWN_POSITIONING, !cha.isFloating());
- double _dist = _dest != null ? cha.getMyLocation().calculateDistanceTo(new Point3D(_dest[0], _dest[1], _dest[2]), false) : 0;
- boolean okToMove = _dist > cha.getCollisionRadius();
- if (!targetNear && !playersNear && okToMove)
- {
- okToMove = cha.getKnownList().getKnownCharactersInRadiusAt(_dest[0], _dest[1], _dest[2], collision + collision + 10, false).isEmpty();
- if (okToMove)
- reposM = 2;
- }
- if (!okToMove && (targetNear || playersNear || System.currentTimeMillis() - getAI().getLastToPawnCoordRecalc() > 3000))
- {
- _dest = _pawnBasePositionData.calcNewPositionAroundPawn(true, Config.SL2_MOD_AI_USE_ATK_INDEX_FOR_PAWN_POSITIONING, !cha.isFloating());
- _dist = _dest != null ? cha.getMyLocation().calculateDistanceTo(new Point3D(_dest[0], _dest[1], _dest[2]), false) : 0;
- okToMove = _dist > cha.getCollisionRadius() && (targetNear || cha.getKnownList().getKnownCharactersInRadiusAt(_dest[0], _dest[1], _dest[2], collision + collision + 10, false).isEmpty());
- if (okToMove)
- {
- if (!targetNear)
- getRangesCalc().keepCurrentPositionVector(target);
- reposM = 3;
- }
- }
- if (okToMove)
- {
- getAI().moveTo(_dest[0], _dest[1], _dest[2]);
- if (cha.isMoving())
- {
- getAI().setLastToPawnCoordRecalc(System.currentTimeMillis());
- try
- {
- if (cha.isAIDebug() && Config.AI_log_this(cha, "on_atk_repos"))
- cha.debug().debugRegisterActorAI_Warning("thinkAttack: reposition "+reposM);
- }
- catch (Exception e)
- {
- }
- return true;
- }
- lastResort = true;
- }
- }
- else if (!charsNear && !cha.isMoving())
- {
- final int[] _dest = _pawnBasePositionData.calcNewPositionAroundPawn();
- if (_dest != null && _dest[4] == 1)
- {
- final Point3D d = new Point3D(_dest[0], _dest[1], _dest[2]);
- if (!cha.isMoving() && !target.isMoving() && ExtUtil.calculateDistance(d, cha.getMyLocation(), false) <= collision / 4)
- _pawnBasePositionData.tryKeepingPositionVector();
- }
- }
- }
- catch(NullPointerException npe)
- {
- // ignore NPE's (can appear, when task is run, after target is decayed).
- }
- }
- /* Last resort movement routine if one above failed or sth */
- if ((lastResort || _pawnBasePositionData.needToCalcNewPositionAroundPawn()) && !cha.isMoving()/*&& (*//*target.isMoving() !=*//* !cha.isMoving())*/)//cha.isInsideRadius(target, getAI().getRangesCalc().isWithinMaxOffset(target), cha.isFloating() || target.isFloating(), false))
- {
- getAI().moveToPawn(target, getAI().getRangesCalc().getMinOffset(target), true, lastResort);
- if (cha.isMoving())
- {
- getAI().setLastToPawnCoordRecalc(System.currentTimeMillis());
- return true;
- }
- }
- }
- return false;
- }
- @Override
- public boolean block_think_after_run()
- {
- return false;
- }
- @Override
- public int update_weight()
- {
- return -1;
- }
- @Override
- public boolean removeable()
- {
- return !valid();
- }
- @Override
- public boolean valid_run_delay()
- {
- return !(getActor().isAttackingNow() && !getActor().isAttackAborted()) && (calcTimeSinceTaskLastExec(false) <= 0
- || calcTimeSinceTaskLastExec(false) > (!getActor().isMoving() || getTarget().isMoving() ? 250 : 350));
- }
- @Override
- public int max_task_instances()
- {
- return 1;
- }
- @Override
- public void on_variable_listener(AITaskSimpleVar.LISTENER_EVENTS event, AITaskSimpleVar variable)
- {
- if (event == AITaskSimpleVar.LISTENER_EVENTS.VALUE_CHANGE && variable.getVarName().equals("_forceAtkRepos") && variable.getValueBool())
- {
- _forceMove = true;
- run();
- }
- }
- @Override
- public void on_added_to_queue(AI_TaskQueue queue)
- {
- queue.getTaskVariable("_forceAtkRepos").registerListener(getTaskId(), AITaskSimpleVar.LISTENER_EVENTS.VALUE_CHANGE);
- }
- @Override
- public void on_remove_from_queue(AI_TaskQueue queue)
- {
- queue.getTaskVariable("_forceAtkRepos").unregisterListener(getTaskId(), AITaskSimpleVar.LISTENER_EVENTS.VALUE_CHANGE);
- }
- @Override
- public boolean valid_update_weight_delay()
- {
- return false;
- }
- }
Add Comment
Please, Sign In to add comment