Cuberite
A lightweight, fast and extensible game server for Minecraft
Enderman.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
3 
4 #include "Chunk.h"
5 #include "Enderman.h"
6 #include "../Entities/Player.h"
7 #include "../LineBlockTracer.h"
8 
9 
10 
11 
13 // cPlayerLookCheck
15 {
16 public:
17 
18  cPlayerLookCheck(Vector3d a_EndermanHeadPosition, int a_SightDistance) :
19  m_Player(nullptr),
20  m_EndermanHeadPosition(a_EndermanHeadPosition),
21  m_SightDistance(a_SightDistance)
22  {
23  }
24 
25  bool operator () (cPlayer & a_Player)
26  {
27  // Don't check players who cannot be targeted
28  if (!a_Player.CanMobsTarget())
29  {
30  return false;
31  }
32 
33  const auto PlayerHeadPosition = a_Player.GetPosition().addedY(a_Player.GetHeight());
34  const auto Direction = m_EndermanHeadPosition - PlayerHeadPosition;
35 
36  // Don't check players who are more than SightDistance (64) blocks away:
37  if (Direction.Length() > m_SightDistance)
38  {
39  return false;
40  }
41 
42  // Don't check if the player has a pumpkin on his head:
44  {
45  return false;
46  }
47 
48  const auto LookVector = a_Player.GetLookVector(); // Note: ||LookVector|| is always 1.
49  const auto Cosine = Direction.Dot(LookVector) / Direction.Length(); // a.b / (||a|| * ||b||)
50 
51  // If the player's crosshair is within 5 degrees of the enderman, it counts as looking:
52  if ((Cosine < std::cos(0.09)) || (Cosine > std::cos(0))) // 0.09 rad ~ 5 degrees
53  {
54  return false;
55  }
56 
57  // TODO: Check if endermen are angered through water in Vanilla
59  {
60  // No direct line of sight
61  return false;
62  }
63 
64  m_Player = &a_Player;
65  return true;
66  }
67 
68  cPlayer * GetPlayer(void) const { return m_Player; }
69 
70 protected:
71 
75 } ;
76 
77 
78 
79 
80 
82  Super("Enderman", mtEnderman, "entity.endermen.hurt", "entity.endermen.death", "entity.endermen.ambient", 0.6f, 2.9f),
83  m_bIsScreaming(false),
84  m_CarriedBlock(E_BLOCK_AIR),
85  m_CarriedMeta(0)
86 {
87 }
88 
89 
90 
91 
92 
93 void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer)
94 {
95  unsigned int LootingLevel = 0;
96  if (a_Killer != nullptr)
97  {
99  }
100  AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_ENDER_PEARL);
101 }
102 
103 
104 
105 
106 
108 {
109  if (GetTarget() != nullptr)
110  {
111  return;
112  }
113 
114  cPlayerLookCheck Callback(GetPosition().addedY(GetHeight()), m_SightDistance);
115  if (m_World->ForEachPlayer(Callback))
116  {
117  return;
118  }
119 
120  ASSERT(Callback.GetPlayer() != nullptr);
121 
122  // Target the player:
123  cAggressiveMonster::EventSeePlayer(Callback.GetPlayer(), a_Chunk);
124  m_bIsScreaming = true;
126 }
127 
128 
129 
130 
131 
133 {
135  m_bIsScreaming = false;
137 }
138 
139 
140 
141 
142 
143 void cEnderman::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
144 {
145  Super::Tick(a_Dt, a_Chunk);
146  if (!IsTicking())
147  {
148  // The base class tick destroyed us
149  return;
150  }
151 
152  if (m_EMState != CHASING)
153  {
154  cMonster * EndermiteFound = GetMonsterOfTypeInSight(mtEndermite, 64);
155  if (EndermiteFound != nullptr)
156  {
157  SetTarget(EndermiteFound);
158  m_EMState = CHASING;
159  m_bIsScreaming = true;
160  }
161  }
162  else
163  {
164  const auto Target = GetTarget();
165  if (Target != nullptr)
166  {
167  if (!Target->IsTicking())
168  {
169  m_EMState = IDLE;
170  m_bIsScreaming = false;
171  }
172  }
173  }
174 
175  PREPARE_REL_AND_CHUNK(GetPosition().Floor(), a_Chunk);
176  if (!RelSuccess)
177  {
178  return;
179  }
180 
181  // Take damage when wet:
182  if (IsInWater() || Chunk->IsWeatherWetAt(Rel))
183  {
184  EventLosePlayer();
185  TakeDamage(dtEnvironment, nullptr, 1, 0);
186  // TODO teleport to a safe location
187  }
188 }
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_PUMPKIN
Definition: BlockType.h:101
@ E_ITEM_ENDER_PEARL
Definition: BlockType.h:413
#define PREPARE_REL_AND_CHUNK(Position, OriginalChunk)
Definition: Chunk.h:32
@ dtEnvironment
Definition: Defines.h:265
#define ASSERT(x)
Definition: Globals.h:276
@ mtEndermite
Definition: MonsterTypes.h:28
@ mtEnderman
Definition: MonsterTypes.h:27
Direction
Definition: Chunk.h:36
unsigned int GetLevel(int a_EnchantmentID) const
Returns the level for the specified enchantment; 0 if not stored.
Definition: Entity.h:76
virtual bool IsInWater(void) const
Returns true if any part of the entity is in a water block.
Definition: Entity.h:501
bool IsTicking(void) const
Returns true if the entity is valid and ticking.
Definition: Entity.cpp:2259
cWorld * m_World
Definition: Entity.h:624
void TakeDamage(cEntity &a_Attacker)
Makes this pawn take damage from an attack by a_Attacker.
Definition: Entity.cpp:272
float GetHeight(void) const
Definition: Entity.h:193
virtual cItem GetEquippedWeapon(void) const
Returns the curently equipped weapon; empty item if none.
Definition: Entity.h:333
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:297
Vector3d GetLookVector(void) const
Definition: Entity.cpp:2267
cWorld * GetWorld(void) const
Definition: Entity.h:190
Definition: Player.h:29
virtual cItem GetEquippedHelmet(void) const override
Returns the currently equipped helmet; empty item if none.
Definition: Player.h:598
bool CanMobsTarget(void) const
Returns true if the player can be targeted by Mobs.
Definition: Player.cpp:1061
cEnchantments m_Enchantments
Definition: Item.h:166
short m_ItemType
Definition: Item.h:163
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:215
static bool LineOfSightTrace(cWorld &a_World, const Vector3d &a_Start, const Vector3d &a_End, int a_Sight)
Returns true if the two positions are within line of sight (not obscured by blocks).
virtual void EventSeePlayer(cPlayer *a_Player, cChunk &a_Chunk) override
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
cMonster * GetMonsterOfTypeInSight(eMonsterType a_mobtype, unsigned int SightDistance=16)
Check if a monster of certain type is in sight.
Vector3d m_EndermanHeadPosition
Definition: Enderman.cpp:73
cPlayer * GetPlayer(void) const
Definition: Enderman.cpp:68
bool operator()(cPlayer &a_Player)
Definition: Enderman.cpp:25
cPlayer * m_Player
Definition: Enderman.cpp:72
cPlayerLookCheck(Vector3d a_EndermanHeadPosition, int a_SightDistance)
Definition: Enderman.cpp:18
virtual void EventLosePlayer(void) override
Definition: Enderman.cpp:132
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Enderman.cpp:143
virtual void GetDrops(cItems &a_Drops, cEntity *a_Killer=nullptr) override
Returns the list of drops for this pawn when it is killed.
Definition: Enderman.cpp:93
virtual void CheckEventSeePlayer(cChunk &a_Chunk) override
Definition: Enderman.cpp:107
bool m_bIsScreaming
Definition: Enderman.h:32
int m_SightDistance
Definition: Monster.h:314
void SetTarget(cPawn *a_NewTarget)
Sets the target that this mob will chase.
Definition: Monster.cpp:1204
void AddRandomDropItem(cItems &a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth=0)
Adds a random number of a_Item between a_Min and a_Max to itemdrops a_Drops.
Definition: Monster.cpp:1518
cPawn * GetTarget()
Returns the current target.
Definition: Monster.cpp:1243
@ IDLE
Definition: Monster.h:40
@ CHASING
Definition: Monster.h:40
enum cMonster::MState m_EMState
virtual void EventLosePlayer(void)
Definition: Monster.cpp:839
Vector3< T > addedY(T a_AddY) const
Returns a copy of this vector moved by the specified amount on the y axis.
Definition: Vector3.h:314
T Dot(const Vector3< T > &a_Rhs) const
Definition: Vector3.h:110
virtual void BroadcastEntityMetadata(const cEntity &a_Entity, const cClientHandle *a_Exclude=nullptr) override
virtual bool ForEachPlayer(cPlayerListCallback a_Callback) override
Calls the callback for each player in the list; returns true if all players processed,...
Definition: World.cpp:2266