Cuberite
A lightweight, fast and extensible game server for Minecraft
Horse.cpp
Go to the documentation of this file.
1 #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
2 
3 #include "Horse.h"
4 #include "../World.h"
5 #include "../EffectID.h"
6 #include "../Entities/Player.h"
7 #include "../UI/HorseWindow.h"
8 
9 
10 
11 
12 
13 cHorse::cHorse(int Type, int Color, int Style, int TameTimes) :
14  Super("Horse", mtHorse, "entity.horse.hurt", "entity.horse.death", "entity.horse.ambient", 1.4f, 1.6f),
15  cEntityWindowOwner(this),
16  m_bHasChest(false),
17  m_bIsEating(false),
18  m_bIsRearing(false),
19  m_bIsMouthOpen(false),
20  m_bIsTame(false),
21  m_Type(Type),
22  m_Color(Color),
23  m_Style(Style),
24  m_TimesToTame(TameTimes),
25  m_TameAttemptTimes(0),
26  m_RearTickCount(0),
27  m_MaxSpeed(14.0)
28 {
29 }
30 
31 
32 
33 
34 
35 void cHorse::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
36 {
37  Super::Tick(a_Dt, a_Chunk);
38  if (!IsTicking())
39  {
40  // The base class tick destroyed us
41  return;
42  }
43 
44  bool MetadataDirty = false;
45  auto & Random = GetRandomProvider();
46 
47  if (!m_bIsMouthOpen)
48  {
49  if (Random.RandBool(0.02))
50  {
51  MetadataDirty = true;
52  m_bIsMouthOpen = true;
53  }
54  }
55  else
56  {
57  if (Random.RandBool(0.10))
58  {
59  MetadataDirty = true;
60  m_bIsMouthOpen = false;
61  }
62  }
63 
64  if ((m_Attachee != nullptr) && (!m_bIsTame))
65  {
67  {
68  if (Random.RandBool(0.02))
69  {
74 
75  m_World->BroadcastSoundEffect("entity.horse.angry", GetPosition(), 1.0f, 1.0f);
76  m_Attachee->Detach();
77  MetadataDirty = true;
78  m_bIsRearing = true;
79  }
80  }
81  else
82  {
83  m_World->BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
84  MetadataDirty = true;
85  m_bIsTame = true;
86  }
87  }
88 
89  if (m_bIsRearing)
90  {
91  if (m_RearTickCount == 20)
92  {
93  MetadataDirty = true;
94  m_bIsRearing = false;
95  m_RearTickCount = 0;
96  }
97  else
98  {
100  }
101  }
102 
103  if (MetadataDirty)
104  {
106  }
107 }
108 
109 
110 
111 
112 
114 {
115  const auto Window = GetWindow();
116  if (Window != nullptr)
117  {
118  Window->OwnerDestroyed();
119  }
120 
121  Super::OnRemoveFromWorld(a_World);
122 }
123 
124 
125 
126 
127 
129 {
130  Super::OnRightClicked(a_Player);
131 
132  if (m_bIsTame)
133  {
134  if (a_Player.IsCrouched())
135  {
136  PlayerOpenWindow(a_Player);
137  return;
138  }
139 
140  auto EquipedItemType = a_Player.GetEquippedItem().m_ItemType;
141 
142  if (
143  !IsSaddled() &&
144  (
145  (EquipedItemType == E_ITEM_SADDLE) ||
146  ItemCategory::IsHorseArmor(EquipedItemType)
147  )
148  )
149  {
150  // Player is holding a horse inventory item, open the window:
151  PlayerOpenWindow(a_Player);
152  }
153  else
154  {
155  a_Player.AttachTo(*this);
156  }
157  }
158  else if (a_Player.GetEquippedItem().IsEmpty())
159  {
160  // Check if leashed / unleashed to player before try to ride
162  {
163  if (m_Attachee != nullptr)
164  {
165  if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
166  {
167  a_Player.Detach();
168  return;
169  }
170 
171  if (m_Attachee->IsPlayer())
172  {
173  return;
174  }
175 
176  m_Attachee->Detach();
177  }
178 
180  a_Player.AttachTo(*this);
181  }
182  }
183  else
184  {
185  m_bIsRearing = true;
186  m_RearTickCount = 0;
187  m_World->BroadcastSoundEffect("entity.horse.angry", GetPosition(), 1.0f, 0.8f);
188  }
189 }
190 
191 
192 
193 
194 
196 {
197  if (a_Saddle.m_ItemType == E_ITEM_SADDLE)
198  {
199  m_World->BroadcastSoundEffect("entity.horse.saddle", GetPosition(), 1.0f, 0.8f);
200  }
201  else if (!a_Saddle.IsEmpty())
202  {
203  return; // Invalid item
204  }
205 
206  m_Saddle = std::move(a_Saddle);
208 }
209 
210 
211 
212 
213 
215 {
217  {
218  m_World->BroadcastSoundEffect("entity.horse.armor", GetPosition(), 1.0f, 0.8f);
219  }
220  else if (!a_Armor.IsEmpty())
221  {
222  return; // Invalid item
223  }
224 
225  m_Armor = std::move(a_Armor);
227 }
228 
229 
230 
231 
232 
233 int cHorse::GetHorseArmour(void) const
234 {
235  switch (m_Armor.m_ItemType)
236  {
237  case E_ITEM_EMPTY: return 0;
238  case E_ITEM_IRON_HORSE_ARMOR: return 1;
239  case E_ITEM_GOLD_HORSE_ARMOR: return 2;
240  case E_ITEM_DIAMOND_HORSE_ARMOR: return 3;
241 
242  default:
243  {
244  LOGWARN("cHorse::GetHorseArmour: Invalid armour item (%d)", m_Armor.m_ItemType);
245  return 0;
246  }
247  }
248 }
249 
250 
251 
252 
253 
254 void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer)
255 {
256  if (IsBaby())
257  {
258  return; // Babies don't drop items
259  }
260 
261  unsigned int LootingLevel = 0;
262  if (a_Killer != nullptr)
263  {
265  }
266  AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER);
267  if (IsSaddled())
268  {
269  a_Drops.push_back(m_Saddle);
270  }
271  if (!m_Armor.IsEmpty())
272  {
273  a_Drops.push_back(m_Armor);
274  }
275 }
276 
277 
278 
279 
280 
281 void cHorse::InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
282 {
283  // If horse is tame and someone is sitting on it, don't walk around
284  if ((!m_bIsTame) || (m_Attachee == nullptr))
285  {
286  Super::InStateIdle(a_Dt, a_Chunk);
287  }
288 }
289 
290 
291 
292 
293 
294 void cHorse::HandleSpeedFromAttachee(float a_Forward, float a_Sideways)
295 {
296  if ((m_bIsTame) && IsSaddled())
297  {
298  Super::HandleSpeedFromAttachee(a_Forward * m_MaxSpeed, a_Sideways * m_MaxSpeed);
299  }
300 }
301 
302 
303 
304 
305 
307 {
308  auto Window = GetWindow();
309  if (Window == nullptr)
310  {
311  Window = new cHorseWindow(*this);
312  OpenWindow(Window);
313  }
314 
315  a_Player.OpenWindow(*Window);
316 }
@ E_ITEM_EMPTY
Definition: BlockType.h:296
@ E_ITEM_IRON_HORSE_ARMOR
Definition: BlockType.h:463
@ E_ITEM_GOLD_HORSE_ARMOR
Definition: BlockType.h:464
@ E_ITEM_DIAMOND_HORSE_ARMOR
Definition: BlockType.h:465
@ E_ITEM_LEATHER
Definition: BlockType.h:378
@ E_ITEM_SADDLE
Definition: BlockType.h:373
@ PARTICLE_SMOKE
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
#define LOGWARN
Definition: LoggerSimple.h:88
eMonsterType m_Type
Definition: Monster.cpp:35
@ mtHorse
Definition: MonsterTypes.h:34
bool IsHorseArmor(short a_ItemType)
Definition: Defines.cpp:602
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
bool IsPlayer(void) const
Definition: Entity.h:160
cEntity * m_Attachee
The entity which is attached to this entity (rider), nullptr if none.
Definition: Entity.h:591
void Detach(void)
Detaches from the currently attached entity, if any.
Definition: Entity.cpp:2052
bool IsTicking(void) const
Returns true if the entity is valid and ticking.
Definition: Entity.cpp:2259
cWorld * m_World
Definition: Entity.h:624
virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways)
Definition: Entity.cpp:2230
UInt32 GetUniqueID(void) const
Definition: Entity.h:253
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
void AttachTo(cEntity &a_AttachTo)
Attaches to the specified entity; detaches from any previous one first.
Definition: Entity.cpp:2027
Definition: Player.h:29
const cItem & GetEquippedItem(void) const
Definition: Player.h:162
void OpenWindow(cWindow &a_Window)
Opens the specified window; closes the current one first using CloseWindow()
Definition: Player.cpp:1123
virtual bool IsCrouched(void) const override
Definition: Player.cpp:2949
Definition: Item.h:37
cEnchantments m_Enchantments
Definition: Item.h:166
bool IsEmpty(void) const
Returns true if the item represents an empty stack - either the type is invalid, or count is zero.
Definition: Item.h:69
short m_ItemType
Definition: Item.h:163
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:215
cItem m_Armor
Definition: Horse.h:66
int GetHorseArmour(void) const
Definition: Horse.cpp:233
cItem m_Saddle
Definition: Horse.h:65
void SetHorseSaddle(cItem a_SaddleItem)
Set the horse's saddle to the given item.
Definition: Horse.cpp:195
bool m_bIsMouthOpen
Definition: Horse.h:62
bool IsSaddled(void) const
Definition: Horse.h:30
virtual void InStateIdle(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Horse.cpp:281
void PlayerOpenWindow(cPlayer &a_Player)
Definition: Horse.cpp:306
int m_RearTickCount
Definition: Horse.h:63
bool m_bIsTame
Definition: Horse.h:62
virtual void OnRemoveFromWorld(cWorld &a_World) override
Called when the entity is removed from a world.
Definition: Horse.cpp:113
int m_TameAttemptTimes
Definition: Horse.h:63
virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override
Definition: Horse.cpp:294
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Horse.cpp:35
void SetHorseArmor(cItem a_ArmorItem)
Set the horse's armor slot to the given item.
Definition: Horse.cpp:214
cHorse(int Type, int Color, int Style, int TameTimes)
Definition: Horse.cpp:13
virtual void OnRightClicked(cPlayer &a_Player) override
Called when the specified player right-clicks this entity.
Definition: Horse.cpp:128
virtual void GetDrops(cItems &a_Drops, cEntity *a_Killer=nullptr) override
Returns the list of drops for this pawn when it is killed.
Definition: Horse.cpp:254
float m_MaxSpeed
Definition: Horse.h:64
bool m_bIsRearing
Definition: Horse.h:62
int m_TimesToTame
Definition: Horse.h:63
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
bool m_IsLeashActionJustDone
Mob has ben leashed or unleashed in current player action.
Definition: Monster.h:344
virtual void InStateIdle(std::chrono::milliseconds a_Dt, cChunk &a_Chunk)
Definition: Monster.cpp:851
bool IsBaby(void) const
Definition: Monster.h:156
virtual void OnRemoveFromWorld(cWorld &a_World) override
Called when the entity is removed from a world.
Definition: Monster.cpp:139
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
virtual void OnRightClicked(cPlayer &a_Player) override
Called when the specified player right-clicks this entity.
cWindow * GetWindow(void) const
Definition: WindowOwner.h:40
void OpenWindow(cWindow *a_Window)
Definition: WindowOwner.h:34
Window owner that is associated with an entity (chest minecart etc.)
Definition: WindowOwner.h:82
Definition: World.h:53
virtual void BroadcastEntityMetadata(const cEntity &a_Entity, const cClientHandle *a_Exclude=nullptr) override
virtual void BroadcastParticleEffect(const AString &a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle *a_Exclude=nullptr) override
virtual void BroadcastSoundParticleEffect(const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle *a_Exclude=nullptr) override
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override