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.cpp288
1 files changed, 82 insertions, 206 deletions
diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp
index a2089e13f..1c020232a 100644
--- a/src/Mobs/PassiveMonster.cpp
+++ b/src/Mobs/PassiveMonster.cpp
@@ -5,215 +5,127 @@
#include "../World.h"
#include "../Entities/Player.h"
#include "BoundingBox.h"
-#include "../Items/ItemSpawnEgg.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),
- m_LovePartner(nullptr),
- m_LoveTimer(0),
- m_LoveCooldown(0),
- m_MatingTimer(0)
+cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height, cItems & a_BreedingItems, cItems & a_FollowedItems) :
+ super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height),
+ m_BehaviorBreeder(this), m_BehaviorItemFollower(this, a_FollowedItems), m_BehaviorCoward(this)
{
- m_EMPersonality = PASSIVE;
+ m_EMPersonality = PASSIVE;
}
-bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
+cPassiveMonster::~cPassiveMonster()
{
- if (!super::DoTakeDamage(a_TDI))
- {
- return false;
- }
- if ((a_TDI.Attacker != this) && (a_TDI.Attacker != nullptr))
- {
- m_EMState = ESCAPING;
- }
- return true;
+
}
-void cPassiveMonster::EngageLoveMode(cPassiveMonster * a_Partner)
+bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- m_LovePartner = a_Partner;
- m_MatingTimer = 50; // about 3 seconds of mating
+ if (!super::DoTakeDamage(a_TDI))
+#pragma once
+
+#include "Monster.h"
+#include "Behaviors/BehaviorBreeder.h"
+#include "Behaviors/BehaviorItemFollower.h"
+#include "Behaviors/BehaviorCoward.h"
+
+
+typedef std::string AString;
+class cPassiveMonster : public cMonster
+{
+ typedef cMonster super;
+
+public:
+ cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height, cItems & a_BreedingItems, cItems & a_FollowedItems);
+ virtual ~cPassiveMonster();
+ virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
+ virtual void OnRightClicked(cPlayer & a_Player) override;
+
+ /** When hit by someone, run away */
+ virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
+
+ virtual void Destroyed(void) override;
+
+private:
+ cBehaviorBreeder m_BehaviorBreeder;
+ cBehaviorItemFollower m_BehaviorItemFollower;
+ cBehaviorCoward m_BehaviorCoward;
+};
+
+ {
+ return false;
+ }
+ m_BehaviorCoward.DoTakeDamage(a_TDI);
+ return true;
}
-void cPassiveMonster::ResetLoveMode()
+void cPassiveMonster::Destroyed()
{
- 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);
+ m_BehaviorBreeder.Destroyed();
+ super::Destroyed();
}
-void cPassiveMonster::Destroyed()
+cBehaviorBreeder & cPassiveMonster::GetBehaviorBreeder()
{
- if (m_LovePartner != nullptr)
- {
- m_LovePartner->ResetLoveMode();
- }
- super::Destroyed();
+ return m_BehaviorBreeder;
}
+const cBehaviorBreeder & cPassiveMonster::GetBehaviorBreeder() const
+{
+ return static_cast<const cBehaviorBreeder &>(m_BehaviorBreeder);
+}
+
+
void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
- super::Tick(a_Dt, a_Chunk);
- if (!IsTicking())
- {
- // The base class tick destroyed us
- return;
- }
-
- if (m_EMState == ESCAPING)
- {
- CheckEventLostPlayer();
- }
-
- // if we have a partner, mate
- if (m_LovePartner != nullptr)
- {
-
- if (m_MatingTimer > 0)
- {
- // If we should still mate, keep bumping into them until baby is made
- Vector3d Pos = m_LovePartner->GetPosition();
- MoveToPosition(Pos);
- }
- else
- {
- // Mating finished. Spawn baby
- Vector3f Pos = (GetPosition() + m_LovePartner->GetPosition()) * 0.5;
- UInt32 BabyID = m_World->SpawnMob(Pos.x, Pos.y, Pos.z, GetMobType(), true);
-
- class cBabyInheritCallback :
- public cEntityCallback
- {
- public:
- cPassiveMonster * Baby;
- cBabyInheritCallback() : Baby(nullptr) { }
- virtual bool Item(cEntity * a_Entity) override
- {
- Baby = static_cast<cPassiveMonster *>(a_Entity);
- return true;
- }
- } Callback;
-
- m_World->DoWithEntityByID(BabyID, Callback);
- if (Callback.Baby != nullptr)
- {
- Callback.Baby->InheritFromParents(this, m_LovePartner);
- }
-
- m_World->SpawnExperienceOrb(Pos.x, Pos.y, Pos.z, GetRandomProvider().RandInt(1, 6));
-
- m_LovePartner->ResetLoveMode();
- ResetLoveMode();
- }
- }
- else
- {
- // We have no partner, so we just chase the player if they have our breeding item
- 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 we are in love mode but we have no partner, search for a partner neabry
- 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 the entity is not a monster, don't breed with it
- // Also, do not self-breed
- if ((a_Entity->GetEntityType() != etMonster) || (a_Entity == m_Me))
- {
- return false;
- }
-
- cPassiveMonster * Me = static_cast<cPassiveMonster*>(m_Me);
- cPassiveMonster * PotentialPartner = static_cast<cPassiveMonster*>(a_Entity);
-
- // If the potential partner is not of the same species, don't breed with it
- if (PotentialPartner->GetMobType() != Me->GetMobType())
- {
- return false;
- }
-
- // If the potential partner is not in love
- // Or they already have a mate, do not breed with them
- if ((!PotentialPartner->IsInLove()) || (PotentialPartner->GetPartner() != nullptr))
- {
- return false;
- }
-
- // All conditions met, let's breed!
- PotentialPartner->EngageLoveMode(Me);
- Me->EngageLoveMode(PotentialPartner);
- return true;
- }
- } Callback(this);
-
- m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8, -4), Callback);
- }
-
- m_LoveTimer--;
- }
- if (m_MatingTimer > 0)
- {
- m_MatingTimer--;
- }
- if (m_LoveCooldown > 0)
- {
- m_LoveCooldown--;
- }
+ super::Tick(a_Dt, a_Chunk);
+
+ for (;;)
+ {
+ if (m_BehaviorCoward.ActiveTick())
+ {
+ break;
+ }
+ if (m_BehaviorBreeder.ActiveTick())
+ {
+ break;
+ }
+ if (m_BehaviorItemFollower.ActiveTick())
+ {
+ break;
+ }
+ if (super::m_BehaviorWanderer.ActiveTick(a_Dt, a_Chunk))
+ {
+ break;
+ }
+
+ ASSERT(!"Not a single Behavior took control, this is not normal. ");
+ break;
+ }
+
+ m_BehaviorBreeder.Tick();
}
@@ -222,42 +134,6 @@ void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
void cPassiveMonster::OnRightClicked(cPlayer & a_Player)
{
- super::OnRightClicked(a_Player);
-
- const cItem & EquippedItem = a_Player.GetEquippedItem();
-
- // If a player holding breeding items right-clicked me, go into love mode
- if ((m_LoveCooldown == 0) && !IsInLove() && !IsBaby())
- {
- cItems Items;
- GetBreedingItems(Items);
- if (Items.ContainsType(EquippedItem.m_ItemType))
- {
- if (!a_Player.IsGameModeCreative())
- {
- a_Player.GetInventory().RemoveOneEquippedItem();
- }
- m_LoveTimer = 20 * 30; // half a minute
- m_World->BroadcastEntityStatus(*this, esMobInLove);
- }
- }
- // If a player holding my spawn egg right-clicked me, spawn a new baby
- if (EquippedItem.m_ItemType == E_ITEM_SPAWN_EGG)
- {
- eMonsterType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(EquippedItem.m_ItemDamage);
- if (
- (MonsterType == m_MobType) &&
- (m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), m_MobType, true) != cEntity::INVALID_ID) // Spawning succeeded
- )
- {
- if (!a_Player.IsGameModeCreative())
- {
- // The mob was spawned, "use" the item:
- a_Player.GetInventory().RemoveOneEquippedItem();
- }
- }
- }
+ super::OnRightClicked(a_Player);
+ m_BehaviorBreeder.OnRightClicked(a_Player);
}
-
-
-