Cuberite
A lightweight, fast and extensible game server for Minecraft
AggressiveMonster.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 "AggressiveMonster.h"
5 
6 #include "LineBlockTracer.h"
7 #include "World.h"
8 #include "Entities/Player.h"
9 
10 
11 
12 
13 
14 cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, float a_Width, float a_Height) :
15  Super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_SoundAmbient, a_Width, a_Height)
16 {
18 }
19 
20 
21 
22 
23 
24 // What to do if in Chasing State
25 void cAggressiveMonster::InStateChasing(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
26 {
27  Super::InStateChasing(a_Dt, a_Chunk);
28 
29  if (GetTarget() != nullptr)
30  {
32  }
33 }
34 
35 
36 
37 
38 
40 {
41  Super::EventSeePlayer(a_Player, a_Chunk);
43 }
44 
45 
46 
47 
48 
49 cMonster * cAggressiveMonster::GetMonsterOfTypeInSight(eMonsterType a_MobType, unsigned int a_SightDistance)
50 {
51 
52  cMonster * FoundTarget = nullptr;
53  auto MinimumDistance = static_cast<double>(a_SightDistance * a_SightDistance);
54 
55  class cCallback : public cBlockTracer::cCallbacks
56  {
57  public:
58  bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
59  {
60  return a_BlockType != E_BLOCK_AIR;
61  }
62  };
63 
64  auto Callbacks = cCallback();
65  auto Tracer = cLineBlockTracer(*GetWorld(), Callbacks);
66 
67  cEntityCallback Callback = [&](cEntity & a_Entity)
68  {
69  if (!a_Entity.IsMob())
70  {
71  return false;
72  }
73 
74  auto & Other = dynamic_cast<cMonster &>(a_Entity);
75  if (Other.GetMobType() != a_MobType)
76  {
77  return false;
78  }
79 
80  Vector3d MyHeadPosition = GetPosition().addedY(GetHeight());
81  Vector3d TargetPosition = Other.GetPosition().addedY(Other.GetHeight());
82  double TargetDistance = (MyHeadPosition - TargetPosition).SqrLength();
83 
84  if (
85  (MinimumDistance > TargetDistance) &&
86  (TargetDistance < (a_SightDistance * a_SightDistance))
87  )
88  {
89  FoundTarget = & Other;
90  return true;
91  }
92  return false;
93  };
94 
95  cBoundingBox CheckZone(GetPosition().addedXZ(-a_SightDistance, -a_SightDistance), GetPosition().addedXZ(a_SightDistance, a_SightDistance));
96  m_World->ForEachEntityInBox(CheckZone, Callback);
97  return FoundTarget;
98 }
99 
100 
101 
102 
103 
104 void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
105 {
106  Super::Tick(a_Dt, a_Chunk);
107  if (!IsTicking())
108  {
109  // The base class tick destroyed us
110  return;
111  }
112 
113  // Set or clear m_Target depending on rules for this Monster:
114  if (m_EMState == CHASING)
115  {
116  CheckEventLostPlayer(a_Dt);
117  }
118  else
119  {
120  CheckEventSeePlayer(a_Chunk);
121  }
122 
123  if (
124  (GetTarget() != nullptr) &&
125  TargetIsInRange() &&
127  *GetWorld(),
128  GetPosition().addedY(GetHeight()),
129  GetTarget()->GetPosition().addedY(GetTarget()->GetHeight()),
131  ) &&
132  (GetHealth() > 0.0)
133  )
134  {
135  // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls)
136  Attack(a_Dt);
137  }
138 }
139 
140 
141 
142 
143 
144 bool cAggressiveMonster::Attack(std::chrono::milliseconds a_Dt)
145 {
146  if ((GetTarget() == nullptr) || (m_AttackCoolDownTicksLeft != 0))
147  {
148  return false;
149  }
150 
151  // Setting this higher gives us more wiggle room for attackrate
153 
154  double KnockbackAmount = 9;
155  GetTarget()->TakeDamage(dtMobAttack, this, m_AttackDamage, KnockbackAmount);
156 
157  return true;
158 }
@ E_BLOCK_AIR
Definition: BlockType.h:10
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:44
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:41
@ dtMobAttack
Definition: Defines.h:271
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
Definition: Defines.h:38
eMonsterType
Identifies individual monster type.
Definition: MonsterTypes.h:11
std::string AString
Definition: StringUtils.h:11
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:24
Definition: Chunk.h:36
Definition: Entity.h:76
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
float GetHealth(void) const
Returns the health of this entity.
Definition: Entity.h:367
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:297
cWorld * GetWorld(void) const
Definition: Entity.h:190
Definition: Player.h:29
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 bool Attack(std::chrono::milliseconds a_Dt)
Try to perform attack returns true if attack was deemed successful (hit player, fired projectile,...
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
virtual void InStateChasing(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.
cAggressiveMonster(const AString &a_ConfigName, eMonsterType a_MobType, const AString &a_SoundHurt, const AString &a_SoundDeath, const AString &a_SoundAmbient, float a_Width, float a_Height)
virtual bool IsNetherNative(void)
Returns whether this mob spawns in the Nether in Vanilla.
Definition: Monster.cpp:988
void ResetAttackCooldown()
Definition: Monster.cpp:937
virtual void InStateChasing(std::chrono::milliseconds a_Dt, cChunk &a_Chunk)
Definition: Monster.cpp:906
virtual void CheckEventLostPlayer(std::chrono::milliseconds a_Dt)
Definition: Monster.cpp:784
virtual void MoveToPosition(const Vector3d &a_Position)
Engage pathfinder and tell it to calculate a path to a given position, and move the mob accordingly.
Definition: Monster.cpp:245
cPawn * GetTarget()
Returns the current target.
Definition: Monster.cpp:1243
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Monster.cpp:264
@ CHASING
Definition: Monster.h:40
bool TargetIsInRange(void)
Returns whether or not the target is close enough for attack.
Definition: Monster.h:276
enum cMonster::MState m_EMState
virtual void EventSeePlayer(cPlayer *a_Player, cChunk &a_Chunk)
Definition: Monster.cpp:829
int m_AttackCoolDownTicksLeft
Definition: Monster.h:313
@ AGGRESSIVE
Definition: Monster.h:41
enum cMonster::MPersonality m_EMPersonality
virtual void CheckEventSeePlayer(cChunk &a_Chunk)
Definition: Monster.cpp:738
int m_AttackDamage
Definition: Monster.h:311
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
virtual bool ForEachEntityInBox(const cBoundingBox &a_Box, cEntityCallback a_Callback) override
Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
Definition: World.cpp:2445