summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Mobs/Behaviors/Behavior.cpp10
-rw-r--r--src/Mobs/Behaviors/Behavior.h6
-rw-r--r--src/Mobs/Behaviors/BehaviorAggressive.cpp9
-rw-r--r--src/Mobs/Behaviors/BehaviorBreeder.cpp2
-rw-r--r--src/Mobs/Behaviors/BehaviorChaser.cpp36
-rw-r--r--src/Mobs/Behaviors/BehaviorChaser.h5
-rw-r--r--src/Mobs/Behaviors/BehaviorCoward.cpp14
-rw-r--r--src/Mobs/Behaviors/BehaviorCoward.h7
-rw-r--r--src/Mobs/Behaviors/BehaviorItemFollower.cpp27
-rw-r--r--src/Mobs/Behaviors/BehaviorItemFollower.h5
-rw-r--r--src/Mobs/Monster.cpp34
-rw-r--r--src/Mobs/Monster.h1
-rw-r--r--src/Mobs/PassiveMonster.cpp82
-rw-r--r--src/Mobs/Slime.cpp108
-rw-r--r--src/Mobs/Wolf.cpp648
-rw-r--r--src/MonsterConfig.cpp16
16 files changed, 529 insertions, 481 deletions
diff --git a/src/Mobs/Behaviors/Behavior.cpp b/src/Mobs/Behaviors/Behavior.cpp
index a8f719f66..7b54a3340 100644
--- a/src/Mobs/Behaviors/Behavior.cpp
+++ b/src/Mobs/Behaviors/Behavior.cpp
@@ -79,3 +79,13 @@ void cBehavior::Destroyed()
LOGD("ERROR: Called Destroyed on a behavior that doesn't have one.");
ASSERT(1 == 0);
}
+
+
+
+
+void cBehavior::DoTakeDamage(TakeDamageInfo & a_TDI)
+{
+ UNUSED(a_TDI);
+ LOGD("ERROR: Called DoTakeDamage on a behavior that doesn't have one.");
+ ASSERT(1 == 0);
+}
diff --git a/src/Mobs/Behaviors/Behavior.h b/src/Mobs/Behaviors/Behavior.h
index ce719f7e4..81499eade 100644
--- a/src/Mobs/Behaviors/Behavior.h
+++ b/src/Mobs/Behaviors/Behavior.h
@@ -1,5 +1,6 @@
#pragma once
+struct TakeDamageInfo;
class cBehavior
{
public:
@@ -9,7 +10,10 @@ public:
virtual void Tick();
virtual void PostTick();
virtual void PreTick();
+
+
virtual void onRightClicked();
virtual void Destroyed();
- virtual ~cBehavior() = 0;
+ virtual void DoTakeDamage(TakeDamageInfo & a_TDI);
+ virtual ~cBehavior() {}
};
diff --git a/src/Mobs/Behaviors/BehaviorAggressive.cpp b/src/Mobs/Behaviors/BehaviorAggressive.cpp
index b2c7cc9ef..d629d83ac 100644
--- a/src/Mobs/Behaviors/BehaviorAggressive.cpp
+++ b/src/Mobs/Behaviors/BehaviorAggressive.cpp
@@ -32,15 +32,6 @@ void cBehaviorAggressive::PreTick()
-void cBehaviorAggressive::Destroyed()
-{
- m_ParentChaser->SetTarget(nullptr);
-}
-
-
-
-
-
cPawn * cBehaviorAggressive::FindNewTarget()
{
cPlayer * Closest = m_Parent->GetNearestPlayer();
diff --git a/src/Mobs/Behaviors/BehaviorBreeder.cpp b/src/Mobs/Behaviors/BehaviorBreeder.cpp
index 34f5142e0..219846367 100644
--- a/src/Mobs/Behaviors/BehaviorBreeder.cpp
+++ b/src/Mobs/Behaviors/BehaviorBreeder.cpp
@@ -66,7 +66,7 @@ void cBehaviorBreeder::Tick()
m_LovePartner->GetBehaviorBreeder()->ResetLoveMode();
ResetLoveMode();
- }d
+ }
}
}
diff --git a/src/Mobs/Behaviors/BehaviorChaser.cpp b/src/Mobs/Behaviors/BehaviorChaser.cpp
index d4a72896a..71a50c55b 100644
--- a/src/Mobs/Behaviors/BehaviorChaser.cpp
+++ b/src/Mobs/Behaviors/BehaviorChaser.cpp
@@ -2,10 +2,10 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "BehaviorChaser.h"
+#include "BehaviorStriker.h"
#include "../Monster.h"
#include "../../Entities/Pawn.h"
-#include "BehaviorStriker.h"
-
+#include "../../Entities/Player.h"
@@ -15,7 +15,7 @@ cBehaviorChaser::cBehaviorChaser(cMonster * a_Parent) :
, m_AttackDamage(1)
, m_AttackRange(1)
, m_AttackCoolDownTicksLeft(0)
- , m_TicksSinceLastDamaged(50)
+ , m_TicksSinceLastDamaged(100)
{
ASSERT(m_Parent != nullptr);
}
@@ -36,8 +36,7 @@ bool cBehaviorChaser::IsControlDesired()
void cBehaviorChaser::Tick()
{
- ASSERT((GetTarget() == nullptr) || (GetTarget()->IsPawn() && (GetTarget()->GetWorld() == GetWorld())));
-
+ ASSERT((GetTarget() == nullptr) || (GetTarget()->IsPawn() && (GetTarget()->GetWorld() == m_Parent->GetWorld())));
// Stop targeting out of range targets
if (GetTarget() != nullptr)
{
@@ -71,7 +70,11 @@ void cBehaviorChaser::ApproachTarget()
void cBehaviorChaser::PostTick()
{
- ++m_TicksSinceLastDamaged;
+ if (m_TicksSinceLastDamaged < 100)
+ {
+ ++m_TicksSinceLastDamaged;
+ }
+
if (m_AttackCoolDownTicksLeft > 0)
{
m_AttackCoolDownTicksLeft -= 1;
@@ -82,6 +85,25 @@ void cBehaviorChaser::PostTick()
+void cBehaviorChaser::DoTakeDamage(TakeDamageInfo & a_TDI)
+{
+ if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn())
+ {
+ if (
+ (!a_TDI.Attacker->IsPlayer()) ||
+ (static_cast<cPlayer *>(a_TDI.Attacker)->CanMobsTarget())
+ )
+ {
+ SetTarget(static_cast<cPawn*>(a_TDI.Attacker));
+ }
+ m_TicksSinceLastDamaged = 0;
+ }
+}
+
+
+
+
+
void cBehaviorChaser::Destroyed()
{
SetTarget(nullptr);
@@ -194,7 +216,7 @@ void cBehaviorChaser::StrikeTarget()
cBehaviorStriker * Striker = m_Parent->GetBehaviorStriker();
if (Striker != nullptr)
{
- Striker->Strike(m_Target);
+ // Striker->Strike(m_Target); //mobTodo
}
ResetStrikeCooldown();
}
diff --git a/src/Mobs/Behaviors/BehaviorChaser.h b/src/Mobs/Behaviors/BehaviorChaser.h
index 75f3fc121..b71d503b3 100644
--- a/src/Mobs/Behaviors/BehaviorChaser.h
+++ b/src/Mobs/Behaviors/BehaviorChaser.h
@@ -24,6 +24,7 @@ public:
void Tick() override;
void Destroyed() override;
void PostTick() override;
+ void DoTakeDamage(TakeDamageInfo & a_TDI) override;
// Our host monster will call these once it loads its config file
void SetAttackRate(float a_AttackRate);
@@ -35,11 +36,9 @@ public:
/** Sets the target. */
void SetTarget(cPawn * a_Target);
-
- virtual ~cBehaviorChaser();
protected:
void ApproachTarget();
- // virtual void ApproachTarget() = 0;
+ // virtual void ApproachTarget() = 0; //mobTodo
private:
/** Our parent */
diff --git a/src/Mobs/Behaviors/BehaviorCoward.cpp b/src/Mobs/Behaviors/BehaviorCoward.cpp
index ec3626807..31927a5e8 100644
--- a/src/Mobs/Behaviors/BehaviorCoward.cpp
+++ b/src/Mobs/Behaviors/BehaviorCoward.cpp
@@ -16,12 +16,20 @@ cBehaviorCoward::cBehaviorCoward(cMonster * a_Parent) :
+bool cBehaviorCoward::IsControlDesired()
+{
+ return (m_Attacker != nullptr); //mobTodo probably not so safe pointer (and cChaser m_Target too)
+}
+
+
+
+
-bool cBehaviorCoward::Tick()
+void cBehaviorCoward::Tick()
{
if (m_Attacker == nullptr)
{
- return false;
+ return;
}
// TODO NOT SAFE
@@ -29,14 +37,12 @@ bool cBehaviorCoward::Tick()
{
// We lost the attacker
m_Attacker = nullptr;
- return false;
}
Vector3d newloc = m_Parent->GetPosition();
newloc.x = (m_Attacker->GetPosition().x < newloc.x)? (newloc.x + m_Parent->GetSightDistance()): (newloc.x - m_Parent->GetSightDistance());
newloc.z = (m_Attacker->GetPosition().z < newloc.z)? (newloc.z + m_Parent->GetSightDistance()): (newloc.z - m_Parent->GetSightDistance());
m_Parent->MoveToPosition(newloc);
- return true;
}
diff --git a/src/Mobs/Behaviors/BehaviorCoward.h b/src/Mobs/Behaviors/BehaviorCoward.h
index ed0ad3ed5..13deece61 100644
--- a/src/Mobs/Behaviors/BehaviorCoward.h
+++ b/src/Mobs/Behaviors/BehaviorCoward.h
@@ -10,14 +10,15 @@ class cItems;
class cEntity;
struct TakeDamageInfo;
-class cBehaviorCoward
+class cBehaviorCoward : cBehavior
{
public:
cBehaviorCoward(cMonster * a_Parent);
// Functions our host Monster should invoke:
- bool Tick();
- void DoTakeDamage(TakeDamageInfo & a_TDI);
+ bool IsControlDesired() override;
+ void Tick() override;
+ void DoTakeDamage(TakeDamageInfo & a_TDI) override;
private:
diff --git a/src/Mobs/Behaviors/BehaviorItemFollower.cpp b/src/Mobs/Behaviors/BehaviorItemFollower.cpp
index 2b0377c46..22c20d6b4 100644
--- a/src/Mobs/Behaviors/BehaviorItemFollower.cpp
+++ b/src/Mobs/Behaviors/BehaviorItemFollower.cpp
@@ -17,7 +17,30 @@ cBehaviorItemFollower::cBehaviorItemFollower(cMonster * a_Parent) :
-bool cBehaviorItemFollower::Tick()
+bool cBehaviorItemFollower::IsControlDesired()
+{
+ cItems FollowedItems;
+ m_Parent->GetFollowedItems(FollowedItems);
+ if (FollowedItems.Size() > 0)
+ {
+ cPlayer * a_Closest_Player = m_Parent->GetNearestPlayer();
+ if (a_Closest_Player != nullptr)
+ {
+ cItem EquippedItem = a_Closest_Player->GetEquippedItem();
+ if (FollowedItems.ContainsType(EquippedItem))
+ {
+ return true; // We take control of the monster. Now it'll call our tick
+ }
+ }
+ }
+ return false;
+}
+
+
+
+
+
+void cBehaviorItemFollower::Tick()
{
cItems FollowedItems;
m_Parent->GetFollowedItems(FollowedItems);
@@ -31,9 +54,7 @@ bool cBehaviorItemFollower::Tick()
{
Vector3d PlayerPos = a_Closest_Player->GetPosition();
m_Parent->MoveToPosition(PlayerPos);
- return true; // We took control of the monster, prevent other Behaviors from doing so
}
}
}
- return false;
}
diff --git a/src/Mobs/Behaviors/BehaviorItemFollower.h b/src/Mobs/Behaviors/BehaviorItemFollower.h
index 09acfe473..ab33de65f 100644
--- a/src/Mobs/Behaviors/BehaviorItemFollower.h
+++ b/src/Mobs/Behaviors/BehaviorItemFollower.h
@@ -9,7 +9,7 @@ class cBehaviorItemFollower;
class cMonster;
class cItems;
-class cBehaviorItemFollower
+class cBehaviorItemFollower : public cBehavior
{
public:
cBehaviorItemFollower(cMonster * a_Parent);
@@ -17,7 +17,8 @@ public:
void GetBreedingItems(cItems & a_Items);
// Functions our host Monster should invoke:
- void Tick();
+ bool IsControlDesired() override;
+ void Tick() override;
private:
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 65cce204b..246b433bd 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -300,10 +300,6 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
return;
}
- if (m_TicksSinceLastDamaged < 100)
- {
- ++m_TicksSinceLastDamaged;
- }
if ((GetTarget() != nullptr))
{
ASSERT(GetTarget()->IsTicking());
@@ -338,9 +334,12 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
Then STOP. */
if (
//mobTodo emstate
- (GetBehaviorDayLightBurner() != nullptr) && (m_TicksSinceLastDamaged >= 100) &&
+ /* (GetBehaviorDayLightBurner() != nullptr) && (m_TicksSinceLastDamaged >= 100) &&
GetBehaviorDayLightBurner()->WouldBurnAt(m_NextWayPointPosition, *Chunk) &&
- !(GetBehaviorDayLightBurner()->WouldBurnAt(GetPosition(), *Chunk))
+ !(GetBehaviorDayLightBurner()->WouldBurnAt(GetPosition(), *Chunk)) */
+ 1 == 0
+
+ // This logic should probably be in chaser
)
{
// If we burn in daylight, and we would burn at the next step, and we won't burn where we are right now, and we weren't provoked recently:
@@ -524,22 +523,14 @@ bool cMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
return false;
}
+
if (!m_SoundHurt.empty() && (m_Health > 0))
{
m_World->BroadcastSoundEffect(m_SoundHurt, GetPosX(), GetPosY(), GetPosZ(), 1.0f, 0.8f);
}
- if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn())
- {
- if (
- (!a_TDI.Attacker->IsPlayer()) ||
- (static_cast<cPlayer *>(a_TDI.Attacker)->CanMobsTarget())
- )
- {
- SetTarget(static_cast<cPawn*>(a_TDI.Attacker));
- }
- m_TicksSinceLastDamaged = 0;
- }
+ //mobTodo call all interested behaviors
+
return true;
}
@@ -665,15 +656,6 @@ void cMonster::OnRightClicked(cPlayer & a_Player)
-void cMonster::ResetAttackCooldown()
-{
- m_AttackCoolDownTicksLeft = static_cast<int>(3 * 20 * m_AttackRate); // A second has 20 ticks, an attack rate of 1 means 1 hit every 3 seconds
-}
-
-
-
-
-
void cMonster::SetCustomName(const AString & a_CustomName)
{
m_CustomName = a_CustomName;
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index 3e0a913bf..11737b5bf 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -130,7 +130,6 @@ public:
void SetDropChanceLeggings(float a_DropChanceLeggings) { m_DropChanceLeggings = a_DropChanceLeggings; }
void SetDropChanceBoots(float a_DropChanceBoots) { m_DropChanceBoots = a_DropChanceBoots; }
void SetCanPickUpLoot(bool a_CanPickUpLoot) { m_CanPickUpLoot = a_CanPickUpLoot; }
- void ResetAttackCooldown();
double GetRelativeWalkSpeed(void) const { return m_RelativeWalkSpeed; } // tolua_export
void SetRelativeWalkSpeed(double a_WalkSpeed) { m_RelativeWalkSpeed = a_WalkSpeed; } // tolua_export
diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp
index c5dab6d80..d4fa1840e 100644
--- a/src/Mobs/PassiveMonster.cpp
+++ b/src/Mobs/PassiveMonster.cpp
@@ -10,10 +10,10 @@
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_BehaviorBreeder(this), m_BehaviorItemFollower(this), m_BehaviorCoward(this), m_BehaviorWanderer(this)
+ super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height),
+ m_BehaviorBreeder(this), m_BehaviorItemFollower(this), m_BehaviorCoward(this), m_BehaviorWanderer(this)
{
- m_EMPersonality = PASSIVE;
+ m_EMPersonality = PASSIVE;
}
@@ -31,12 +31,12 @@ cPassiveMonster::~cPassiveMonster()
bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- if (!super::DoTakeDamage(a_TDI))
- {
- return false;
- }
- m_BehaviorCoward.DoTakeDamage(a_TDI);
- return true;
+ if (!super::DoTakeDamage(a_TDI))
+ {
+ return false;
+ }
+ m_BehaviorCoward.DoTakeDamage(a_TDI);
+ return true;
}
@@ -45,8 +45,8 @@ bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
void cPassiveMonster::Destroyed()
{
- m_BehaviorBreeder.Destroyed();
- super::Destroyed();
+ m_BehaviorBreeder.Destroyed();
+ super::Destroyed();
}
@@ -55,7 +55,7 @@ void cPassiveMonster::Destroyed()
cBehaviorBreeder * cPassiveMonster::GetBehaviorBreeder()
{
- return &m_BehaviorBreeder;
+ return &m_BehaviorBreeder;
}
@@ -64,38 +64,38 @@ cBehaviorBreeder * cPassiveMonster::GetBehaviorBreeder()
const cBehaviorBreeder * cPassiveMonster::GetBehaviorBreeder() const
{
- return static_cast<const cBehaviorBreeder *>(&m_BehaviorBreeder);
+ return static_cast<const cBehaviorBreeder *>(&m_BehaviorBreeder);
}
void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
- super::Tick(a_Dt, a_Chunk);
-
- for (;;)
- {
- if (m_BehaviorCoward.ActiveTick())
- {
- break;
- }
- if (m_BehaviorBreeder.Tick())
- {
- break;
- }
- if (m_BehaviorItemFollower.ActiveTick())
- {
- break;
- }
- if (m_BehaviorWanderer.ActiveTick(a_Dt, a_Chunk))
- {
- break;
- }
-
- ASSERT(!"Not a single Behavior took control, this is not normal. ");
- break;
- }
-
- m_BehaviorBreeder.PostTick();
+ super::Tick(a_Dt, a_Chunk);
+
+ for (;;)
+ {
+ /*if (m_BehaviorCoward.Tick())
+ {
+ break;
+ }
+ if (m_BehaviorBreeder.Tick())
+ {
+ break;
+ }
+ if (m_BehaviorItemFollower.Tick())
+ {
+ break;
+ }
+ if (m_BehaviorWanderer.ActiveTick(a_Dt, a_Chunk))
+ {
+ break;
+ }*/
+
+ ASSERT(!"Not a single Behavior took control, this is not normal. ");
+ break;
+ }
+
+ m_BehaviorBreeder.PostTick();
}
@@ -104,6 +104,6 @@ void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
void cPassiveMonster::OnRightClicked(cPlayer & a_Player)
{
- super::OnRightClicked(a_Player);
- m_BehaviorBreeder.OnRightClicked(a_Player);
+ super::OnRightClicked(a_Player);
+ m_BehaviorBreeder.OnRightClicked(a_Player);
}
diff --git a/src/Mobs/Slime.cpp b/src/Mobs/Slime.cpp
index df4c2f6ee..92c181798 100644
--- a/src/Mobs/Slime.cpp
+++ b/src/Mobs/Slime.cpp
@@ -10,17 +10,17 @@
cSlime::cSlime(int a_Size) :
- super("Slime",
- mtSlime,
- Printf("entity.%sslime.hurt", GetSizeName(a_Size).c_str()),
- Printf("entity.%sslime.death", GetSizeName(a_Size).c_str()),
- 0.6 * a_Size,
- 0.6 * a_Size
- ),
- m_Size(a_Size)
+ super("Slime",
+ mtSlime,
+ Printf("entity.%sslime.hurt", GetSizeName(a_Size).c_str()),
+ Printf("entity.%sslime.death", GetSizeName(a_Size).c_str()),
+ 0.6 * a_Size,
+ 0.6 * a_Size
+ ),
+ m_Size(a_Size)
{
- SetMaxHealth(a_Size * a_Size);
- SetAttackDamage(a_Size);
+ SetMaxHealth(a_Size * a_Size);
+ // SetAttackDamage(a_Size); //mobTodo myBehavior.setaTTACKDamage
}
@@ -29,17 +29,17 @@ cSlime::cSlime(int a_Size) :
void cSlime::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{
- unsigned int LootingLevel = 0;
- if (a_Killer != nullptr)
- {
- LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
- }
-
- // Only slimes with the size 1 can drop slimeballs.
- if (m_Size == 1)
- {
- AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SLIMEBALL);
- }
+ unsigned int LootingLevel = 0;
+ if (a_Killer != nullptr)
+ {
+ LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
+ }
+
+ // Only slimes with the size 1 can drop slimeballs.
+ if (m_Size == 1)
+ {
+ AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SLIMEBALL);
+ }
}
@@ -48,13 +48,13 @@ void cSlime::GetDrops(cItems & a_Drops, cEntity * a_Killer)
//mobTodo
/*bool cSlime::Attack(std::chrono::milliseconds a_Dt)
{
- if (m_Size > 1)
- {
- // Only slimes larger than size 1 attack a player.
- return super::Attack(a_Dt);
- }
+ if (m_Size > 1)
+ {
+ // Only slimes larger than size 1 attack a player.
+ return super::Attack(a_Dt);
+ }
- return false;
+ return false;
}*/
@@ -63,28 +63,28 @@ void cSlime::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cSlime::KilledBy(TakeDamageInfo & a_TDI)
{
- if (GetHealth() > 0)
- {
- return;
- }
-
- if (m_Size != 1)
- {
- auto & Random = GetRandomProvider();
- int SpawnAmount = Random.RandInt(2, 4);
-
- for (int i = 0; i < SpawnAmount; ++i)
- {
- double AddX = (i % 2 - 0.5) * m_Size / 4.0;
- double AddZ = (i / 2 - 0.5) * m_Size / 4.0;
-
- auto NewSlime = cpp14::make_unique<cSlime>(m_Size / 2);
- NewSlime->SetPosition(GetPosX() + AddX, GetPosY() + 0.5, GetPosZ() + AddZ);
- NewSlime->SetYaw(Random.RandReal(360.0f));
- m_World->SpawnMobFinalize(std::move(NewSlime));
- }
- }
- super::KilledBy(a_TDI);
+ if (GetHealth() > 0)
+ {
+ return;
+ }
+
+ if (m_Size != 1)
+ {
+ auto & Random = GetRandomProvider();
+ int SpawnAmount = Random.RandInt(2, 4);
+
+ for (int i = 0; i < SpawnAmount; ++i)
+ {
+ double AddX = (i % 2 - 0.5) * m_Size / 4.0;
+ double AddZ = (i / 2 - 0.5) * m_Size / 4.0;
+
+ auto NewSlime = cpp14::make_unique<cSlime>(m_Size / 2);
+ NewSlime->SetPosition(GetPosX() + AddX, GetPosY() + 0.5, GetPosZ() + AddZ);
+ NewSlime->SetYaw(Random.RandReal(360.0f));
+ m_World->SpawnMobFinalize(std::move(NewSlime));
+ }
+ }
+ super::KilledBy(a_TDI);
}
@@ -93,11 +93,11 @@ void cSlime::KilledBy(TakeDamageInfo & a_TDI)
AString cSlime::GetSizeName(int a_Size)
{
- if (a_Size == 1)
- {
- return "small_";
- }
- return "";
+ if (a_Size == 1)
+ {
+ return "small_";
+ }
+ return "";
}
diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp
index a92fb2071..d7ecb3d47 100644
--- a/src/Mobs/Wolf.cpp
+++ b/src/Mobs/Wolf.cpp
@@ -12,16 +12,16 @@
cWolf::cWolf(void) :
- super("Wolf", mtWolf, "entity.wolf.hurt", "entity.wolf.death", 0.6, 0.8),
- m_IsSitting(false),
- m_IsTame(false),
- m_IsBegging(false),
- m_IsAngry(false),
- m_OwnerName(""),
- m_CollarColor(E_META_DYE_ORANGE),
- m_NotificationCooldown(0)
+ super("Wolf", mtWolf, "entity.wolf.hurt", "entity.wolf.death", 0.6, 0.8),
+ m_IsSitting(false),
+ m_IsTame(false),
+ m_IsBegging(false),
+ m_IsAngry(false),
+ m_OwnerName(""),
+ m_CollarColor(E_META_DYE_ORANGE),
+ m_NotificationCooldown(0)
{
- m_RelativeWalkSpeed = 2;
+ m_RelativeWalkSpeed = 2;
}
@@ -30,43 +30,43 @@ cWolf::cWolf(void) :
bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- cPawn * PreviousTarget = GetTarget();
- if (!super::DoTakeDamage(a_TDI))
- {
- return false;
- }
-
- if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn())
- {
- auto currTarget = GetTarget();
- if ((currTarget != nullptr) && currTarget->IsPlayer())
- {
- if (m_IsTame)
- {
- if ((static_cast<cPlayer*>(currTarget)->GetUUID() == m_OwnerUUID))
- {
- SetTarget(PreviousTarget); // Do not attack owner
- }
- else
- {
- SetIsSitting(false);
- NotifyAlliesOfFight(static_cast<cPawn*>(a_TDI.Attacker));
- }
- }
- else
- {
- m_IsAngry = true;
- }
- }
- else if (m_IsTame)
- {
- SetIsSitting(false);
- NotifyAlliesOfFight(static_cast<cPawn*>(a_TDI.Attacker));
- }
- }
-
- m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face
- return true;
+ cPawn * PreviousTarget = GetTarget();
+ if (!super::DoTakeDamage(a_TDI))
+ {
+ return false;
+ }
+
+ if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn())
+ {
+ auto currTarget = GetTarget();
+ if ((currTarget != nullptr) && currTarget->IsPlayer())
+ {
+ if (m_IsTame)
+ {
+ if ((static_cast<cPlayer*>(currTarget)->GetUUID() == m_OwnerUUID))
+ {
+ SetTarget(PreviousTarget); // Do not attack owner
+ }
+ else
+ {
+ SetIsSitting(false);
+ NotifyAlliesOfFight(static_cast<cPawn*>(a_TDI.Attacker));
+ }
+ }
+ else
+ {
+ m_IsAngry = true;
+ }
+ }
+ else if (m_IsTame)
+ {
+ SetIsSitting(false);
+ NotifyAlliesOfFight(static_cast<cPawn*>(a_TDI.Attacker));
+ }
+ }
+
+ m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face
+ return true;
}
@@ -75,41 +75,41 @@ bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
void cWolf::NotifyAlliesOfFight(cPawn * a_Opponent)
{
- if (GetOwnerName() == "")
- {
- return;
- }
- m_NotificationCooldown = 15;
- class cCallback : public cPlayerListCallback
- {
- virtual bool Item(cPlayer * a_Player) override
- {
- a_Player->NotifyNearbyWolves(m_Opponent, false);
- return false;
- }
- public:
- cPawn * m_Opponent;
- } Callback;
-
- Callback.m_Opponent = a_Opponent;
- m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback);
+ if (GetOwnerName() == "")
+ {
+ return;
+ }
+ m_NotificationCooldown = 15;
+ class cCallback : public cPlayerListCallback
+ {
+ virtual bool Item(cPlayer * a_Player) override
+ {
+ a_Player->NotifyNearbyWolves(m_Opponent, false);
+ return false;
+ }
+ public:
+ cPawn * m_Opponent;
+ } Callback;
+
+ Callback.m_Opponent = a_Opponent;
+ m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback);
}
/*bool cWolf::Attack(std::chrono::milliseconds a_Dt)
{
- UNUSED(a_Dt);
+ UNUSED(a_Dt);
- if ((GetTarget() != nullptr) && (GetTarget()->IsPlayer()))
- {
- if (static_cast<cPlayer *>(GetTarget())->GetUUID() == m_OwnerUUID)
- {
- SetTarget(nullptr);
- return false;
- }
- }
+ if ((GetTarget() != nullptr) && (GetTarget()->IsPlayer()))
+ {
+ if (static_cast<cPlayer *>(GetTarget())->GetUUID() == m_OwnerUUID)
+ {
+ SetTarget(nullptr);
+ return false;
+ }
+ }
- NotifyAlliesOfFight(static_cast<cPawn*>(GetTarget()));
- return super::Attack(a_Dt);
+ NotifyAlliesOfFight(static_cast<cPawn*>(GetTarget()));
+ return super::Attack(a_Dt);
}*/
@@ -119,46 +119,46 @@ void cWolf::NotifyAlliesOfFight(cPawn * a_Opponent)
void cWolf::ReceiveNearbyFightInfo(AString a_PlayerID, cPawn * a_Opponent, bool a_IsPlayerInvolved)
{
- if (
- (a_Opponent == nullptr) || IsSitting() || (!IsTame()) ||
- (!a_Opponent->IsPawn()) || (a_PlayerID != m_OwnerUUID)
- )
- {
- return;
- }
-
- // If we already have a target
- if (GetTarget() != nullptr)
- {
- // If a wolf is asking for help and we already have a target, do nothing
- if (!a_IsPlayerInvolved)
- {
- return;
- }
- // If a player is asking for help and we already have a target,
- // there's a 50% chance of helping and a 50% chance of doing nothing
- // This helps spread a wolf pack's targets over several mobs
- else if (GetRandomProvider().RandBool())
- {
- return;
- }
- }
-
- if (a_Opponent->IsPlayer() && static_cast<cPlayer *>(a_Opponent)->GetUUID() == m_OwnerUUID)
- {
- return; // Our owner has hurt himself, avoid attacking them.
- }
-
- if (a_Opponent->IsMob() && static_cast<cMonster *>(a_Opponent)->GetMobType() == mtWolf)
- {
- cWolf * Wolf = static_cast<cWolf *>(a_Opponent);
- if (Wolf->GetOwnerUUID() == GetOwnerUUID())
- {
- return; // Our owner attacked one of their wolves. Abort attacking wolf.
- }
- }
-
- SetTarget(a_Opponent);
+ if (
+ (a_Opponent == nullptr) || IsSitting() || (!IsTame()) ||
+ (!a_Opponent->IsPawn()) || (a_PlayerID != m_OwnerUUID)
+ )
+ {
+ return;
+ }
+
+ // If we already have a target
+ if (GetTarget() != nullptr)
+ {
+ // If a wolf is asking for help and we already have a target, do nothing
+ if (!a_IsPlayerInvolved)
+ {
+ return;
+ }
+ // If a player is asking for help and we already have a target,
+ // there's a 50% chance of helping and a 50% chance of doing nothing
+ // This helps spread a wolf pack's targets over several mobs
+ else if (GetRandomProvider().RandBool())
+ {
+ return;
+ }
+ }
+
+ if (a_Opponent->IsPlayer() && static_cast<cPlayer *>(a_Opponent)->GetUUID() == m_OwnerUUID)
+ {
+ return; // Our owner has hurt himself, avoid attacking them.
+ }
+
+ if (a_Opponent->IsMob() && static_cast<cMonster *>(a_Opponent)->GetMobType() == mtWolf)
+ {
+ cWolf * Wolf = static_cast<cWolf *>(a_Opponent);
+ if (Wolf->GetOwnerUUID() == GetOwnerUUID())
+ {
+ return; // Our owner attacked one of their wolves. Abort attacking wolf.
+ }
+ }
+
+ SetTarget(a_Opponent);
}
@@ -169,82 +169,82 @@ void cWolf::ReceiveNearbyFightInfo(AString a_PlayerID, cPawn * a_Opponent, bool
void cWolf::OnRightClicked(cPlayer & a_Player)
{
- const cItem & EquippedItem = a_Player.GetEquippedItem();
- const int EquippedItemType = EquippedItem.m_ItemType;
-
- if (!IsTame() && !IsAngry())
- {
- // If the player is holding a bone, try to tame the wolf:
- if (EquippedItemType == E_ITEM_BONE)
- {
- if (!a_Player.IsGameModeCreative())
- {
- a_Player.GetInventory().RemoveOneEquippedItem();
- }
-
- if (GetRandomProvider().RandBool(0.125))
- {
- // Taming succeeded
- SetMaxHealth(20);
- SetIsTame(true);
- SetOwner(a_Player.GetName(), a_Player.GetUUID());
- m_World->BroadcastEntityStatus(*this, esWolfTamed);
- m_World->GetBroadcaster().BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
- }
- else
- {
- // Taming failed
- m_World->BroadcastEntityStatus(*this, esWolfTaming);
- m_World->GetBroadcaster().BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
- }
- }
- }
- else if (IsTame())
- {
- // Feed the wolf, restoring its health, or dye its collar:
- switch (EquippedItemType)
- {
- case E_ITEM_RAW_BEEF:
- case E_ITEM_STEAK:
- case E_ITEM_RAW_PORKCHOP:
- case E_ITEM_COOKED_PORKCHOP:
- case E_ITEM_RAW_CHICKEN:
- case E_ITEM_COOKED_CHICKEN:
- case E_ITEM_ROTTEN_FLESH:
- {
- if (m_Health < m_MaxHealth)
- {
- Heal(ItemHandler(EquippedItemType)->GetFoodInfo(&EquippedItem).FoodLevel);
- if (!a_Player.IsGameModeCreative())
- {
- a_Player.GetInventory().RemoveOneEquippedItem();
- }
- }
- break;
- }
- case E_ITEM_DYE:
- {
- if (a_Player.GetUUID() == m_OwnerUUID) // Is the player the owner of the dog?
- {
- SetCollarColor(EquippedItem.m_ItemDamage);
- if (!a_Player.IsGameModeCreative())
- {
- a_Player.GetInventory().RemoveOneEquippedItem();
- }
- }
- break;
- }
- default:
- {
- if (a_Player.GetUUID() == m_OwnerUUID) // Is the player the owner of the dog?
- {
- SetIsSitting(!IsSitting());
- }
- }
- }
- }
-
- m_World->BroadcastEntityMetadata(*this);
+ const cItem & EquippedItem = a_Player.GetEquippedItem();
+ const int EquippedItemType = EquippedItem.m_ItemType;
+
+ if (!IsTame() && !IsAngry())
+ {
+ // If the player is holding a bone, try to tame the wolf:
+ if (EquippedItemType == E_ITEM_BONE)
+ {
+ if (!a_Player.IsGameModeCreative())
+ {
+ a_Player.GetInventory().RemoveOneEquippedItem();
+ }
+
+ if (GetRandomProvider().RandBool(0.125))
+ {
+ // Taming succeeded
+ SetMaxHealth(20);
+ SetIsTame(true);
+ SetOwner(a_Player.GetName(), a_Player.GetUUID());
+ m_World->BroadcastEntityStatus(*this, esWolfTamed);
+ m_World->GetBroadcaster().BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
+ }
+ else
+ {
+ // Taming failed
+ m_World->BroadcastEntityStatus(*this, esWolfTaming);
+ m_World->GetBroadcaster().BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
+ }
+ }
+ }
+ else if (IsTame())
+ {
+ // Feed the wolf, restoring its health, or dye its collar:
+ switch (EquippedItemType)
+ {
+ case E_ITEM_RAW_BEEF:
+ case E_ITEM_STEAK:
+ case E_ITEM_RAW_PORKCHOP:
+ case E_ITEM_COOKED_PORKCHOP:
+ case E_ITEM_RAW_CHICKEN:
+ case E_ITEM_COOKED_CHICKEN:
+ case E_ITEM_ROTTEN_FLESH:
+ {
+ if (m_Health < m_MaxHealth)
+ {
+ Heal(ItemHandler(EquippedItemType)->GetFoodInfo(&EquippedItem).FoodLevel);
+ if (!a_Player.IsGameModeCreative())
+ {
+ a_Player.GetInventory().RemoveOneEquippedItem();
+ }
+ }
+ break;
+ }
+ case E_ITEM_DYE:
+ {
+ if (a_Player.GetUUID() == m_OwnerUUID) // Is the player the owner of the dog?
+ {
+ SetCollarColor(EquippedItem.m_ItemDamage);
+ if (!a_Player.IsGameModeCreative())
+ {
+ a_Player.GetInventory().RemoveOneEquippedItem();
+ }
+ }
+ break;
+ }
+ default:
+ {
+ if (a_Player.GetUUID() == m_OwnerUUID) // Is the player the owner of the dog?
+ {
+ SetIsSitting(!IsSitting());
+ }
+ }
+ }
+ }
+
+ m_World->BroadcastEntityMetadata(*this);
}
@@ -253,92 +253,96 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
- if (!IsAngry())
- {
- cMonster::Tick(a_Dt, a_Chunk);
- if (m_NotificationCooldown > 0)
- {
- m_NotificationCooldown -= 1;
- }
- }
- else
- {
- super::Tick(a_Dt, a_Chunk);
- }
-
- if (!IsTicking())
- {
- // The base class tick destroyed us
- return;
- }
-
- if (GetTarget() == nullptr)
- {
- cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance));
- if (a_Closest_Player != nullptr)
- {
- switch (a_Closest_Player->GetEquippedItem().m_ItemType)
- {
- case E_ITEM_BONE:
- case E_ITEM_RAW_BEEF:
- case E_ITEM_STEAK:
- case E_ITEM_RAW_CHICKEN:
- case E_ITEM_COOKED_CHICKEN:
- case E_ITEM_ROTTEN_FLESH:
- case E_ITEM_RAW_PORKCHOP:
- case E_ITEM_COOKED_PORKCHOP:
- {
- if (!IsBegging())
- {
- SetIsBegging(true);
- m_World->BroadcastEntityMetadata(*this);
- }
-
- m_FinalDestination = a_Closest_Player->GetPosition(); // So that we will look at a player holding food
-
- // Don't move to the player if the wolf is sitting.
- if (!IsSitting())
- {
- MoveToPosition(a_Closest_Player->GetPosition());
- }
-
- break;
- }
- default:
- {
- if (IsBegging())
- {
- SetIsBegging(false);
- m_World->BroadcastEntityMetadata(*this);
- }
- }
- }
- }
- }
- else
- {
- if (IsSitting())
- {
- SetTarget(nullptr);
- }
- else
- {
- MoveToPosition(GetTarget()->GetPosition());
- if (TargetIsInRange())
- {
- // Attack(a_Dt); mobTodo
- }
- }
- }
-
- if (IsTame() && !IsSitting())
- {
- TickFollowPlayer();
- }
- else if (IsSitting())
- {
- StopMovingToPosition();
- }
+ //mobTodo behaviors!
+
+ /*
+ if (!IsAngry())
+ {
+ cMonster::Tick(a_Dt, a_Chunk);
+ if (m_NotificationCooldown > 0)
+ {
+ m_NotificationCooldown -= 1;
+ }
+ }
+ else
+ {
+ super::Tick(a_Dt, a_Chunk);
+ }
+
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
+
+ if (GetTarget() == nullptr)
+ {
+ cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance));
+ if (a_Closest_Player != nullptr)
+ {
+ switch (a_Closest_Player->GetEquippedItem().m_ItemType)
+ {
+ case E_ITEM_BONE:
+ case E_ITEM_RAW_BEEF:
+ case E_ITEM_STEAK:
+ case E_ITEM_RAW_CHICKEN:
+ case E_ITEM_COOKED_CHICKEN:
+ case E_ITEM_ROTTEN_FLESH:
+ case E_ITEM_RAW_PORKCHOP:
+ case E_ITEM_COOKED_PORKCHOP:
+ {
+ if (!IsBegging())
+ {
+ SetIsBegging(true);
+ m_World->BroadcastEntityMetadata(*this);
+ }
+
+ m_FinalDestination = a_Closest_Player->GetPosition(); // So that we will look at a player holding food
+
+ // Don't move to the player if the wolf is sitting.
+ if (!IsSitting())
+ {
+ MoveToPosition(a_Closest_Player->GetPosition());
+ }
+
+ break;
+ }
+ default:
+ {
+ if (IsBegging())
+ {
+ SetIsBegging(false);
+ m_World->BroadcastEntityMetadata(*this);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (IsSitting())
+ {
+ SetTarget(nullptr);
+ }
+ else
+ {
+ MoveToPosition(GetTarget()->GetPosition());
+ if (TargetIsInRange())
+ {
+ // Attack(a_Dt); mobTodo
+ }
+ }
+ }
+
+ if (IsTame() && !IsSitting())
+ {
+ TickFollowPlayer();
+ }
+ else if (IsSitting())
+ {
+ StopMovingToPosition();
+ }
+ */
}
@@ -347,51 +351,51 @@ void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
void cWolf::TickFollowPlayer()
{
- class cCallback :
- public cPlayerListCallback
- {
- virtual bool Item(cPlayer * a_Player) override
- {
- OwnerPos = a_Player->GetPosition();
- OwnerFlying = a_Player->IsFlying();
- return true;
- }
- public:
- Vector3d OwnerPos;
- bool OwnerFlying;
- } Callback;
-
- if (m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback))
- {
- // The player is present in the world, follow him:
- double Distance = (Callback.OwnerPos - GetPosition()).Length();
- if (Distance > 20)
- {
- if (!Callback.OwnerFlying)
- {
- Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z);
- TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z);
- SetTarget(nullptr);
- }
- }
- if (Distance < 2)
- {
- if (GetTarget() == nullptr)
- {
- StopMovingToPosition();
- }
- }
- else
- {
- if (GetTarget() == nullptr)
- {
- if (!Callback.OwnerFlying)
- {
- MoveToPosition(Callback.OwnerPos);
- }
- }
- }
- }
+ class cCallback :
+ public cPlayerListCallback
+ {
+ virtual bool Item(cPlayer * a_Player) override
+ {
+ OwnerPos = a_Player->GetPosition();
+ OwnerFlying = a_Player->IsFlying();
+ return true;
+ }
+ public:
+ Vector3d OwnerPos;
+ bool OwnerFlying;
+ } Callback;
+
+ if (m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback))
+ {
+ // The player is present in the world, follow him:
+ double Distance = (Callback.OwnerPos - GetPosition()).Length();
+ if (Distance > 20)
+ {
+ if (!Callback.OwnerFlying)
+ {
+ Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z);
+ TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z);
+ SetTarget(nullptr);
+ }
+ }
+ if (Distance < 2)
+ {
+ if (GetTarget() == nullptr)
+ {
+ StopMovingToPosition();
+ }
+ }
+ else
+ {
+ if (GetTarget() == nullptr)
+ {
+ if (!Callback.OwnerFlying)
+ {
+ MoveToPosition(Callback.OwnerPos);
+ }
+ }
+ }
+ }
}
diff --git a/src/MonsterConfig.cpp b/src/MonsterConfig.cpp
index 28132607e..97336166c 100644
--- a/src/MonsterConfig.cpp
+++ b/src/MonsterConfig.cpp
@@ -3,6 +3,7 @@
#include "MonsterConfig.h"
#include "Mobs/Monster.h"
+#include "Mobs/Behaviors/BehaviorChaser.h"
#include "IniFile.h"
@@ -90,11 +91,18 @@ void cMonsterConfig::AssignAttributes(cMonster * a_Monster, const AString & a_Na
{
if (itr->m_Name.compare(a_Name) == 0)
{
- a_Monster->SetAttackDamage (itr->m_AttackDamage);
- a_Monster->SetAttackRange (itr->m_AttackRange);
- a_Monster->SetSightDistance(itr->m_SightDistance);
- a_Monster->SetAttackRate (static_cast<float>(itr->m_AttackRate));
+ cBehaviorChaser * Chaser = a_Monster->GetBehaviorChaser();
+
+ // mobTodo chaser is kind of "attacker", not really chaser?
+ if (Chaser != nullptr)
+ {
+ Chaser->SetAttackDamage (itr->m_AttackDamage);
+ Chaser->SetAttackRange (itr->m_AttackRange);
+ Chaser->SetAttackRate (static_cast<float>(itr->m_AttackRate));
+ }
+
a_Monster->SetMaxHealth (itr->m_MaxHealth);
+ a_Monster->SetSightDistance(itr->m_SightDistance);
a_Monster->SetIsFireproof (itr->m_IsFireproof);
return;
}