summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Mobs/Enderman.cpp119
-rw-r--r--src/Mobs/Enderman.h2
2 files changed, 121 insertions, 0 deletions
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; }