1
0

Merge pull request #1927 from SafwatHalaby/AI_BetterDayLightHandling

AI - Much better burning/daylight behavior
This commit is contained in:
Tiger Wang 2015-05-02 16:50:08 +01:00
commit 114962943b
6 changed files with 22 additions and 63 deletions

View File

@ -142,7 +142,7 @@ void cMonster::TickPathFinding()
case ePathFinderStatus::PATH_NOT_FOUND: case ePathFinderStatus::PATH_NOT_FOUND:
{ {
FinishPathFinding(); ResetPathFinding();
break; break;
} }
@ -164,7 +164,7 @@ void cMonster::TickPathFinding()
} }
if (m_Path->IsLastPoint()) if (m_Path->IsLastPoint())
{ {
FinishPathFinding(); ResetPathFinding();
} }
break; break;
@ -191,7 +191,7 @@ void cMonster::MoveToPosition(const Vector3d & a_Position)
void cMonster::StopMovingToPosition() void cMonster::StopMovingToPosition()
{ {
m_bMovingToDestination = false; m_bMovingToDestination = false;
FinishPathFinding(); ResetPathFinding();
} }
@ -209,7 +209,7 @@ bool cMonster::IsCoordinateInTraversedList(Vector3i a_Coords)
/* No one should call this except the pathfinder orthe monster tick or StopMovingToPosition. /* No one should call this except the pathfinder orthe monster tick or StopMovingToPosition.
Resets the pathfinder, usually starting a brand new path, unless called from StopMovingToPosition. */ Resets the pathfinder, usually starting a brand new path, unless called from StopMovingToPosition. */
void cMonster::FinishPathFinding(void) void cMonster::ResetPathFinding(void)
{ {
if (m_Path != nullptr) if (m_Path != nullptr)
{ {
@ -254,6 +254,7 @@ bool cMonster::ReachedFinalDestination()
void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{ {
super::Tick(a_Dt, a_Chunk); super::Tick(a_Dt, a_Chunk);
GET_AND_VERIFY_CURRENT_CHUNK(Chunk, POSX_TOINT, POSZ_TOINT);
if (m_Health <= 0) if (m_Health <= 0)
{ {
@ -276,7 +277,8 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
} }
// Burning in daylight // Burning in daylight
HandleDaylightBurning(a_Chunk); bool WouldBurnRightNow = WouldBurnAt(GetPosition(), *Chunk); // cached so that we use it twice, spares some cycles.
HandleDaylightBurning(*Chunk, WouldBurnRightNow);
@ -300,7 +302,12 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{ {
if (--m_GiveUpCounter == 0) if (--m_GiveUpCounter == 0)
{ {
FinishPathFinding(); ResetPathFinding(); // Not to be confused with StopMovingToPosition, this just discards the current path and calculates another.
}
else if (m_BurnsInDaylight && WouldBurnAt(m_Destination, *Chunk) && !WouldBurnRightNow && (m_TicksSinceLastDamaged == 100))
{
// If we burn in daylight, and we would burn at the next step, and we won't burn where we are right now, and we weren't provoked recently:
StopMovingToPosition();
} }
else else
{ {
@ -1091,7 +1098,7 @@ void cMonster::AddRandomWeaponDropItem(cItems & a_Drops, short a_LootingLevel)
void cMonster::HandleDaylightBurning(cChunk & a_Chunk) void cMonster::HandleDaylightBurning(cChunk & a_Chunk, bool WouldBurn)
{ {
if (!m_BurnsInDaylight) if (!m_BurnsInDaylight)
{ {
@ -1110,7 +1117,7 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk)
return; return;
} }
if (WouldBurnAt(GetPosition(), a_Chunk)) if (!IsOnFire() && WouldBurn)
{ {
// Burn for 100 ticks, then decide again // Burn for 100 ticks, then decide again
StartBurning(100); StartBurning(100);
@ -1129,7 +1136,6 @@ bool cMonster::WouldBurnAt(Vector3d a_Location, cChunk & a_Chunk)
(a_Chunk.GetSkyLight(RelX, RelY, RelZ) == 15) && // In the daylight (a_Chunk.GetSkyLight(RelX, RelY, RelZ) == 15) && // In the daylight
(a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand
(GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime
!IsOnFire() && // Not already burning
GetWorld()->IsWeatherSunnyAt(POSX_TOINT, POSZ_TOINT) // Not raining GetWorld()->IsWeatherSunnyAt(POSX_TOINT, POSZ_TOINT) // Not raining
) )
{ {

View File

@ -208,7 +208,7 @@ protected:
This is based on the ultimate, final destination and the current position, as well as the traversed coordinates, and any environmental hazards */ This is based on the ultimate, final destination and the current position, as well as the traversed coordinates, and any environmental hazards */
void TickPathFinding(void); void TickPathFinding(void);
/** Finishes a pathfinding task, be it due to failure or something else */ /** Finishes a pathfinding task, be it due to failure or something else */
void FinishPathFinding(void); void ResetPathFinding(void);
/** Sets the body yaw and head yaw/pitch based on next/ultimate destinations */ /** Sets the body yaw and head yaw/pitch based on next/ultimate destinations */
void SetPitchAndYawFromDestination(void); void SetPitchAndYawFromDestination(void);
@ -244,7 +244,7 @@ protected:
bool m_CanPickUpLoot; bool m_CanPickUpLoot;
int m_TicksSinceLastDamaged; // How many ticks ago we were last damaged by a player? int m_TicksSinceLastDamaged; // How many ticks ago we were last damaged by a player?
void HandleDaylightBurning(cChunk & a_Chunk); void HandleDaylightBurning(cChunk & a_Chunk, bool WouldBurn);
bool WouldBurnAt(Vector3d a_Location, cChunk & a_Chunk); bool WouldBurnAt(Vector3d a_Location, cChunk & a_Chunk);
bool m_BurnsInDaylight; bool m_BurnsInDaylight;
double m_RelativeWalkSpeed; double m_RelativeWalkSpeed;

View File

@ -48,26 +48,6 @@ void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cSkeleton::MoveToPosition(const Vector3d & a_Position)
{
// Todo use WouldBurnAt(), not sure how to obtain a chunk though...
super::MoveToPosition(a_Position); // Look at the player and update m_Destination to hit them if they're close
// If the destination is sufficiently skylight challenged AND the skeleton isn't on fire AND we weren't attacked recently then block the movement
if (
!IsOnFire() &&
(m_World->GetBlockSkyLight((int)floor(a_Position.x), (int)floor(a_Position.y), (int)floor(a_Position.z)) - m_World->GetSkyDarkness() > 8) &&
m_TicksSinceLastDamaged == 100
)
{
StopMovingToPosition();
}
}
void cSkeleton::Attack(std::chrono::milliseconds a_Dt) void cSkeleton::Attack(std::chrono::milliseconds a_Dt)
{ {
m_AttackInterval += (static_cast<float>(a_Dt.count()) / 1000) * m_AttackRate; m_AttackInterval += (static_cast<float>(a_Dt.count()) / 1000) * m_AttackRate;

View File

@ -18,7 +18,6 @@ public:
CLASS_PROTODEF(cSkeleton) CLASS_PROTODEF(cSkeleton)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
virtual void MoveToPosition(const Vector3d & a_Position) override;
virtual void Attack(std::chrono::milliseconds a_Dt) override; virtual void Attack(std::chrono::milliseconds a_Dt) override;
virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override;

View File

@ -37,27 +37,3 @@ void cZombie::GetDrops(cItems & a_Drops, cEntity * a_Killer)
AddRandomArmorDropItem(a_Drops, LootingLevel); AddRandomArmorDropItem(a_Drops, LootingLevel);
AddRandomWeaponDropItem(a_Drops, LootingLevel); AddRandomWeaponDropItem(a_Drops, LootingLevel);
} }
void cZombie::MoveToPosition(const Vector3d & a_Position)
{
// Todo use WouldBurnAt(), not sure how to obtain a chunk though...
super::MoveToPosition(a_Position); // Look at the player and update m_Destination to hit them if they're close
// If the destination is sufficiently skylight challenged AND the skeleton isn't on fire AND we weren't attacked recently then block the movement
if (
!IsOnFire() &&
(m_World->GetBlockSkyLight((int)floor(a_Position.x), (int)floor(a_Position.y), (int)floor(a_Position.z)) - m_World->GetSkyDarkness() > 8) &&
m_TicksSinceLastDamaged == 100
)
{
StopMovingToPosition();
}
}

View File

@ -17,8 +17,6 @@ public:
CLASS_PROTODEF(cZombie) CLASS_PROTODEF(cZombie)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
virtual void MoveToPosition(const Vector3d & a_Position) override;
virtual bool IsUndead(void) override { return true; } virtual bool IsUndead(void) override { return true; }
bool IsVillagerZombie(void) const { return m_IsVillagerZombie; } bool IsVillagerZombie(void) const { return m_IsVillagerZombie; }