1
0
Fork 0

Mob bugfixes

* Mobs no longer require constant line-of-sight to a player to remain
aggravated
* Fixed an ASSERT
* Fixed mobs jumping
* Fixed Idle state not properly using AI
+ Added FILE_IO_PREFIX to favicon loading
+ Implemented #563
This commit is contained in:
Tiger Wang 2014-01-25 14:42:26 +00:00
parent fd7fc7e59e
commit 314fc3cdac
6 changed files with 54 additions and 26 deletions

View File

@ -223,6 +223,8 @@ void cChunkGenerator::Execute(void)
if (m_Queue.empty()) if (m_Queue.empty())
{ {
// Sometimes the queue remains empty
// If so, we can't do any front() operations on it!
continue; continue;
} }

View File

@ -259,6 +259,17 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
if (m_bMovingToDestination) if (m_bMovingToDestination)
{ {
if (m_bOnGround)
{
int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z);
if (DoesPosYRequireJump(NextHeight))
{
m_bOnGround = false;
AddPosY(1.5); // Jump!!
}
}
Vector3f Distance = m_Destination - GetPosition(); Vector3f Distance = m_Destination - GetPosition();
if(!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move if(!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move
{ {
@ -285,17 +296,6 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
TickPathFinding(); // We have reached the next point in our path, calculate another point TickPathFinding(); // We have reached the next point in our path, calculate another point
} }
} }
if(m_bOnGround)
{
int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z);
if (IsNextYPosReachable(NextHeight))
{
m_bOnGround = false;
SetSpeedY(5.f); // Jump!!
}
}
} }
if (ReachedFinalDestination()) if (ReachedFinalDestination())
@ -373,6 +373,11 @@ int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ)
{ {
int PosY = (int)floor(GetPosY()); int PosY = (int)floor(GetPosY());
if (PosY < 0)
PosY = 0;
else if (PosY > cChunkDef::Height)
PosY = cChunkDef::Height;
if (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))]) if (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))])
{ {
while (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))] && (PosY > 0)) while (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))] && (PosY > 0))
@ -494,7 +499,7 @@ void cMonster::KilledBy(cEntity * a_Killer)
void cMonster::CheckEventSeePlayer(void) void cMonster::CheckEventSeePlayer(void)
{ {
// TODO: Rewrite this to use cWorld's DoWithPlayers() // TODO: Rewrite this to use cWorld's DoWithPlayers()
cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance, false);
if (Closest != NULL) if (Closest != NULL)
{ {
@ -548,6 +553,11 @@ void cMonster::EventLosePlayer(void)
void cMonster::InStateIdle(float a_Dt) void cMonster::InStateIdle(float a_Dt)
{ {
if (m_bMovingToDestination)
{
return; // Still getting there
}
m_IdleInterval += a_Dt; m_IdleInterval += a_Dt;
if (m_IdleInterval > 1) if (m_IdleInterval > 1)
@ -557,20 +567,19 @@ void cMonster::InStateIdle(float a_Dt)
m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds
Vector3d Dist; Vector3d Dist;
Dist.x = (double)m_World->GetTickRandomNumber(m_SightDistance * 2) - m_SightDistance; Dist.x = (double)m_World->GetTickRandomNumber(10) - 5;
Dist.z = (double)m_World->GetTickRandomNumber(m_SightDistance * 2) - m_SightDistance; Dist.z = (double)m_World->GetTickRandomNumber(10) - 5;
if ((Dist.SqrLength() > 2) && (rem >= 3)) if ((Dist.SqrLength() > 2) && (rem >= 3))
{ {
m_Destination.x = GetPosX() + Dist.x; Vector3d Destination(GetPosX() + Dist.x, 0, GetPosZ() + Dist.z);
m_Destination.z = GetPosZ() + Dist.z;
int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); int NextHeight = FindFirstNonAirBlockPosition(Destination.x, Destination.z);
if (IsNextYPosReachable(NextHeight + 1)) if (IsNextYPosReachable(NextHeight))
{ {
m_Destination.y = (double)NextHeight; Destination.y = NextHeight;
MoveToPosition(m_Destination); MoveToPosition(Destination);
} }
} }
} }

View File

@ -168,10 +168,18 @@ protected:
If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1 If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1
If current Y is solid, goes up to find first nonsolid block, and returns that */ If current Y is solid, goes up to find first nonsolid block, and returns that */
int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ); int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ);
/** Returns if a monster can actually reach a given height by jumping */ /** Returns if a monster can actually reach a given height by jumping or walking */
inline bool IsNextYPosReachable(int a_PosY) inline bool IsNextYPosReachable(int a_PosY)
{ {
return (a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1); return (
(a_PosY <= (int)floor(GetPosY())) ||
DoesPosYRequireJump(a_PosY)
);
}
/** Returns if a monster can reach a given height by jumping */
inline bool DoesPosYRequireJump(int a_PosY)
{
return ((a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1));
} }
/** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */ /** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */

View File

@ -194,7 +194,7 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
m_PlayerCount = 0; m_PlayerCount = 0;
m_PlayerCountDiff = 0; m_PlayerCountDiff = 0;
m_FaviconData = Base64Encode(cFile::ReadWholeFile("favicon.png")); // Will return empty string if file nonexistant; client doesn't mind m_FaviconData = Base64Encode(cFile::ReadWholeFile(FILE_IO_PREFIX + AString("favicon.png"))); // Will return empty string if file nonexistant; client doesn't mind
if (m_bIsConnected) if (m_bIsConnected)
{ {

View File

@ -234,7 +234,11 @@ cWorld::cWorld(const AString & a_WorldName) :
m_WorldName(a_WorldName), m_WorldName(a_WorldName),
m_IniFileName(m_WorldName + "/world.ini"), m_IniFileName(m_WorldName + "/world.ini"),
m_StorageSchema("Default"), m_StorageSchema("Default"),
#ifdef _arm_
m_StorageCompressionFactor(3),
#else
m_StorageCompressionFactor(6), m_StorageCompressionFactor(6),
#endif
m_IsSpawnExplicitlySet(false), m_IsSpawnExplicitlySet(false),
m_WorldAgeSecs(0), m_WorldAgeSecs(0),
m_TimeOfDaySecs(0), m_TimeOfDaySecs(0),
@ -2419,7 +2423,7 @@ bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCa
// TODO: This interface is dangerous! // TODO: This interface is dangerous!
cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit) cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit, bool a_CheckLineOfSight)
{ {
cTracer LineOfSight(this); cTracer LineOfSight(this);
@ -2434,7 +2438,12 @@ cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit)
if (Distance < ClosestDistance) if (Distance < ClosestDistance)
{ {
if (!LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length())) if (a_CheckLineOfSight && !LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length()))
{
ClosestDistance = Distance;
ClosestPlayer = *itr;
}
else
{ {
ClosestDistance = Distance; ClosestDistance = Distance;
ClosestPlayer = *itr; ClosestPlayer = *itr;

View File

@ -239,7 +239,7 @@ public:
bool FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << bool FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
// TODO: This interface is dangerous - rewrite to DoWithClosestPlayer(pos, sight, action) // TODO: This interface is dangerous - rewrite to DoWithClosestPlayer(pos, sight, action)
cPlayer * FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit); cPlayer * FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit, bool a_CheckLineOfSight = true);
void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player