Cuberite
A lightweight, fast and extensible game server for Minecraft
PassiveMonster.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 "PassiveMonster.h"
5 #include "../World.h"
6 #include "../Entities/Player.h"
7 #include "../BoundingBox.h"
8 #include "../Items/ItemSpawnEgg.h"
9 
10 
11 
12 
13 cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) :
14  super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height),
15  m_LovePartner(nullptr),
16  m_LoveTimer(0),
17  m_LoveCooldown(0),
18  m_MatingTimer(0)
19 {
21 }
22 
23 
24 
25 
26 
28 {
29  if (!super::DoTakeDamage(a_TDI))
30  {
31  return false;
32  }
33  if ((a_TDI.Attacker != this) && (a_TDI.Attacker != nullptr))
34  {
36  }
37  return true;
38 }
39 
40 
41 
42 
43 
45 {
46  m_LovePartner = a_Partner;
47  m_MatingTimer = 50; // about 3 seconds of mating
48 }
49 
50 
51 
52 
53 
55 {
56  m_LovePartner = nullptr;
57  m_LoveTimer = 0;
58  m_MatingTimer = 0;
59  m_LoveCooldown = 20 * 60 * 5; // 5 minutes
60 
61  // when an animal is in love mode, the client only stops sending the hearts if we let them know it's in cooldown, which is done with the "age" metadata
63 }
64 
65 
66 
67 
68 
70 {
71  if (m_LovePartner != nullptr)
72  {
74  }
76 }
77 
78 
79 
80 
81 
82 void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
83 {
84  super::Tick(a_Dt, a_Chunk);
85  if (!IsTicking())
86  {
87  // The base class tick destroyed us
88  return;
89  }
90 
91  if (m_EMState == ESCAPING)
92  {
94  }
95 
96  // if we have a partner, mate
97  if (m_LovePartner != nullptr)
98  {
99 
100  if (m_MatingTimer > 0)
101  {
102  // If we should still mate, keep bumping into them until baby is made
104  MoveToPosition(Pos);
105  }
106  else
107  {
108  // Mating finished. Spawn baby
109  Vector3f Pos = (GetPosition() + m_LovePartner->GetPosition()) * 0.5;
110  UInt32 BabyID = m_World->SpawnMob(Pos.x, Pos.y, Pos.z, GetMobType(), true);
111 
112  cPassiveMonster * Baby = nullptr;
113 
114  m_World->DoWithEntityByID(BabyID, [&](cEntity & a_Entity)
115  {
116  Baby = static_cast<cPassiveMonster *>(&a_Entity);
117  return true;
118  }
119  );
120 
121  if (Baby != nullptr)
122  {
123  Baby->InheritFromParents(this, m_LovePartner);
124  }
125 
126  m_World->SpawnExperienceOrb(Pos.x, Pos.y, Pos.z, GetRandomProvider().RandInt(1, 6));
127 
129  ResetLoveMode();
130  }
131  }
132  else
133  {
134  // We have no partner, so we just chase the player if they have our breeding item
135  cItems FollowedItems;
136  GetFollowedItems(FollowedItems);
137  if (FollowedItems.Size() > 0)
138  {
139  m_World->DoWithNearestPlayer(GetPosition(), static_cast<float>(m_SightDistance), [&](cPlayer & a_Player) -> bool
140  {
141  cItem EquippedItem = a_Player.GetEquippedItem();
142  if (FollowedItems.ContainsType(EquippedItem))
143  {
144  Vector3d PlayerPos = a_Player.GetPosition();
145  MoveToPosition(PlayerPos);
146  }
147 
148  return true;
149  });
150  }
151  }
152 
153  // If we are in love mode but we have no partner, search for a partner neabry
154  if (m_LoveTimer > 0)
155  {
156  if (m_LovePartner == nullptr)
157  {
158  m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8), [=](cEntity & a_Entity)
159  {
160  // If the entity is not a monster, don't breed with it
161  // Also, do not self-breed
162  if ((a_Entity.GetEntityType() != etMonster) || (&a_Entity == this))
163  {
164  return false;
165  }
166 
167  auto & Me = static_cast<cPassiveMonster&>(*this);
168  auto & PotentialPartner = static_cast<cPassiveMonster&>(a_Entity);
169 
170  // If the potential partner is not of the same species, don't breed with it
171  if (PotentialPartner.GetMobType() != Me.GetMobType())
172  {
173  return false;
174  }
175 
176  // If the potential partner is not in love
177  // Or they already have a mate, do not breed with them
178  if ((!PotentialPartner.IsInLove()) || (PotentialPartner.GetPartner() != nullptr))
179  {
180  return false;
181  }
182 
183  // All conditions met, let's breed!
184  PotentialPartner.EngageLoveMode(&Me);
185  Me.EngageLoveMode(&PotentialPartner);
186  return true;
187  }
188  );
189  }
190 
191  m_LoveTimer--;
192  }
193  if (m_MatingTimer > 0)
194  {
195  m_MatingTimer--;
196  }
197  if (m_LoveCooldown > 0)
198  {
199  m_LoveCooldown--;
200  }
201 }
202 
203 
204 
205 
206 
208 {
209  super::OnRightClicked(a_Player);
210 
211  const cItem & EquippedItem = a_Player.GetEquippedItem();
212 
213  // If a player holding breeding items right-clicked me, go into love mode
214  if ((m_LoveCooldown == 0) && !IsInLove() && !IsBaby())
215  {
216  cItems Items;
217  GetBreedingItems(Items);
218  if (Items.ContainsType(EquippedItem.m_ItemType))
219  {
220  if (!a_Player.IsGameModeCreative())
221  {
222  a_Player.GetInventory().RemoveOneEquippedItem();
223  }
224  m_LoveTimer = 20 * 30; // half a minute
226  }
227  }
228  // If a player holding my spawn egg right-clicked me, spawn a new baby
229  if (EquippedItem.m_ItemType == E_ITEM_SPAWN_EGG)
230  {
232  if (
233  (MonsterType == m_MobType) &&
234  (m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), m_MobType, true) != cEntity::INVALID_ID) // Spawning succeeded
235  )
236  {
237  if (!a_Player.IsGameModeCreative())
238  {
239  // The mob was spawned, "use" the item:
240  a_Player.GetInventory().RemoveOneEquippedItem();
241  }
242  }
243  }
244 }
245 
246 
247 
double GetPosY(void) const
Definition: Entity.h:207
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:2729
virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby=false) override
Spawns a mob of the specified type.
Definition: World.cpp:3190
double GetPosX(void) const
Definition: Entity.h:206
virtual void Destroyed() override
Definition: Monster.cpp:156
T x
Definition: Vector3.h:17
eEntityType GetEntityType(void) const
Definition: Entity.h:168
eMonsterType GetMobType(void) const
Definition: Monster.h:68
short m_ItemDamage
Definition: Item.h:211
size_t Size(void) const
Definition: Item.h:257
bool RemoveOneEquippedItem(void)
Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed.
Definition: Inventory.cpp:207
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Monster.cpp:263
MTRand & GetRandomProvider()
Returns the current thread&#39;s random number source.
Definition: FastRandom.cpp:20
virtual void BroadcastEntityMetadata(const cEntity &a_Entity, const cClientHandle *a_Exclude=nullptr) override
cWorld * m_World
Definition: Entity.h:620
virtual void Destroyed(void) override
virtual bool DoTakeDamage(TakeDamageInfo &a_TDI) override
When hit by someone, run away.
const cItem & GetEquippedItem(void) const
Definition: Player.h:142
Definition: Player.h:27
void EngageLoveMode(cPassiveMonster *a_Partner)
Start the mating process.
bool IsInLove() const
Returns whether the monster has just been fed and is ready to mate.
bool IsBaby(void) const
Definition: Monster.h:150
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:244
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:23
Definition: Chunk.h:49
bool DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback a_Callback)
Calls the callback if the entity with the specified ID is found, with the entity object as the callba...
Definition: World.cpp:2738
T y
Definition: Vector3.h:17
enum cMonster::MState m_EMState
eMonsterType
Identifies individual monster type, as well as their network type-ID.
Definition: MonsterTypes.h:10
static eMonsterType ItemDamageToMonsterType(short a_ItemDamage)
Converts the Spawn egg item damage to the monster type to spawn.
Definition: ItemSpawnEgg.h:59
T z
Definition: Vector3.h:17
int m_SightDistance
Definition: Monster.h:275
UInt32 SpawnExperienceOrb(Vector3d a_Pos, int a_Reward)
Spawns an experience orb at the given location with the given reward.
Definition: World.cpp:2024
cPassiveMonster(const AString &a_ConfigName, eMonsterType a_MobType, const AString &a_SoundHurt, const AString &a_SoundDeath, double a_Width, double a_Height)
virtual void CheckEventLostPlayer(void)
Definition: Monster.cpp:726
int m_LoveTimer
If above 0, the monster is in love mode, and will breed if a nearby monster is also in love mode...
bool IsTicking(void) const
Returns true if the entity is valid and ticking.
Definition: Entity.cpp:2201
virtual bool DoTakeDamage(TakeDamageInfo &a_TDI) override
Makes this entity take damage specified in the a_TDI.
Definition: Monster.cpp:563
eMonsterType m_MobType
Definition: Monster.h:264
bool DoWithNearestPlayer(Vector3d a_Pos, double a_RangeLimit, cPlayerListCallback a_Callback, bool a_CheckLineOfSight=true, bool a_IgnoreSpectator=true)
Calls the callback for nearest player for given position, Returns false if player not found...
Definition: World.cpp:2639
bool ContainsType(const cItem &a_Item)
Definition: Item.cpp:711
void ResetLoveMode()
Finish the mating process.
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
virtual void GetBreedingItems(cItems &a_Items)
Returns the items that make the animal breed - this is usually the same as the ones that make the ani...
virtual void InheritFromParents(cPassiveMonster *a_Parent1, cPassiveMonster *a_Parent2)
Called after the baby is born, allows the baby to inherit the parents&#39; properties (color...
virtual void GetFollowedItems(cItems &a_Items)
Returns the items that the animal of this class follows when a player holds it in hand...
std::string AString
Definition: StringUtils.h:13
cPassiveMonster * m_LovePartner
The monster&#39;s breeding partner.
int m_LoveCooldown
If above 0, the monster is in cooldown mode and will refuse to breed.
int m_MatingTimer
The monster is engaged in mating, once this reaches zero, a baby will be born.
Definition: Entity.h:73
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:307
unsigned int UInt32
Definition: Globals.h:113
virtual void OnRightClicked(cPlayer &a_Player) override
Called when the specified player right-clicks this entity.
Definition: Monster.cpp:672
double GetPosZ(void) const
Definition: Entity.h:208
bool IsGameModeCreative(void) const
Returns true if the player is in Creative mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1260
short m_ItemType
Definition: Item.h:209
virtual void OnRightClicked(cPlayer &a_Player) override
Called when the specified player right-clicks this entity.
cInventory & GetInventory(void)
Definition: Player.h:136
static const UInt32 INVALID_ID
Special ID that is considered an "invalid value", signifying no entity.
Definition: Entity.h:156
Definition: Item.h:36
enum cMonster::MPersonality m_EMPersonality
cEntity * Attacker
Definition: Entity.h:60
virtual void BroadcastEntityStatus(const cEntity &a_Entity, Int8 a_Status, const cClientHandle *a_Exclude=nullptr) override
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:234