summaryrefslogtreecommitdiffstats
path: root/src/Mobs/Monster.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Mobs/Monster.cpp')
-rw-r--r--src/Mobs/Monster.cpp60
1 files changed, 43 insertions, 17 deletions
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index fa36285ba..7d8c3de02 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -133,9 +133,8 @@ void cMonster::MoveToWayPoint(cChunk & a_Chunk)
{
if (DoesPosYRequireJump(FloorC(m_NextWayPointPosition.y)))
{
- if (
- (IsOnGround() && (GetSpeedX() == 0.0f) && (GetSpeedY() == 0.0f)) // TODO water handling?
- )
+ if (((IsOnGround()) && (GetSpeed().SqrLength() == 0.0f)) ||
+ (IsSwimming()))
{
m_bOnGround = false;
m_JumpCoolDown = 20;
@@ -303,18 +302,18 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
case IDLE:
{
// If enemy passive we ignore checks for player visibility.
- InStateIdle(a_Dt);
+ InStateIdle(a_Dt, a_Chunk);
break;
}
case CHASING:
{
// If we do not see a player anymore skip chasing action.
- InStateChasing(a_Dt);
+ InStateChasing(a_Dt, a_Chunk);
break;
}
case ESCAPING:
{
- InStateEscaping(a_Dt);
+ InStateEscaping(a_Dt, a_Chunk);
break;
}
case ATTACKING: break;
@@ -377,7 +376,7 @@ void cMonster::SetPitchAndYawFromDestination(bool a_IsFollowingPath)
double HeadRotation, HeadPitch;
HeadDistance.Normalize();
VectorToEuler(HeadDistance.x, HeadDistance.y, HeadDistance.z, HeadRotation, HeadPitch);
- if (std::abs(BodyRotation - HeadRotation) < 90)
+ if ((std::abs(BodyRotation - HeadRotation) < 70) && (std::abs(HeadPitch) < 60))
{
SetHeadYaw(HeadRotation);
SetPitch(-HeadPitch);
@@ -385,7 +384,7 @@ void cMonster::SetPitchAndYawFromDestination(bool a_IsFollowingPath)
else
{
SetHeadYaw(BodyRotation);
- SetPitch(-BodyPitch);
+ SetPitch(0);
}
}
@@ -611,7 +610,7 @@ void cMonster::EventLosePlayer(void)
-void cMonster::InStateIdle(std::chrono::milliseconds a_Dt)
+void cMonster::InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
if (m_PathfinderActivated)
{
@@ -632,9 +631,24 @@ void cMonster::InStateIdle(std::chrono::milliseconds a_Dt)
if ((Dist.SqrLength() > 2) && (rem >= 3))
{
- Vector3d Destination(GetPosX() + Dist.x, 0, GetPosZ() + Dist.z);
- Destination.y = FindFirstNonAirBlockPosition(Destination.x, Destination.z);
- MoveToPosition(Destination);
+
+ Vector3d Destination(GetPosX() + Dist.x, GetPosition().y, GetPosZ() + Dist.z);
+
+ cChunk * Chunk = a_Chunk.GetNeighborChunk(static_cast<int>(Destination.x), static_cast<int>(Destination.z));
+ if ((Chunk == nullptr) || !Chunk->IsValid())
+ {
+ return;
+ }
+
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ int RelX = static_cast<int>(Destination.x) - Chunk->GetPosX() * cChunkDef::Width;
+ int RelZ = static_cast<int>(Destination.z) - Chunk->GetPosZ() * cChunkDef::Width;
+ Chunk->GetBlockTypeMeta(RelX, static_cast<int>(Destination.y) - 1, RelZ, BlockType, BlockMeta);
+ if (BlockType != E_BLOCK_STATIONARY_WATER) // Idle mobs shouldn't enter water on purpose
+ {
+ MoveToPosition(Destination);
+ }
}
}
}
@@ -645,7 +659,7 @@ void cMonster::InStateIdle(std::chrono::milliseconds a_Dt)
// What to do if in Chasing State
// This state should always be defined in each child class
-void cMonster::InStateChasing(std::chrono::milliseconds a_Dt)
+void cMonster::InStateChasing(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
UNUSED(a_Dt);
}
@@ -655,7 +669,7 @@ void cMonster::InStateChasing(std::chrono::milliseconds a_Dt)
// What to do if in Escaping State
-void cMonster::InStateEscaping(std::chrono::milliseconds a_Dt)
+void cMonster::InStateEscaping(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
UNUSED(a_Dt);
@@ -1084,6 +1098,19 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk, bool WouldBurn)
bool cMonster::WouldBurnAt(Vector3d a_Location, cChunk & a_Chunk)
{
+ // If the Y coord is out of range, return the most logical result without considering anything else:
+ int RelY = FloorC(a_Location.y);
+ if (RelY < 0)
+ {
+ // Never burn under the world
+ return false;
+ }
+ if (RelY >= cChunkDef::Height)
+ {
+ // Always burn above the world
+ return true;
+ }
+
cChunk * Chunk = a_Chunk.GetNeighborChunk(FloorC(a_Location.x), FloorC(a_Location.z));
if ((Chunk == nullptr) || (!Chunk->IsValid()))
{
@@ -1091,14 +1118,13 @@ bool cMonster::WouldBurnAt(Vector3d a_Location, cChunk & a_Chunk)
}
int RelX = FloorC(a_Location.x) - Chunk->GetPosX() * cChunkDef::Width;
- int RelY = FloorC(a_Location.y);
int RelZ = FloorC(a_Location.z) - Chunk->GetPosZ() * cChunkDef::Width;
if (
(Chunk->GetSkyLight(RelX, RelY, RelZ) == 15) && // In the daylight
(Chunk->GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand
- (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime
- GetWorld()->IsWeatherSunnyAt(POSX_TOINT, POSZ_TOINT) // Not raining
+ (GetWorld()->GetTimeOfDay() < 12000 + 1000) && // Daytime
+ GetWorld()->IsWeatherSunnyAt(POSX_TOINT, POSZ_TOINT) // Not raining
)
{
return true;