diff options
-rw-r--r-- | src/Blocks/BlockIce.h | 14 | ||||
-rw-r--r-- | src/Items/ItemHandler.cpp | 1 | ||||
-rw-r--r-- | src/Mobs/Enderman.cpp | 119 | ||||
-rw-r--r-- | src/Mobs/Enderman.h | 2 |
4 files changed, 134 insertions, 2 deletions
diff --git a/src/Blocks/BlockIce.h b/src/Blocks/BlockIce.h index c50623594..c38630fe3 100644 --- a/src/Blocks/BlockIce.h +++ b/src/Blocks/BlockIce.h @@ -24,9 +24,19 @@ public: } - virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override + virtual void OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override { - // TODO: Ice destroyed with air below it should turn into air instead of water + if (a_Player->IsGameModeCreative() || (a_BlockY <= 0)) + { + return; + } + + BLOCKTYPE BlockBelow = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ); + if (!cBlockInfo::FullyOccupiesVoxel(BlockBelow) && !IsBlockLiquid(BlockBelow)) + { + return; + } + a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WATER, 0); // This is called later than the real destroying of this ice block } diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index d36b5d663..acfd1e648 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -578,6 +578,7 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType) case E_BLOCK_LAPIS_BLOCK: case E_BLOCK_SNOW: case E_BLOCK_VINES: + case E_BLOCK_PACKED_ICE: { return false; } diff --git a/src/Mobs/Enderman.cpp b/src/Mobs/Enderman.cpp index becc99a86..a32e4e175 100644 --- a/src/Mobs/Enderman.cpp +++ b/src/Mobs/Enderman.cpp @@ -2,6 +2,74 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Enderman.h" +#include "../Entities/Player.h" +#include "../Tracer.h" + + + + +/////////////////////////////////////////////////////////////////////////// +// cPlayerLookCheck +class cPlayerLookCheck : + public cPlayerListCallback +{ +public: + cPlayerLookCheck(Vector3d a_EndermanPos) : + m_Player(NULL), + m_EndermanPos(a_EndermanPos) + { + } + + virtual bool Item(cPlayer * a_Player) override + { + // Don't check players who are in creative gamemode + if (a_Player->IsGameModeCreative()) + { + return false; + } + + Vector3d Direction = m_EndermanPos - a_Player->GetPosition(); + + // Don't check players who are more then 64 blocks away + if (Direction.SqrLength() > 64) + { + return false; + } + + // Don't check if the player has a pumpkin on his head + if (a_Player->GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN) + { + return false; + } + + + Vector3d LookVector = a_Player->GetLookVector(); + double dot = Direction.Dot(LookVector); + + // 0.09 rad ~ 5 degrees + // If the player's crosshair is within 5 degrees of the enderman, it counts as looking + if (dot > cos(0.09)) + { + return false; + } + + cTracer LineOfSight(a_Player->GetWorld()); + if (LineOfSight.Trace(m_EndermanPos, Direction, (int)Direction.Length())) + { + // No direct line of sight + return false; + } + + m_Player = a_Player; + return true; + } + + cPlayer * GetPlayer(void) const { return m_Player; } + +protected: + cPlayer * m_Player; + Vector3d m_EndermanPos; +} ; @@ -32,3 +100,54 @@ void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer) +void cEnderman::CheckEventSeePlayer() +{ + if (m_Target != NULL) + { + return; + } + + cPlayerLookCheck Callback(GetPosition()); + if (m_World->ForEachPlayer(Callback)) + { + return; + } + + ASSERT(Callback.GetPlayer() != NULL); + + int ChunkX, ChunkZ; + cChunkDef::BlockToChunk(POSX_TOINT, POSZ_TOINT, ChunkX, ChunkZ); + + // Check if the chunk the enderman is in is lit + if (!m_World->IsChunkLighted(ChunkX, ChunkZ)) + { + m_World->QueueLightChunk(ChunkX, ChunkZ); + return; + } + + // Enderman only attack if the skylight is higher than 7 + if (m_World->GetBlockSkyLight(POSX_TOINT, POSY_TOINT, POSZ_TOINT) <= 7) + { + // TODO: Teleport the enderman to a random spot + return; + } + + if (!Callback.GetPlayer()->IsGameModeCreative()) + { + super::EventSeePlayer(Callback.GetPlayer()); + m_EMState = CHASING; + m_bIsScreaming = true; + GetWorld()->BroadcastEntityMetadata(*this); + } +} + + + + + +void cEnderman::EventLosePlayer() +{ + super::EventLosePlayer(); + m_bIsScreaming = false; + GetWorld()->BroadcastEntityMetadata(*this); +} diff --git a/src/Mobs/Enderman.h b/src/Mobs/Enderman.h index aa2eff682..da857ee09 100644 --- a/src/Mobs/Enderman.h +++ b/src/Mobs/Enderman.h @@ -18,6 +18,8 @@ public: CLASS_PROTODEF(cEnderman) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void CheckEventSeePlayer(void) override; + virtual void EventLosePlayer(void) override; bool IsScreaming(void) const {return m_bIsScreaming; } BLOCKTYPE GetCarriedBlock(void) const {return CarriedBlock; } |