View Single Post
  #9  
Old 10-04-2015, 11:18 PM
rencro
Hill Giant
 
Join Date: Sep 2008
Location: So. California
Posts: 219
Default

Heres where I'm at, this uses its own code for bots movement while leaving haynars untouched for use with all other mob entities. I applied this to code pulled on 3 Oct 2015 and ran ok.

At least can have ok movement until someone is able to fix bots to work with haynar's movement code. Also, I did get my toilet fixed..

Code:
diff --git a/zone/bot.cpp b/zone/bot.cpp
index cbc951c..4a6e8af 100644
--- a/zone/bot.cpp
+++ b/zone/bot.cpp
@@ -242,8 +242,10 @@ void Bot::ChangeBotArcherWeapons(bool isArcher) {
 
 void Bot::Sit() {
 	if(IsMoving()) {
+		//SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget->GetY()));
 		moved = false;
-		SetCurrentSpeed(0);
+		SendPosition(); //rencro -- revert haynar on bots
+		SetMoving(false); //rencro -- revert haynar on bots
 		tar_ndx = 0;
 	}
 
@@ -318,7 +320,7 @@ NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::str
 	BotNPCType.d_melee_texture2 = 0;
 	BotNPCType.qglobal = false;
 	BotNPCType.attack_speed = 0;
-	BotNPCType.runspeed = 0.7f;
+	BotNPCType.runspeed = 1.25; //rencro -- revert haynar on bots
 	BotNPCType.bodytype = 1;
 	BotNPCType.findable = 0;
 	BotNPCType.hp_regen = 1;
@@ -349,7 +351,7 @@ NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string b
 	Result.drakkin_details = 0;
 	Result.drakkin_heritage = 0;
 	Result.drakkin_tattoo = 0;
-	Result.runspeed = 0.7f;
+	Result.runspeed = 1.25; //rencro revert haynar on bots
 	Result.bodytype = 1;
 	Result.findable = 0;
 	Result.hp_regen = 1;
@@ -2403,7 +2405,7 @@ void Bot::AI_Process() {
 				} else if(!IsRooted()) {
 					if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) {
 						Log.Out(Logs::Detail, Logs::AI, "Returning to location prior to being summoned.");
-						CalculateNewPosition2(m_PreSummonLocation.x, m_PreSummonLocation.y, m_PreSummonLocation.z, GetRunspeed());
+						CalculateNewPosition2(m_PreSummonLocation.x, m_PreSummonLocation.y, m_PreSummonLocation.z, GetBotRunspeed()); //rencro
 						SetHeading(CalculateHeadingToTarget(m_PreSummonLocation.x, m_PreSummonLocation.y));
 						return;
 					}
@@ -2478,9 +2480,11 @@ void Bot::AI_Process() {
 			if(IsMoving()) {
 				SetHeading(0);
 				SetRunAnimSpeed(0);
-				SetCurrentSpeed(GetRunspeed());
-				if(moved)
-					SetCurrentSpeed(0);
+				if (moved) {
+					moved = false; //rencro -- revert haynar on bots
+					SendPosition(); //rencro -- revert haynar on bots
+					SetMoving(false); //rencro -- revert haynar on bots
+				}
 			}
 			return;
 		}
@@ -2516,10 +2520,10 @@ void Bot::AI_Process() {
 			if(IsMoving()) {
 				SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
 				SetRunAnimSpeed(0);
-				SetCurrentSpeed(0);
 				if(moved) {
 					moved = false;
-					SetCurrentSpeed(0);
+					SendPosition(); //rencro -- revert haynar on bots
+					SetMoving(false); //rencro -- revert haynar on bots
 				}
 			}
 			atCombatRange = true;
@@ -2533,10 +2537,10 @@ void Bot::AI_Process() {
 		if(atCombatRange) {
 			if(IsMoving()) {
 				SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
-				SetCurrentSpeed(0);
 				if(moved) {
 					moved = false;
-					SetCurrentSpeed(0);
+					SendPosition(); //rencro -- revert haynar on bots
+					SetMoving(false); //rencro -- revert haynar on bots
 				}
 			}
 
@@ -2547,7 +2551,7 @@ void Bot::AI_Process() {
 					float newY = 0;
 					float newZ = 0;
 					if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) {
-						CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
+						CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed()); //rencro
 						return;
 					}
 				}
@@ -2557,7 +2561,7 @@ void Bot::AI_Process() {
 					float newY = 0;
 					float newZ = 0;
 					if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) {
-						CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
+						CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed()); //rencro
 						return;
 					}
 				}
@@ -2679,7 +2683,7 @@ void Bot::AI_Process() {
 			if (AImovement_timer->Check()) {
 				if(!IsRooted()) {
 					Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName());
-					CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed());
+					CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetBotRunspeed()); //rencro
 					return;
 				}
 
@@ -2718,9 +2722,9 @@ void Bot::AI_Process() {
 				Mob* follow = entity_list.GetMob(GetFollowID());
 				if(follow) {
 					float dist = DistanceSquared(m_Position, follow->GetPosition());
-					int speed = follow->GetRunspeed();
+					float speed = follow->GetBotRunspeed(); //rencro -- revert haynar on bots 0.6999..
 					if(dist < GetFollowDistance() + 1000)
-						speed = follow->GetWalkspeed();
+						speed = follow->GetBotWalkspeed();
 
 					if(dist > GetFollowDistance()) {
 						CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
@@ -2730,7 +2734,8 @@ void Bot::AI_Process() {
 					} else {
 						if(moved) {
 							moved = false;
-							SetCurrentSpeed(0);
+							SendPosition(); //rencro --revert haynar on bots
+							SetMoving(false); //rencro -- revert haynar on bots
 						}
 					}
 				}
@@ -2797,14 +2802,14 @@ void Bot::PetAIProcess() {
 				if(botPet->GetClass() == ROGUE && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) {
 					// Move the rogue to behind the mob
 					if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) {
-						botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetRunspeed());
+						botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetBotRunspeed()); //rencro
 						return;
 					}
 				}
 				else if(GetTarget() == botPet->GetTarget() && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) {
 					// If the bot owner and the bot are fighting the same mob, then move the pet to the rear arc of the mob
 					if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) {
-						botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetRunspeed());
+						botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetBotRunspeed()); //rencro
 						return;
 					}
 				}
@@ -2819,7 +2824,7 @@ void Bot::PetAIProcess() {
 						moveBehindMob = true;
 
 					if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ, moveBehindMob)) {
-						botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetRunspeed());
+						botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetBotRunspeed()); //rencro
 						return;
 					}
 				}
@@ -2902,13 +2907,13 @@ void Bot::PetAIProcess() {
 					botPet->SetRunAnimSpeed(0);
 					if(!botPet->IsRooted()) {
 						Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", botPet->GetTarget()->GetCleanName());
-						botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetOwner()->GetRunspeed());
+						botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetOwner()->GetBotRunspeed()); //rencro
 						return;
 					} else {
 						botPet->SetHeading(botPet->GetTarget()->GetHeading());
 						if(moved) {
 							moved = false;
-							SetCurrentSpeed(0);
+							//SetCurrentSpeed(0);
 							botPet->SendPosition();
 							botPet->SetMoving(false);
 						}
@@ -2930,13 +2935,13 @@ void Bot::PetAIProcess() {
 					float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition());
 					botPet->SetRunAnimSpeed(0);
 					if(dist > 184) {
-						botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetRunspeed());
+						botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetBotRunspeed()); //rencro
 						return;
 					} else {
 						botPet->SetHeading(botPet->GetTarget()->GetHeading());
 						if(moved) {
 							moved = false;
-							SetCurrentSpeed(0);
+							//SetCurrentSpeed(0);
 							botPet->SendPosition();
 							botPet->SetMoving(false);
 						}
@@ -8043,7 +8048,53 @@ bool Bot::CanHeal() {
 }
 
 bool Bot::CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ) {
-	return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ);
+	// 2.5625 is the inverse of 0.3902439. The only difference is in implementation.
+	// NOTE: You can not change just one of the constants below. They are the same number, just expressed inversly of each other.
+	// const float clientOverServerRatio = 2.5625f;
+	const float serverOverClientRatio = 0.3902439f;
+
+	// Use this block if using 2.5625 as the ratio.
+	// const int clientAnimationMovementRateTypeMultiple = 8;
+
+	//	WildcardX: These are valid rates and observations based on painstaking testing of the client response to these values
+	//
+	//
+	//	0 * 8 = 0 : No Movement
+	//	1 * 8 = 8 : Death Walk
+	//	2 * 8 = 16 : Slow Walk
+	//	3 * 8 = 24 : Normal Walk
+	//	4 * 8 = 32 : Jog
+	//	5 * 8 = 40 : Normal Run
+	//	6 * 8 = 48 : Faster Run
+	//	7 * 8 = 56 : Even Faster Run
+	//	8 * 8 = 64 : Fastest Yet Run (Bard Song Speed?)
+	//	9 * 8 = 72 : Faster Fastest Yet Run
+	//	10 * 8 = 80 : .... you get the idea, this is pretty fast
+	//	11 * 8 = 88 : .... warp speed anyone?
+	//	12 * 8 = 96 : .... transwarp drive was invented by gnomes in Norrath
+	//	13 * 8 = 104 : ... who needs warp drives when you can just displace through time and space?
+	//
+	//
+	//	You get the idea here with these... These seem to be "benchmark values" of animation movement and how fast
+	//	the client thinks the Mob is moving so it can make it all look seemless between updates from the server.
+	//	This chart is scalable by the client so you can pass an animation rate of 50 and get a "faster run" but not quite a "even faster run"
+
+	// Convert the Bot movement rate to a value the client understands based on the chart above
+	// Use this block if using 2.5625 as the ratio.
+	// speed *= clientMovementRateTypeMultiple;
+
+
+	// This sets the movement animation rate with the client
+	// Use this block if using 2.5625 as the ratio.
+	// pRunAnimSpeed = speed;
+	pRunAnimSpeed = ((serverOverClientRatio * 10.0f) * speed) * 10.0f;
+
+	// Now convert our "speed" from the value necessary for the client to animate the correct movement type rate to the server side speed
+	// Use this block if using 2.5625 as the ratio.
+	// speed *= serverOverClientRatio;
+	speed = pRunAnimSpeed / serverOverClientRatio;
+
+	return MakeNewBotPositionAndSendUpdate(x, y, z, speed, checkZ);
 }
 
 void Bot::BotGroupOrderFollow(Group* group, Client* client) {
diff --git a/zone/mob.cpp b/zone/mob.cpp
index 24f17a5..5251bbd 100644
--- a/zone/mob.cpp
+++ b/zone/mob.cpp
@@ -559,6 +555,66 @@ bool Mob::IsInvisible(Mob* other) const
 	return(false);
 }
 
+/* rencro -- bots with haynar need to walk through this part of code and remove non bot stuff*/
+float Mob::_GetMovementSpeed(int mod) const
+{
+	/*
+	if (mod >= 0) {
+		return 0.6f;
+	}
+	else {
+		return 0.4f;
+	} */
+	if (IsRooted())
+		return 0.0f;
+	else if (IsPseudoRooted())
+		return 0.00001f;
+
+	float speed_mod = 0.6f; //seems to work ok so far
+
+	int aa_mod = 0;
+	int spell_mod = 0;
+	int runspeedcap = RuleI(Character, BaseRunSpeedCap);
+	int movemod = 0;
+	float frunspeedcap = 0.0f;
+
+	runspeedcap += itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap;
+	aa_mod += itembonuses.BaseMovementSpeed + spellbonuses.BaseMovementSpeed + aabonuses.BaseMovementSpeed;
+	spell_mod += spellbonuses.movementspeed + itembonuses.movementspeed;
+
+	//hard cap
+	if (runspeedcap > 225)
+		runspeedcap = 225;
+
+	if (spell_mod < 0)
+		movemod += spell_mod;
+	else if (spell_mod > aa_mod)
+		movemod = spell_mod;
+	else
+		movemod = aa_mod;
+
+	// cap negative movemods from snares mostly
+	if (movemod < -85)
+		movemod = -85;
+
+	if (movemod != 0)
+		speed_mod += speed_mod * static_cast<float>(movemod) / 100.0f;
+
+	//runspeed caps
+	frunspeedcap = static_cast<float>(runspeedcap) / 100.0f;
+
+	//apply final mod such as the -47 for walking
+	// use runspeed since it should stack with snares
+	// blah blah blah
+	if (mod != 0)
+		speed_mod += runspeed * static_cast<float>(mod) / 100.0f;
+
+	if (speed_mod <= 0.0f)
+		speed_mod = 0.0f;
+
+	return speed_mod;
+}
+
 int Mob::_GetWalkSpeed() const {
 
 	if (IsRooted() || IsStunned() || IsMezzed())
@@ -1384,6 +1440,8 @@ void Mob::SendPosition()
 	PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
 	MakeSpawnUpdateNoDelta(spu);
 	move_tic_count = 0;
+	if (IsBot())
+		tar_ndx = 20; //rencro -- bots with haynar
 	entity_list.QueueClients(this, app, true);
 	safe_delete(app);
 }
diff --git a/zone/mob.h b/zone/mob.h
index 6510652..d134022 100644
--- a/zone/mob.h
+++ b/zone/mob.h
@@ -464,6 +464,11 @@ public:
 	virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); }
 	virtual void GoToBind(uint8 bindnum = 0) { }
 	virtual void Gate();
+	/* rencro -- add bots around haynar */	
+	float GetBotWalkspeed() const { return(_GetMovementSpeed(-47)); }
+	float GetBotRunspeed() const { return(_GetMovementSpeed(0)); }
+	float GetBotBaseRunspeed() const { return runspeed; }
+	/* rencro -- add bots around haynar */
 	int GetWalkspeed() const { return(_GetWalkSpeed()); }
 	int GetRunspeed() const { return(_GetRunSpeed()); }
 	void SetCurrentSpeed(int in);
@@ -998,6 +1003,7 @@ protected:
 	int _GetRunSpeed() const;
 	int _GetFearSpeed() const;
 	virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ);
+	virtual bool MakeNewBotPositionAndSendUpdate(float x, float y, float z, float speed, bool checkZ); //rencro -- add bots around haynar code
 
 	virtual bool AI_EngagedCastCheck() { return(false); }
 	virtual bool AI_PursueCastCheck() { return(false); }
diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp
index e900c68..cf04ecf 100644
--- a/zone/waypoints.cpp
+++ b/zone/waypoints.cpp
@@ -708,6 +708,212 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
 	pLastChange = Timer::GetCurrentTime();
 	return true;
 }
+/* rencro add bots around haynar */
+bool Mob::MakeNewBotPositionAndSendUpdate(float x, float y, float z, float speed, bool checkZ) {
+	if(GetID()==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);
+
+		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);
+
+		//fix up pathing Z
+		if(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;
+	//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 = 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 / numsteps;
+			m_TargetV.y = m_TargetV.y / numsteps;
+			m_TargetV.z = m_TargetV.z / 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
+		{
+			m_Position.x = x;
+			m_Position.y = y;
+			m_Position.z = z;
+
+			tar_ndx = 20;
+			Log.Out(Logs::Detail, Logs::AI, "Only a single step to get there... jumping.");
+		}
+	}
+
+	else {
+		tar_vector /= 20.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);
+	}
+
+	//fix up pathing Z
+	if(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
+	{
+		move_tic_count = RuleI(Zone, NPCPositonUpdateTicCount); //wtf is Positon??
+		SendPosUpdate();
+		SetAppearance(eaStanding, false);
+	}
+	pLastChange = Timer::GetCurrentTime();
+	return true;
+}
 
 bool Mob::CalculateNewPosition2(float x, float y, float z, int speed, bool checkZ, bool calcHeading) {
 	return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ);
Reply With Quote