From 4ae3b64b077b444c8217f8da265cb5eedeaf699a Mon Sep 17 00:00:00 2001 From: Gargaj Date: Sun, 29 Nov 2015 19:13:31 +0100 Subject: implement breeding --- src/Mobs/PassiveMonster.cpp | 149 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 138 insertions(+), 11 deletions(-) (limited to 'src/Mobs/PassiveMonster.cpp') 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(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(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(m_Me); + cPassiveMonster * Partner = static_cast(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); + } + } +} + + + -- cgit v1.2.3