summaryrefslogtreecommitdiffstats
path: root/src/Mobs/PassiveMonster.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Mobs/PassiveMonster.cpp')
-rw-r--r--src/Mobs/PassiveMonster.cpp149
1 files changed, 138 insertions, 11 deletions
diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp
index a3d51da35..e39f6e23d 100644
--- a/src/Mobs/PassiveMonster.cpp
+++ b/src/Mobs/PassiveMonster.cpp
@@ -4,12 +4,17 @@
#include "PassiveMonster.h"
#include "../World.h"
#include "../Entities/Player.h"
+#include "BoundingBox.h"
cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) :
- super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height)
+ super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height),
+ m_LovePartner(nullptr),
+ m_LoveTimer(0),
+ m_LoveCooldown(0),
+ m_MatingTimer(0)
{
m_EMPersonality = PASSIVE;
}
@@ -35,6 +40,31 @@ bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
+void cPassiveMonster::EngageLoveMode(cPassiveMonster * a_Partner)
+{
+ m_LovePartner = a_Partner;
+ m_MatingTimer = 50; // about 3 seconds of mating
+}
+
+
+
+
+
+void cPassiveMonster::ResetLoveMode()
+{
+ m_LovePartner = nullptr;
+ m_LoveTimer = 0;
+ m_MatingTimer = 0;
+ m_LoveCooldown = 20 * 60 * 5; // 5 minutes
+
+ // 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
+ m_World->BroadcastEntityMetadata(*this);
+}
+
+
+
+
+
void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
@@ -43,25 +73,122 @@ void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
CheckEventLostPlayer();
}
- cItems FollowedItems;
- GetFollowedItems(FollowedItems);
- if (FollowedItems.Size() <= 0)
+ if ((m_LovePartner != nullptr) && m_LovePartner->IsDestroyed())
{
- return;
+ m_LovePartner = nullptr;
}
- cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance));
- if (a_Closest_Player != nullptr)
+ if (m_LovePartner != nullptr)
{
- cItem EquippedItem = a_Closest_Player->GetEquippedItem();
- if (FollowedItems.ContainsType(EquippedItem))
+ // if we have a partner, bump into them until baby is made
+ if (m_MatingTimer > 0)
{
- Vector3d PlayerPos = a_Closest_Player->GetPosition();
- MoveToPosition(PlayerPos);
+ Vector3d Pos = m_LovePartner->GetPosition();
+ MoveToPosition(Pos);
+ }
+ else
+ {
+ // spawn baby
+ Vector3f Pos = (GetPosition() + m_LovePartner->GetPosition()) * 0.5;
+ m_World->SpawnMob(Pos.x, Pos.y, Pos.z, GetMobType(), true);
+
+ cFastRandom Random;
+ m_World->SpawnExperienceOrb(Pos.x, Pos.y, Pos.z, 1 + Random.NextInt(6));
+
+ m_LovePartner->ResetLoveMode();
+ ResetLoveMode();
}
}
+ else
+ {
+ cItems FollowedItems;
+ GetFollowedItems(FollowedItems);
+ if (FollowedItems.Size() > 0)
+ {
+ cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance));
+ if (a_Closest_Player != nullptr)
+ {
+ cItem EquippedItem = a_Closest_Player->GetEquippedItem();
+ if (FollowedItems.ContainsType(EquippedItem))
+ {
+ Vector3d PlayerPos = a_Closest_Player->GetPosition();
+ MoveToPosition(PlayerPos);
+ }
+ }
+ }
+ }
+
+ if (m_LoveTimer > 0)
+ {
+ if (m_LovePartner == nullptr)
+ {
+ class LookForLover : public cEntityCallback
+ {
+ public:
+ cEntity * m_Me;
+
+ LookForLover(cEntity * a_Me) :
+ m_Me(a_Me)
+ {
+ }
+
+ virtual bool Item(cEntity * a_Entity) override
+ {
+ // if we're the same species as someone around and they dont have a partner, swipe right
+ if ((a_Entity->GetEntityType() == m_Me->GetEntityType()) && (a_Entity != m_Me))
+ {
+ cPassiveMonster * Me = static_cast<cPassiveMonster*>(m_Me);
+ cPassiveMonster * Partner = static_cast<cPassiveMonster*>(a_Entity);
+ if (Partner->IsInLove() && (Partner->GetPartner() == nullptr))
+ {
+ Partner->EngageLoveMode(Me);
+ Me->EngageLoveMode(Partner);
+ return true;
+ }
+ }
+ return false;
+ }
+ } Callback(this);
+
+ m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8), Callback);
+ }
+
+ m_LoveTimer--;
+ }
+ if (m_MatingTimer > 0)
+ {
+ m_MatingTimer--;
+ }
+ if (m_LoveCooldown > 0)
+ {
+ m_LoveCooldown--;
+ }
}
+void cPassiveMonster::OnRightClicked(cPlayer & a_Player)
+{
+ super::OnRightClicked(a_Player);
+
+ // if right clicked on the player with breeding items, go into lovemode
+ if ((m_LoveCooldown == 0) && !IsInLove() && !IsBaby())
+ {
+ short HeldItem = a_Player.GetEquippedItem().m_ItemType;
+ cItems Items;
+ GetBreedingItems(Items);
+ if (Items.ContainsType(HeldItem))
+ {
+ if (!a_Player.IsGameModeCreative())
+ {
+ a_Player.GetInventory().RemoveOneEquippedItem();
+ }
+ m_LoveTimer = 20 * 30; // half a minute
+ m_World->BroadcastEntityStatus(*this, esMobInLove);
+ }
+ }
+}
+
+
+