/* * This file is part of aion-emu <aion-unique.org>. * * aion-unique 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. * * aion-unique 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 aion-unique. If not, see <http://www.gnu.org/licenses/>. */ package com.aionemu.gameserver.controllers; import java.util.concurrent.Future; import org.apache.log4j.Logger; import com.aionemu.gameserver.controllers.movement.MovementType; import com.aionemu.gameserver.model.gameobjects.Creature; import com.aionemu.gameserver.model.gameobjects.VisibleObject; import com.aionemu.gameserver.model.gameobjects.stats.StatEnum; import com.aionemu.gameserver.network.aion.serverpackets.SM_MOVE; import com.aionemu.gameserver.utils.MathUtil; import com.aionemu.gameserver.utils.PacketSendUtility; import com.aionemu.gameserver.utils.ThreadPoolManager; /** * @author ATracer * */ public class MoveController { @SuppressWarnings("unused") private static final Logger log = Logger.getLogger(MoveController.class); private Future<?> moveTask; private Creature owner; private boolean directionChanged = true; private float targetX; private float targetY; private float targetZ; private boolean isFollowTarget; private boolean isStopped = false; private int moveCounter; private float speed = 0; private float distance = 2; private boolean walking; /** * * @param owner */ public MoveController(Creature owner) { this.owner = owner; } /** * @param isFollowTarget the isFollowTarget to set */ public void setFollowTarget(boolean isFollowTarget) { this.isFollowTarget = isFollowTarget; } /** * @param speed the speed to set */ public void setSpeed(float speed) { this.speed = speed; } /** * @param distance the distance to set */ public void setDistance(float distance) { this.distance = distance; } /** * @return the walking */ public boolean isWalking() { return walking; } /** * @param walking the walking to set */ public void setWalking(boolean walking) { this.walking = walking; } public void setNewDirection(float x, float y, float z) { if(x != targetX || y != targetY || z != targetZ) this.directionChanged = true; this.targetX = x; this.targetY = y; this.targetZ = z; } public float getTargetX() { return targetX; } public float getTargetY() { return targetY; } public float getTargetZ() { return targetZ; } public boolean isScheduled() { return moveTask != null && !moveTask.isCancelled(); } public void schedule() { if(speed == 0) speed = owner.getGameStats().getCurrentStat(StatEnum.SPEED) / 1000; moveTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new Runnable(){ @Override public void run() { move(); } }, 0, 200); } private void move() { /** * Demo npc skills - prevent movement while casting */ if(!owner.canPerformMove() || owner.isCasting()) { if(!isStopped) { isStopped = true; owner.getController().stopMoving(); } return; } VisibleObject target = owner.getTarget(); if(isFollowTarget && target != null) { setNewDirection(target.getX(), target.getY(), target.getZ()); } float ownerX = owner.getX(); float ownerY = owner.getY(); float ownerZ = owner.getZ(); double dist = MathUtil.getDistance(ownerX, ownerY, ownerZ, targetX, targetY, targetZ); if(dist > this.distance) { isStopped = false; float x2 = (float) (((targetX - ownerX)/dist) * speed * 0.2) ; float y2 = (float) (((targetY - ownerY)/dist) * speed * 0.2) ; float z2 = (float) (((targetZ - ownerZ)/dist) * speed * 0.2) ; byte heading2 = (byte) (Math.toDegrees(Math.atan2(y2, x2))/3) ; if(directionChanged) { PacketSendUtility.broadcastPacket(owner, new SM_MOVE(owner, ownerX, ownerY, ownerZ, (float) (x2 / 0.2) , (float) (y2 / 0.2) , 0 , heading2, MovementType.MOVEMENT_START_KEYBOARD)); directionChanged = false; } moveCounter++; owner.getActiveRegion().getWorld().updatePosition(owner, ownerX + x2, ownerY + y2, ownerZ + z2, heading2, moveCounter % 5 == 0); } else { if(!isStopped) { isStopped = true; owner.getController().stopMoving(); } } } public double getDistanceToTarget() { if(isFollowTarget) { VisibleObject target = owner.getTarget(); if(target != null) return MathUtil.getDistance(owner.getX(), owner.getY(), owner.getZ(), target.getX(), target.getY(), target.getZ()); } return MathUtil.getDistance(owner.getX(), owner.getY(), owner.getZ(), targetX, targetY, targetZ); } public void stop() { this.walking = false; if(moveTask != null) { moveTask.cancel(true); moveTask = null; } } }