Example #1
0
bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ, bool calcHeading) {
	if(GetID()==0)
		return true;

	float nx = m_Position.x;
	float ny = m_Position.y;
	float nz = m_Position.z;

	// if NPC is rooted
	if (speed == 0) {
		SetHeading(CalculateHeadingToTarget(x, y));
		if(moved){
			SetCurrentSpeed(0);
			moved=false;
		}
		Log.Out(Logs::Detail, Logs::AI, "Rooted while calculating new position to (%.3f, %.3f, %.3f)", x, y, z);
		return true;
	}

	float old_test_vector=test_vector;
	m_TargetV.x = x - nx;
	m_TargetV.y = y - ny;
	m_TargetV.z = z - nz;

	if (m_TargetV.x == 0 && m_TargetV.y == 0)
		return false;
	SetCurrentSpeed((int8)(speed)); //*NPC_RUNANIM_RATIO);
	//speed *= NPC_SPEED_MULTIPLIER;

	Log.Out(Logs::Detail, Logs::AI, "Calculating new position to (%.3f, %.3f, %.3f) vector (%.3f, %.3f, %.3f) rate %.3f RAS %d", x, y, z, m_TargetV.x, m_TargetV.y, m_TargetV.z, speed, pRunAnimSpeed);

	// --------------------------------------------------------------------------
	// 2: get unit vector
	// --------------------------------------------------------------------------
	test_vector=sqrtf (x*x + y*y + z*z);
	tar_vector = speed / sqrtf (m_TargetV.x*m_TargetV.x + m_TargetV.y*m_TargetV.y + m_TargetV.z*m_TargetV.z);
	m_Position.w = CalculateHeadingToTarget(x, y);

	if (tar_vector >= 1.0) {
		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), x, y, z);
		}

		m_Position.x = x;
		m_Position.y = y;
		m_Position.z = z;
		Log.Out(Logs::Detail, Logs::AI, "Close enough, jumping to waypoint");
	}
	else {
		float new_x = m_Position.x + m_TargetV.x*tar_vector;
		float new_y = m_Position.y + m_TargetV.y*tar_vector;
		float new_z = m_Position.z + m_TargetV.z*tar_vector;
		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
		}

		m_Position.x = new_x;
		m_Position.y = new_y;
		m_Position.z = new_z;
		Log.Out(Logs::Detail, Logs::AI, "Next position (%.3f, %.3f, %.3f)", m_Position.x, m_Position.y, m_Position.z);
	}

	uint8 NPCFlyMode = 0;

	if(IsNPC()) {
		if(CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
			NPCFlyMode = 1;
	}

	//fix up pathing Z
	if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving))
	{
		if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
			(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
		{
			glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z);

			float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f;

			Log.Out(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x,m_Position.y,m_Position.z);

			if ((newz > -2000) &&
			    std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
			{
				if (std::abs(x - m_Position.x) < 0.5 && std::abs(y - m_Position.y) < 0.5) {
					if (std::abs(z - m_Position.z) <= RuleR(Map, FixPathingZMaxDeltaMoving))
						m_Position.z = z;
					else
						m_Position.z = newz + 1;
				}
				else
					m_Position.z = newz+1;
			}
		}
	}

	//OP_MobUpdate
	if((old_test_vector!=test_vector) || tar_ndx>20){ //send update
		tar_ndx=0;
		this->SetMoving(true);
		moved=true;
		m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f);
		SendPosUpdate();
	}
	tar_ndx++;

	// now get new heading
	SetAppearance(eaStanding, false); // make sure they're standing
	pLastChange = Timer::GetCurrentTime();
	return true;
}
Example #2
0
bool Mob::CalculateNewPosition(float x, float y, float z, float speed, bool checkZ) {
	if(GetID()==0)
		return true;

	float nx = x_pos;
	float ny = y_pos;
	float nz = z_pos;

	// if NPC is rooted
	if (speed == 0.0) {
		SetHeading(CalculateHeadingToTarget(x, y));
		if(moved){
			SendPosition();
			SetMoving(false);
			moved=false;
		}
		SetRunAnimSpeed(0);
		mlog(AI__WAYPOINTS, "Rooted while calculating new position to (%.3f, %.3f, %.3f)", x, y, z);
		return true;
	}

	float old_test_vector=test_vector;
	tar_vx = x - nx;
	tar_vy = y - ny;
	tar_vz = z - nz;

	if (tar_vx == 0 && tar_vy == 0)
		return false;
	pRunAnimSpeed = (uint8)(speed*NPC_RUNANIM_RATIO);
	speed *= NPC_SPEED_MULTIPLIER;

	mlog(AI__WAYPOINTS, "Calculating new position to (%.3f, %.3f, %.3f) vector (%.3f, %.3f, %.3f) rate %.3f RAS %d", x, y, z, tar_vx, tar_vy, tar_vz, speed, pRunAnimSpeed);

	// --------------------------------------------------------------------------
	// 2: get unit vector
	// --------------------------------------------------------------------------
	test_vector=sqrtf (x*x + y*y + z*z);
	tar_vector = speed / sqrtf (tar_vx*tar_vx + tar_vy*tar_vy + tar_vz*tar_vz);
	heading = CalculateHeadingToTarget(x, y);

	if (tar_vector >= 1.0) {
		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), x, y, z);
		}

		x_pos = x;
		y_pos = y;
		z_pos = z;
		mlog(AI__WAYPOINTS, "Close enough, jumping to waypoint");
	}
	else {
		float new_x = x_pos + tar_vx*tar_vector;
		float new_y = y_pos + tar_vy*tar_vector;
		float new_z = z_pos + tar_vz*tar_vector;
		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
		}

		x_pos = new_x;
		y_pos = new_y;
		z_pos = new_z;
		mlog(AI__WAYPOINTS, "Next position (%.3f, %.3f, %.3f)", x_pos, y_pos, z_pos);
	}

	uint8 NPCFlyMode = 0;

	if(IsNPC()) {
		if(CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
			NPCFlyMode = 1;
	}

	//fix up pathing Z
	if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving))
	{
		if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
			(zone->HasWaterMap() && !zone->watermap->InWater(x_pos, y_pos, z_pos)))
		{
			Map::Vertex dest(x_pos, y_pos, z_pos);

			float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f;

			mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos);

			if( (newz > -2000) && ABS(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
			{
				if(ABS(x - x_pos) < 0.5 && ABS(y - y_pos) < 0.5)
				{
					if(ABS(z - z_pos) <= RuleR(Map, FixPathingZMaxDeltaMoving))
						z_pos = z;
					else
						z_pos = newz + 1;
				}
				else
					z_pos = newz+1;
			}
		}
	}

	//OP_MobUpdate
	if((old_test_vector!=test_vector) || tar_ndx>20){ //send update
		tar_ndx=0;
		this->SetMoving(true);
		moved=true;
		delta_x=(x_pos-nx);
		delta_y=(y_pos-ny);
		delta_z=(z_pos-nz);
		delta_heading=0;//(heading-nh)*8;
		SendPosUpdate();
	}
	tar_ndx++;

	// now get new heading
	SetAppearance(eaStanding, false); // make sure they're standing
	pLastChange = Timer::GetCurrentTime();
	return true;
}
Example #3
0
bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ) {
	if(GetID()==0)
		return true;

	if(speed <= 0)
	{
		SetCurrentSpeed(0);
		return true;
	}

	if ((m_Position.x-x == 0) && (m_Position.y-y == 0)) {//spawn is at target coords
		if(m_Position.z-z != 0) {
			m_Position.z = z;
			Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f): Jumping pure Z.", x, y, z);
			return true;
		}
		Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f) inWater=%d: We are there.", x, y, z, inWater);
		return false;
	} else if ((std::abs(m_Position.x - x) < 0.1) && (std::abs(m_Position.y - y) < 0.1)) {
		Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f): X/Y difference <0.1, Jumping to target.", x, y, z);

		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), x, y, z);
		}

		m_Position.x = x;
		m_Position.y = y;
		m_Position.z = z;
		return true;
	}

	bool send_update = false;
	int compare_steps = 20;
	if(tar_ndx < compare_steps && m_TargetLocation.x==x && m_TargetLocation.y==y) {

		float new_x = m_Position.x + m_TargetV.x*tar_vector;
		float new_y = m_Position.y + m_TargetV.y*tar_vector;
		float new_z = m_Position.z + m_TargetV.z*tar_vector;
		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
		}

		m_Position.x = new_x;
		m_Position.y = new_y;
		m_Position.z = new_z;

		Log.Out(Logs::Detail, Logs::AI, "Calculating new position2 to (%.3f, %.3f, %.3f), old vector (%.3f, %.3f, %.3f)", x, y, z, m_TargetV.x, m_TargetV.y, m_TargetV.z);

		uint8 NPCFlyMode = 0;

		if(IsNPC()) {
			if(CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
				NPCFlyMode = 1;
		}

		//fix up pathing Z
		if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving))
		{
			if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
			   (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
			{
				glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z);

				float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f;

				Log.Out(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x,m_Position.y,m_Position.z);

				if ((newz > -2000) &&
				    std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
				{
					if ((std::abs(x - m_Position.x) < 0.5) &&
					    (std::abs(y - m_Position.y) < 0.5)) {
						if (std::abs(z - m_Position.z) <=
						    RuleR(Map, FixPathingZMaxDeltaMoving))
							m_Position.z = z;
						else
							m_Position.z = newz + 1;
					}
					else
						m_Position.z = newz + 1;
				}
			}
		}

		tar_ndx++;
		return true;
	}


	if (tar_ndx>50) {
		tar_ndx--;
	} else {
		tar_ndx=0;
	}
	m_TargetLocation = glm::vec3(x, y, z);

	float nx = this->m_Position.x;
	float ny = this->m_Position.y;
	float nz = this->m_Position.z;
//	float nh = this->heading;

	m_TargetV.x = x - nx;
	m_TargetV.y = y - ny;
	m_TargetV.z = z - nz;
	SetCurrentSpeed((int8)speed);
	pRunAnimSpeed = speed;
	if(IsClient())
	{
		animation = speed / 2;
	}
	//pRunAnimSpeed = (int8)(speed*NPC_RUNANIM_RATIO);
	//speed *= NPC_SPEED_MULTIPLIER;

	Log.Out(Logs::Detail, Logs::AI, "Calculating new position2 to (%.3f, %.3f, %.3f), new vector (%.3f, %.3f, %.3f) rate %.3f, RAS %d", x, y, z, m_TargetV.x, m_TargetV.y, m_TargetV.z, speed, pRunAnimSpeed);

	// --------------------------------------------------------------------------
	// 2: get unit vector
	// --------------------------------------------------------------------------
	float mag = sqrtf (m_TargetV.x*m_TargetV.x + m_TargetV.y*m_TargetV.y + m_TargetV.z*m_TargetV.z);
	tar_vector = (float)speed / mag;

// mob move fix
	int numsteps = (int) ( mag * 16.0f / (float)speed + 0.5f);


// mob move fix

	if (numsteps<20)
	{
		if (numsteps>1)
		{
			tar_vector=1.0f	;
			m_TargetV.x = m_TargetV.x/(float)numsteps;
			m_TargetV.y = m_TargetV.y/(float)numsteps;
			m_TargetV.z = m_TargetV.z/(float)numsteps;

			float new_x = m_Position.x + m_TargetV.x;
			float new_y = m_Position.y + m_TargetV.y;
			float new_z = m_Position.z + m_TargetV.z;
			if(IsNPC()) {
				entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
			}

			m_Position.x = new_x;
			m_Position.y = new_y;
			m_Position.z = new_z;
			m_Position.w = CalculateHeadingToTarget(x, y);
			tar_ndx = 20 - numsteps;
			Log.Out(Logs::Detail, Logs::AI, "Next position2 (%.3f, %.3f, %.3f) (%d steps)", m_Position.x, m_Position.y, m_Position.z, numsteps);
		}
		else
		{
			if(IsNPC()) {
				entity_list.ProcessMove(CastToNPC(), x, y, z);
			}

			m_Position.x = x;
			m_Position.y = y;
			m_Position.z = z;

			Log.Out(Logs::Detail, Logs::AI, "Only a single step to get there... jumping.");

		}
	}

	else {
		tar_vector/=16.0f;
		float dur = Timer::GetCurrentTime() - pLastChange;
		if(dur < 1.0f) {
			dur = 1.0f;
		}
		tar_vector = (tar_vector * AImovement_duration) / 100.0f;

		float new_x = m_Position.x + m_TargetV.x*tar_vector;
		float new_y = m_Position.y + m_TargetV.y*tar_vector;
		float new_z = m_Position.z + m_TargetV.z*tar_vector;
		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
		}

		m_Position.x = new_x;
		m_Position.y = new_y;
		m_Position.z = new_z;
		m_Position.w = CalculateHeadingToTarget(x, y);
		Log.Out(Logs::Detail, Logs::AI, "Next position2 (%.3f, %.3f, %.3f) (%d steps)", m_Position.x, m_Position.y, m_Position.z, numsteps);
	}

	uint8 NPCFlyMode = 0;

	if(IsNPC()) {
		if(CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
			NPCFlyMode = 1;
	}

	//fix up pathing Z
	if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving)) {

		if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
		   (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
		{
			glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z);

			float newz = zone->zonemap->FindBestZ(dest, nullptr);

			Log.Out(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x, m_Position.y, m_Position.z);

			if ((newz > -2000) &&
			    std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
			{
				if (std::abs(x - m_Position.x) < 0.5 && std::abs(y - m_Position.y) < 0.5) {
					if (std::abs(z - m_Position.z) <= RuleR(Map, FixPathingZMaxDeltaMoving))
						m_Position.z = z;
					else
						m_Position.z = newz + 1;
				}
				else
					m_Position.z = newz+1;
				}
		}
	}

	SetMoving(true);
	moved=true;

	m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f);

	if (IsClient())
	{
		SendPosUpdate(1);
		CastToClient()->ResetPositionTimer();
	}
	else
	{
		SendPosUpdate();
		SetAppearance(eaStanding, false);
	}

	pLastChange = Timer::GetCurrentTime();
	return true;
}
Example #4
0
bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool checkZ) {
	if(GetID()==0)
		return true;

	if ((x_pos-x == 0) && (y_pos-y == 0)) {//spawn is at target coords
		if(z_pos-z != 0) {
			z_pos = z;
			mlog(AI__WAYPOINTS, "Calc Position2 (%.3f, %.3f, %.3f): Jumping pure Z.", x, y, z);
			return true;
		}
		mlog(AI__WAYPOINTS, "Calc Position2 (%.3f, %.3f, %.3f) inWater=%d: We are there.", x, y, z, inWater);
		return false;
	}
	else if ((ABS(x_pos - x) < 0.1) && (ABS(y_pos - y) < 0.1))
	{
		mlog(AI__WAYPOINTS, "Calc Position2 (%.3f, %.3f, %.3f): X/Y difference <0.1, Jumping to target.", x, y, z);

		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), x, y, z);
		}

		x_pos = x;
		y_pos = y;
		z_pos = z;
		return true;
	}

	int compare_steps = IsBoat() ? 1 : 20;
	if(tar_ndx < compare_steps && tarx==x && tary==y) {

		float new_x = x_pos + tar_vx*tar_vector;
		float new_y = y_pos + tar_vy*tar_vector;
		float new_z = z_pos + tar_vz*tar_vector;
		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
		}

		x_pos = new_x;
		y_pos = new_y;
		z_pos = new_z;

		mlog(AI__WAYPOINTS, "Calculating new position2 to (%.3f, %.3f, %.3f), old vector (%.3f, %.3f, %.3f)", x, y, z, tar_vx, tar_vy, tar_vz);

		uint8 NPCFlyMode = 0;

		if(IsNPC()) {
			if(CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
				NPCFlyMode = 1;
		}

		//fix up pathing Z
		if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving))
		{
			if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
				(zone->HasWaterMap() && !zone->watermap->InWater(x_pos, y_pos, z_pos)))
			{
				Map::Vertex dest(x_pos, y_pos, z_pos);

				float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f;

				mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos);

				if( (newz > -2000) && ABS(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
				{
					if((ABS(x - x_pos) < 0.5) && (ABS(y - y_pos) < 0.5))
					{
						if(ABS(z-z_pos) <= RuleR(Map, FixPathingZMaxDeltaMoving))
							z_pos = z;
						else
							z_pos = newz + 1;
					}
					else
						z_pos = newz + 1;
				}
			}
		}

		tar_ndx++;
		return true;
	}


	if (tar_ndx>50) {
		tar_ndx--;
	} else {
		tar_ndx=0;
	}
	tarx=x;
	tary=y;
	tarz=z;

	float nx = this->x_pos;
	float ny = this->y_pos;
	float nz = this->z_pos;
//	float nh = this->heading;

	tar_vx = x - nx;
	tar_vy = y - ny;
	tar_vz = z - nz;

	//pRunAnimSpeed = (int8)(speed*NPC_RUNANIM_RATIO);
	//speed *= NPC_SPEED_MULTIPLIER;

	mlog(AI__WAYPOINTS, "Calculating new position2 to (%.3f, %.3f, %.3f), new vector (%.3f, %.3f, %.3f) rate %.3f, RAS %d", x, y, z, tar_vx, tar_vy, tar_vz, speed, pRunAnimSpeed);

	// --------------------------------------------------------------------------
	// 2: get unit vector
	// --------------------------------------------------------------------------
	float mag = sqrtf (tar_vx*tar_vx + tar_vy*tar_vy + tar_vz*tar_vz);
	tar_vector = speed / mag;

// mob move fix
	int numsteps = (int) ( mag * 20 / speed) + 1;


// mob move fix

	if (numsteps<20)
	{
		if (numsteps>1)
		{
			tar_vector=1.0f				;
			tar_vx = tar_vx/numsteps;
			tar_vy = tar_vy/numsteps;
			tar_vz = tar_vz/numsteps;

			float new_x = x_pos + tar_vx;
			float new_y = y_pos + tar_vy;
			float new_z = z_pos + tar_vz;
			if(IsNPC()) {
				entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
			}

			x_pos = new_x;
			y_pos = new_y;
			z_pos = new_z;
			tar_ndx=22-numsteps;
			heading = CalculateHeadingToTarget(x, y);
			mlog(AI__WAYPOINTS, "Next position2 (%.3f, %.3f, %.3f) (%d steps)", x_pos, y_pos, z_pos, numsteps);
		}
		else
		{
			if(IsNPC()) {
				entity_list.ProcessMove(CastToNPC(), x, y, z);
			}

			x_pos = x;
			y_pos = y;
			z_pos = z;

			mlog(AI__WAYPOINTS, "Only a single step to get there... jumping.");

		}
	}

	else {
		tar_vector/=20;

		float new_x = x_pos + tar_vx*tar_vector;
		float new_y = y_pos + tar_vy*tar_vector;
		float new_z = z_pos + tar_vz*tar_vector;
		if(IsNPC()) {
			entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
		}

		x_pos = new_x;
		y_pos = new_y;
		z_pos = new_z;
		heading = CalculateHeadingToTarget(x, y);
		mlog(AI__WAYPOINTS, "Next position2 (%.3f, %.3f, %.3f) (%d steps)", x_pos, y_pos, z_pos, numsteps);
	}

	uint8 NPCFlyMode = 0;

	if(IsNPC()) {
		if(CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
			NPCFlyMode = 1;
	}

	//fix up pathing Z
	if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving)) {

		if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
			(zone->HasWaterMap() && !zone->watermap->InWater(x_pos, y_pos, z_pos)))
		{
			Map::Vertex dest(x_pos, y_pos, z_pos);

			float newz = zone->zonemap->FindBestZ(dest, nullptr); + 2.0f;

			mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos);

			if( (newz > -2000) && ABS(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
			{
				if(ABS(x - x_pos) < 0.5 && ABS(y - y_pos) < 0.5)
				{
					if(ABS(z - z_pos) <= RuleR(Map, FixPathingZMaxDeltaMoving))
						z_pos = z;
					else
						z_pos = newz + 1;
				}
				else
					z_pos = newz+1;
				}
		}
	}

	SetMoving(true);
	moved=true;

	delta_x=x_pos-nx;
	delta_y=y_pos-ny;
	delta_z=z_pos-nz;
	delta_heading=0;

	if (IsClient())
		SendPosUpdate(1);
	else
		SendPosUpdate();

	SetAppearance(eaStanding, false);
	pLastChange = Timer::GetCurrentTime();
	return true;
}