Example #1
0
void cWolf::TickFollowPlayer()
{
	class cCallback :
		public cPlayerListCallback
	{
		virtual bool Item(cPlayer * a_Player) override
		{
			OwnerPos = a_Player->GetPosition();
			return false;
		}
	public:
		Vector3d OwnerPos;
	} Callback;

	if (m_World->DoWithPlayer(m_OwnerName, Callback))
	{
		// The player is present in the world, follow him:
		double Distance = (Callback.OwnerPos - GetPosition()).Length();
		if (Distance > 20)
		{
			Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z);
			TeleportToCoords(m_World, Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z);
		}
		else
		{
			MoveToPosition(Callback.OwnerPos);
		}
	}
}
Example #2
0
void cMonster::InStateIdle(std::chrono::milliseconds a_Dt)
{
	if (m_IsFollowingPath)
	{
		return;  // Still getting there
	}

	m_IdleInterval += a_Dt;

	if (m_IdleInterval > std::chrono::seconds(1))
	{
		// At this interval the results are predictable
		int rem = m_World->GetTickRandomNumber(6) + 1;
		m_IdleInterval -= std::chrono::seconds(1);  // So nothing gets dropped when the server hangs for a few seconds

		Vector3d Dist;
		Dist.x = (double)m_World->GetTickRandomNumber(10) - 5;
		Dist.z = (double)m_World->GetTickRandomNumber(10) - 5;

		if ((Dist.SqrLength() > 2)  && (rem >= 3))
		{
			Vector3d Destination(GetPosX() + Dist.x, 0, GetPosZ() + Dist.z);
			Destination.y = FindFirstNonAirBlockPosition(Destination.x, Destination.z);
			MoveToPosition(Destination);
		}
	}
}
Example #3
0
void cMonster::InStateIdle(float a_Dt)
{
	if (m_bMovingToDestination)
	{
		return; // Still getting there
	}

	m_IdleInterval += a_Dt;

	if (m_IdleInterval > 1)
	{
		// At this interval the results are predictable
		int rem = m_World->GetTickRandomNumber(6) + 1;
		m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds

		Vector3d Dist;
		Dist.x = (double)m_World->GetTickRandomNumber(10) - 5;
		Dist.z = (double)m_World->GetTickRandomNumber(10) - 5;

		if ((Dist.SqrLength() > 2)  && (rem >= 3))
		{
			Vector3d Destination(GetPosX() + Dist.x, 0, GetPosZ() + Dist.z);

			int NextHeight = FindFirstNonAirBlockPosition(Destination.x, Destination.z);

			if (IsNextYPosReachable(NextHeight))
			{
				Destination.y = NextHeight;
				MoveToPosition(Destination);
			}
		}
	}
}
Example #4
0
void cWolf::TickFollowPlayer()
{
	Vector3d OwnerPos;
	bool OwnerFlying;
	auto Callback = [&](cPlayer & a_Player)
	{
		OwnerPos = a_Player.GetPosition();
		OwnerFlying = a_Player.IsFlying();
		return true;
	};

	if (m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback))
	{
		// The player is present in the world, follow him:
		double Distance = (OwnerPos - GetPosition()).Length();
		if (Distance > 20)
		{
			if (!OwnerFlying)
			{
				OwnerPos.y = FindFirstNonAirBlockPosition(OwnerPos.x, OwnerPos.z);
				TeleportToCoords(OwnerPos.x, OwnerPos.y, OwnerPos.z);
				SetTarget(nullptr);
			}
		}
		if (Distance < 2)
		{
			if (GetTarget() == nullptr)
			{
				StopMovingToPosition();
			}
		}
		else
		{
			if (GetTarget() == nullptr)
			{
				if (!OwnerFlying)
				{
					MoveToPosition(OwnerPos);
				}
			}
		}
	}
}
Example #5
0
void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
{
	super::Tick(a_Dt, a_Chunk);

	if (m_Health <= 0)
	{
		// The mob is dead, but we're still animating the "puff" they leave when they die
		m_DestroyTimer += a_Dt / 1000;
		if (m_DestroyTimer > 1)
		{
			Destroy(true);
		}
		return;
	}

	if ((m_Target != NULL) && m_Target->IsDestroyed())
		m_Target = NULL;

	// Burning in daylight
	HandleDaylightBurning(a_Chunk);

	a_Dt /= 1000;

	if (m_bMovingToDestination)
	{
		if (m_bOnGround)
		{
			m_Destination.y = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z);

			if (DoesPosYRequireJump((int)floor(m_Destination.y)))
			{
				m_bOnGround = false;
				AddPosY(1.5); // Jump!!
			}
		}

		Vector3f Distance = m_Destination - GetPosition();
		if(!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move
		{
			Distance.y = 0;
			Distance.Normalize();
			Distance *= 5;
			SetSpeedX(Distance.x);
			SetSpeedZ(Distance.z);

			if (m_EMState == ESCAPING)
			{	//Runs Faster when escaping :D otherwise they just walk away
				SetSpeedX (GetSpeedX() * 2.f);
				SetSpeedZ (GetSpeedZ() * 2.f);
			}
		}
		else
		{
			if (ReachedFinalDestination()) // If we have reached the ultimate, final destination, stop pathfinding and attack if appropriate
			{
				FinishPathFinding();
			}
			else
			{
				TickPathFinding(); // We have reached the next point in our path, calculate another point
			}
		}
	}

	SetPitchAndYawFromDestination();
	HandleFalling();

	switch (m_EMState)
	{
		case IDLE:
		{
			// If enemy passive we ignore checks for player visibility
			InStateIdle(a_Dt);
			break;
		}	
		case CHASING:
		{
			// If we do not see a player anymore skip chasing action
			InStateChasing(a_Dt);
			break;
		}	
		case ESCAPING:
		{
			InStateEscaping(a_Dt);
			break;
		}
	}  // switch (m_EMState)

	BroadcastMovementUpdate();
}
Example #6
0
void cMonster::TickPathFinding()
{
	const int PosX = POSX_TOINT;
	const int PosY = POSY_TOINT;
	const int PosZ = POSZ_TOINT;

	m_FinalDestination.y = (double)FindFirstNonAirBlockPosition(m_FinalDestination.x, m_FinalDestination.z);

	std::vector<Vector3d> m_PotentialCoordinates;
	m_TraversedCoordinates.push_back(Vector3i(PosX, PosY, PosZ));

	static const struct // Define which directions to try to move to
	{
		int x, z;
	} gCrossCoords[] =
	{
		{ 1, 0},
		{-1, 0},
		{ 0, 1},
		{ 0,-1},
	} ;
	
	if ((PosY - 1 < 0) || (PosY + 2 > cChunkDef::Height) /* PosY + 1 will never be true if PosY + 2 is not */)
	{
		// Too low/high, can't really do anything
		FinishPathFinding();
		return;
	}

	for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
	{
		if (IsCoordinateInTraversedList(Vector3i(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ)))
		{
			continue;
		}

		BLOCKTYPE BlockAtY = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ);
		BLOCKTYPE BlockAtYP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 1, gCrossCoords[i].z + PosZ);
		BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ);
		int LowestY = FindFirstNonAirBlockPosition(gCrossCoords[i].x + PosX, gCrossCoords[i].z + PosZ);
		BLOCKTYPE BlockAtLowestY = m_World->GetBlock(gCrossCoords[i].x + PosX, LowestY, gCrossCoords[i].z + PosZ);

		if (
			(!cBlockInfo::IsSolid(BlockAtY)) &&
			(!cBlockInfo::IsSolid(BlockAtYP)) &&
			(!IsBlockLava(BlockAtLowestY)) &&
			(BlockAtLowestY != E_BLOCK_CACTUS) &&
			(PosY - LowestY < FALL_DAMAGE_HEIGHT)
			)
		{
			m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY, gCrossCoords[i].z + PosZ));
		}
		else if (
			(cBlockInfo::IsSolid(BlockAtY)) &&
			(BlockAtY != E_BLOCK_CACTUS) &&
			(!cBlockInfo::IsSolid(BlockAtYP)) &&
			(!cBlockInfo::IsSolid(BlockAtYPP)) &&
			(BlockAtY != E_BLOCK_FENCE) &&
			(BlockAtY != E_BLOCK_FENCE_GATE)
			)
		{
			m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY + 1, gCrossCoords[i].z + PosZ));
		}
	}

	if (!m_PotentialCoordinates.empty())
	{
		Vector3f ShortestCoords = m_PotentialCoordinates.front();
		for (std::vector<Vector3d>::const_iterator itr = m_PotentialCoordinates.begin(); itr != m_PotentialCoordinates.end(); ++itr)
		{
			Vector3f Distance = m_FinalDestination - ShortestCoords;
			Vector3f Distance2 = m_FinalDestination - *itr;
			if (Distance.SqrLength() > Distance2.SqrLength())
			{
				ShortestCoords = *itr;
			}
		}

		m_Destination = ShortestCoords;
		m_Destination.z += 0.5f;
		m_Destination.x += 0.5f;
	}
	else
	{
		FinishPathFinding();
	}
}
Example #7
0
void cMonster::TickPathFinding()
{
	int PosX = (int)floor(GetPosX());
	int PosY = (int)floor(GetPosY());
	int PosZ = (int)floor(GetPosZ());

	m_FinalDestination.y = (double)FindFirstNonAirBlockPosition(m_FinalDestination.x, m_FinalDestination.z);

	std::vector<Vector3d> m_PotentialCoordinates;
	m_TraversedCoordinates.push_back(Vector3i(PosX, PosY, PosZ));

	static const struct // Define which directions to try to move to
	{
		int x, z;
	} gCrossCoords[] =
	{
		{ 1, 0},
		{-1, 0},
		{ 0, 1},
		{ 0,-1},
	} ;

	for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
	{
		if ((gCrossCoords[i].x + PosX == PosX) && (gCrossCoords[i].z + PosZ == PosZ))
		{
			continue;
		}

		if (IsCoordinateInTraversedList(Vector3i(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ)))
		{
			continue;
		}

		BLOCKTYPE BlockAtY = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ);
		BLOCKTYPE BlockAtYP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 1, gCrossCoords[i].z + PosZ);
		BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ);
		BLOCKTYPE BlockAtYM = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY - 1, gCrossCoords[i].z + PosZ);

		if ((!g_BlockIsSolid[BlockAtY]) && (!g_BlockIsSolid[BlockAtYP]) && (!IsBlockLava(BlockAtYM)) && (BlockAtY != E_BLOCK_FENCE) && (BlockAtY != E_BLOCK_FENCE_GATE))
		{
			m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY, gCrossCoords[i].z + PosZ));
		}
		else if ((g_BlockIsSolid[BlockAtY]) && (!g_BlockIsSolid[BlockAtYP]) && (!g_BlockIsSolid[BlockAtYPP]) && (!IsBlockLava(BlockAtYM)) && (BlockAtY != E_BLOCK_FENCE) && (BlockAtY != E_BLOCK_FENCE_GATE))
		{
			m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY + 1, gCrossCoords[i].z + PosZ));
		}
	}

	if (!m_PotentialCoordinates.empty())
	{
		Vector3f ShortestCoords = m_PotentialCoordinates.front();
		for (std::vector<Vector3d>::const_iterator itr = m_PotentialCoordinates.begin(); itr != m_PotentialCoordinates.end(); ++itr)
		{
			Vector3f Distance = m_FinalDestination - ShortestCoords;
			Vector3f Distance2 = m_FinalDestination - *itr;
			if (Distance.SqrLength() > Distance2.SqrLength())
			{
				ShortestCoords = *itr;
			}
		}

		m_Destination = ShortestCoords;
		m_Destination.z += 0.5f;
		m_Destination.x += 0.5f;
	}
	else
	{
		FinishPathFinding();
	}
}