diff options
Diffstat (limited to '')
-rw-r--r-- | src/BlockID.cpp | 1 | ||||
-rw-r--r-- | src/Mobs/Villager.cpp | 156 | ||||
-rw-r--r-- | src/Mobs/Villager.h | 26 | ||||
-rw-r--r-- | src/World.cpp | 1 | ||||
-rw-r--r-- | src/World.h | 3 |
5 files changed, 185 insertions, 2 deletions
diff --git a/src/BlockID.cpp b/src/BlockID.cpp index 095865d07..fbb5a0720 100644 --- a/src/BlockID.cpp +++ b/src/BlockID.cpp @@ -767,6 +767,7 @@ public: g_BlockIsSolid[E_BLOCK_MELON_STEM] = false; g_BlockIsSolid[E_BLOCK_NETHER_PORTAL] = false; g_BlockIsSolid[E_BLOCK_PISTON_EXTENSION] = false; + g_BlockIsSolid[E_BLOCK_POTATOES] = false; g_BlockIsSolid[E_BLOCK_POWERED_RAIL] = false; g_BlockIsSolid[E_BLOCK_RAIL] = false; g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_OFF] = false; diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index c8ff4f101..44ec14295 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -3,6 +3,8 @@ #include "Villager.h" #include "../World.h" +#include "../BlockArea.h" +#include "../Blocks/BlockHandler.h" @@ -10,7 +12,9 @@ cVillager::cVillager(eVillagerType VillagerType) : super("Villager", mtVillager, "", "", 0.6, 1.8), - m_Type(VillagerType) + m_Type(VillagerType), + m_VillagerAction(false), + m_ActionCountDown(-1) { } @@ -33,3 +37,153 @@ void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) + +void cVillager::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if (m_ActionCountDown > -1) + { + m_ActionCountDown--; + if (m_ActionCountDown == 0) + { + switch (m_Type) + { + case vtFarmer: + { + HandleFarmerPlaceCrops(); + } + } + } + return; + } + + if (m_VillagerAction) + { + switch (m_Type) + { + case vtFarmer: + { + HandleFarmerTryHarvestCrops(); + } + } + m_VillagerAction = false; + return; + } + + // Don't always try to do a special action. Each tick has 1% to do a special action. + if (m_World->GetTickRandomNumber(99) != 0) + { + return; + } + + switch (m_Type) + { + case vtFarmer: + { + HandleFarmerPrepareFarmCrops(); + } + } +} + + + + +//////////////////////////////////////////////////////////////////////////////// +// Farmer functions. +void cVillager::HandleFarmerPrepareFarmCrops() +{ + if (!m_World->VillagersShouldHarvestCrops()) + { + return; + } + + cBlockArea Surrounding; + /// Read a 11x7x11 area. + Surrounding.Read( + m_World, + (int) GetPosX() - 5, + (int) GetPosX() + 5, + (int) GetPosY() - 3, + (int) GetPosY() + 3, + (int) GetPosZ() - 5, + (int) GetPosZ() + 5 + ); + + for (int I = 0; I < 5; I++) + { + for (int Y = 0; Y < 6; Y++) + { + // Pick random coordinates and check for crops. + int X = m_World->GetTickRandomNumber(11); + int Z = m_World->GetTickRandomNumber(11); + + // A villager can't farm this. + if (!IsBlockFarmable(Surrounding.GetRelBlockType(X, Y, Z))) + { + continue; + } + if (Surrounding.GetRelBlockMeta(X, Y, Z) != 0x7) + { + continue; + } + + m_VillagerAction = true; + m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); + MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5))); + return; + } // for Y loop. + } // Repeat the procces 5 times. +} + + + + + +void cVillager::HandleFarmerTryHarvestCrops() +{ + // Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks. + if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2) + { + // Check if the blocks didn't change while the villager was walking to the coordinates. + BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7) + { + cBlockHandler * Handler = cBlockHandler::GetBlockHandler(CropBlock); + Handler->DropBlock(m_World, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0); + m_ActionCountDown = 20; + } + } +} + + + + +void cVillager::HandleFarmerPlaceCrops() +{ + // Check if there is still farmland at the spot where the crops were. + if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) + { + m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0); + } +} + + + + + +bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType) +{ + switch (a_BlockType) + { + case E_BLOCK_CROPS: + case E_BLOCK_POTATOES: + case E_BLOCK_CARROTS: + { + return true; + } + } + return false; +} + diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index 4cd9aaa8e..b99ae876f 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -29,12 +29,36 @@ public: CLASS_PROTODEF(cVillager); + // Override functions virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override; - int GetVilType(void) const { return m_Type; } + virtual void Tick (float a_Dt, cChunk & a_Chunk) override; + + // cVillager functions + /** return true if the given blocktype are: crops, potatoes or carrots.*/ + bool IsBlockFarmable(BLOCKTYPE a_BlockType); + + ////////////////////////////////////////////////////////////////// + // Farmer functions + /** It searches in a 11x7x11 area for crops. If it found some it will navigate to them.*/ + void HandleFarmerPrepareFarmCrops(); + + /** Looks if the farmer has reached it's destination, and if it's still crops and the destination is closer then 2 blocks it will harvest them.*/ + void HandleFarmerTryHarvestCrops(); + + /** Replaces the crops he harvested.*/ + void HandleFarmerPlaceCrops(); + + // Get and set functions. + int GetVilType(void) const { return m_Type; } + Vector3i GetCropsPos(void) const { return m_CropsPos; } + bool DoesHaveActionActivated(void) const { return m_VillagerAction; } private: + int m_ActionCountDown; int m_Type; + bool m_VillagerAction; + Vector3i m_CropsPos; } ; diff --git a/src/World.cpp b/src/World.cpp index 5205c2616..88bbf5f8a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -547,6 +547,7 @@ void cWorld::Start(void) m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", false); m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true); m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false); + m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true); m_GameMode = (eGameMode)IniFile.GetValueSetI("GameMode", "GameMode", m_GameMode); diff --git a/src/World.h b/src/World.h index d7a7241d1..4d5659ee6 100644 --- a/src/World.h +++ b/src/World.h @@ -138,6 +138,8 @@ public: bool ShouldLavaSpawnFire(void) const { return m_ShouldLavaSpawnFire; } + bool VillagersShouldHarvestCrops(void) const { return m_VillagersShouldHarvestCrops; } + eDimension GetDimension(void) const { return m_Dimension; } /** Returns the world height at the specified coords; waits for the chunk to get loaded / generated */ @@ -743,6 +745,7 @@ private: bool m_bEnabledPVP; bool m_IsDeepSnowEnabled; bool m_ShouldLavaSpawnFire; + bool m_VillagersShouldHarvestCrops; std::vector<BlockTickQueueItem *> m_BlockTickQueue; std::vector<BlockTickQueueItem *> m_BlockTickQueueCopy; // Second is for safely removing the objects from the queue |