diff options
-rw-r--r-- | src/Mobs/Behaviors/Behavior.cpp | 10 | ||||
-rw-r--r-- | src/Mobs/Behaviors/Behavior.h | 6 | ||||
-rw-r--r-- | src/Mobs/Behaviors/BehaviorAggressive.cpp | 9 | ||||
-rw-r--r-- | src/Mobs/Behaviors/BehaviorBreeder.cpp | 2 | ||||
-rw-r--r-- | src/Mobs/Behaviors/BehaviorChaser.cpp | 36 | ||||
-rw-r--r-- | src/Mobs/Behaviors/BehaviorChaser.h | 5 | ||||
-rw-r--r-- | src/Mobs/Behaviors/BehaviorCoward.cpp | 14 | ||||
-rw-r--r-- | src/Mobs/Behaviors/BehaviorCoward.h | 7 | ||||
-rw-r--r-- | src/Mobs/Behaviors/BehaviorItemFollower.cpp | 27 | ||||
-rw-r--r-- | src/Mobs/Behaviors/BehaviorItemFollower.h | 5 | ||||
-rw-r--r-- | src/Mobs/Monster.cpp | 34 | ||||
-rw-r--r-- | src/Mobs/Monster.h | 1 | ||||
-rw-r--r-- | src/Mobs/PassiveMonster.cpp | 82 | ||||
-rw-r--r-- | src/Mobs/Slime.cpp | 108 | ||||
-rw-r--r-- | src/Mobs/Wolf.cpp | 648 | ||||
-rw-r--r-- | src/MonsterConfig.cpp | 16 |
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; } |