From 18c3dd3b4fc6c40c103296e7b5a53a99fa5e758e Mon Sep 17 00:00:00 2001 From: LogicParrot Date: Tue, 22 Aug 2017 15:15:36 +0300 Subject: d --- src/Mobs/Bat.cpp | 9 +- src/Mobs/Behaviors/BehaviorBreeder.cpp | 304 +++++++------ src/Mobs/Behaviors/BehaviorBreeder.h | 54 ++- src/Mobs/Behaviors/BehaviorItemFollower.cpp | 2 +- src/Mobs/Behaviors/BehaviorItemFollower.h | 10 +- src/Mobs/Blaze.cpp | 2 +- src/Mobs/CaveSpider.cpp | 2 +- src/Mobs/Chicken.cpp | 88 ++-- src/Mobs/Chicken.h | 24 +- src/Mobs/Cow.cpp | 42 +- src/Mobs/Cow.h | 20 +- src/Mobs/Creeper.cpp | 1 + src/Mobs/Creeper.h | 27 +- src/Mobs/Ghast.cpp | 56 +-- src/Mobs/Ghast.h | 13 +- src/Mobs/Monster.cpp | 11 +- src/Mobs/Monster.h | 6 +- src/Mobs/PassiveMonster.cpp | 4 +- src/Mobs/PassiveMonster.h | 4 +- src/Mobs/Silverfish.h | 14 +- src/Mobs/Skeleton.cpp | 94 ++-- src/Mobs/Skeleton.h | 20 +- src/Mobs/Slime.cpp | 114 ++--- src/Mobs/Slime.h | 32 +- src/Mobs/Spider.cpp | 92 ++-- src/Mobs/Wolf.cpp | 656 ++++++++++++++-------------- src/Mobs/Wolf.h | 104 ++--- 27 files changed, 897 insertions(+), 908 deletions(-) (limited to 'src/Mobs') diff --git a/src/Mobs/Bat.cpp b/src/Mobs/Bat.cpp index e419ceb2d..906b99320 100644 --- a/src/Mobs/Bat.cpp +++ b/src/Mobs/Bat.cpp @@ -4,12 +4,13 @@ #include "Bat.h" #include "../Chunk.h" - cBat::cBat(void) : - super("Bat", mtBat, "entity.bat.hurt", "entity.bat.death", 0.5, 0.9) + super("Bat", mtBat, "entity.bat.hurt", "entity.bat.death", 0.5, 0.9) { - SetGravity(-2.0f); - SetAirDrag(0.05f); + SetGravity(-2.0f); + SetAirDrag(0.05f); + + } diff --git a/src/Mobs/Behaviors/BehaviorBreeder.cpp b/src/Mobs/Behaviors/BehaviorBreeder.cpp index ea3e10026..ddca1715a 100644 --- a/src/Mobs/Behaviors/BehaviorBreeder.cpp +++ b/src/Mobs/Behaviors/BehaviorBreeder.cpp @@ -9,25 +9,15 @@ #include "../../Item.h" #include "../../BoundingBox.h" -iBehaviorBreeder::~iBehaviorBreeder() +cBehaviorBreeder::cBehaviorBreeder(cMonster * a_Parent) : + m_Parent(a_Parent), + m_LovePartner(nullptr), + m_LoveTimer(0), + m_LoveCooldown(0), + m_MatingTimer(0), { - -} - - - - - -cBehaviorBreeder::cBehaviorBreeder(cMonster * a_Parent, cItems & a_BreedingItems) : - m_Parent(a_Parent), - m_LovePartner(nullptr), - m_LoveTimer(0), - m_LoveCooldown(0), - m_MatingTimer(0), - m_BreedingItems(a_BreedingItems) -{ - m_Parent = dynamic_cast(m_ParentInterface); - ASSERT(m_Parent != nullptr); + m_Parent = a_Parent; + ASSERT(m_Parent != nullptr); } @@ -36,105 +26,105 @@ cBehaviorBreeder::cBehaviorBreeder(cMonster * a_Parent, cItems & a_BreedingItems bool cBehaviorBreeder::ActiveTick() { - cWorld * World = m_Parent->GetWorld(); - // 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(); - m_Parent->MoveToPosition(Pos); - } - else - { - // Mating finished. Spawn baby - Vector3f Pos = (m_Parent->GetPosition() + m_LovePartner->GetPosition()) * 0.5; - UInt32 BabyID = World->SpawnMob(Pos.x, Pos.y, Pos.z, m_Parent->GetMobType(), true); - - class cBabyInheritCallback : - public cEntityCallback - { - public: - cMonster * Baby; - cBabyInheritCallback() : Baby(nullptr) { } - virtual bool Item(cEntity * a_Entity) override - { - Baby = static_cast(a_Entity); - return true; - } - } Callback; - - m_Parent->GetWorld()->DoWithEntityByID(BabyID, Callback); - if (Callback.Baby != nullptr) - { - Callback.Baby->InheritFromParents(m_Parent, m_LovePartner); - } - - cFastRandom Random; - World->SpawnExperienceOrb(Pos.x, Pos.y, Pos.z, 1 + Random.NextInt(6)); - - m_LovePartner->GetBehaviorBreeder()->ResetLoveMode(); - ResetLoveMode(); - } - return true; - } - - // If we are in love mode and we have no partner - if (m_LoveTimer > 0) - { - class LookForLover : public cEntityCallback - { - public: - cMonster * m_Me; - LookForLover(cMonster * 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() != cEntity::eEntityType::etMonster) || (a_Entity == m_Me)) - { - return false; - } - - auto PotentialPartner = static_cast(a_Entity); - - // If the potential partner is not of the same species, don't breed with it - if (PotentialPartner->GetMobType() != m_Me->GetMobType()) - { - return false; - } - - auto PartnerBreedingBehavior = PotentialPartner->GetBehaviorBreeder(); - auto MyBreedingBehavior = m_Me->GetBehaviorBreeder(); - - // If the potential partner is not in love - // Or they already have a mate, do not breed with them - - if ((!PartnerBreedingBehavior->IsInLove()) || (PartnerBreedingBehavior->GetPartner() != nullptr)) - { - return false; - } - - // All conditions met, let's breed! - PartnerBreedingBehavior->EngageLoveMode(m_Me); - MyBreedingBehavior->EngageLoveMode(PotentialPartner); - return true; - } - } Callback(m_Parent); - - World->ForEachEntityInBox(cBoundingBox(m_Parent->GetPosition(), 8, 8), Callback); - if (m_LovePartner != nullptr) - { - return true; // We found love and took control of the monster, prevent other Behaviors from doing so - } - } - - return false; + cWorld * World = m_Parent->GetWorld(); + // 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(); + m_Parent->MoveToPosition(Pos); + } + else + { + // Mating finished. Spawn baby + Vector3f Pos = (m_Parent->GetPosition() + m_LovePartner->GetPosition()) * 0.5; + UInt32 BabyID = World->SpawnMob(Pos.x, Pos.y, Pos.z, m_Parent->GetMobType(), true); + + class cBabyInheritCallback : + public cEntityCallback + { + public: + cMonster * Baby; + cBabyInheritCallback() : Baby(nullptr) { } + virtual bool Item(cEntity * a_Entity) override + { + Baby = static_cast(a_Entity); + return true; + } + } Callback; + + m_Parent->GetWorld()->DoWithEntityByID(BabyID, Callback); + if (Callback.Baby != nullptr) + { + Callback.Baby->InheritFromParents(m_Parent, m_LovePartner); + } + + cFastRandom Random; + World->SpawnExperienceOrb(Pos.x, Pos.y, Pos.z, 1 + Random.NextInt(6)); + + m_LovePartner->GetBehaviorBreeder()->ResetLoveMode(); + ResetLoveMode(); + } + return true; + } + + // If we are in love mode and we have no partner + if (m_LoveTimer > 0) + { + class LookForLover : public cEntityCallback + { + public: + cMonster * m_Me; + LookForLover(cMonster * 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() != cEntity::eEntityType::etMonster) || (a_Entity == m_Me)) + { + return false; + } + + auto PotentialPartner = static_cast(a_Entity); + + // If the potential partner is not of the same species, don't breed with it + if (PotentialPartner->GetMobType() != m_Me->GetMobType()) + { + return false; + } + + auto PartnerBreedingBehavior = PotentialPartner->GetBehaviorBreeder(); + auto MyBreedingBehavior = m_Me->GetBehaviorBreeder(); + + // If the potential partner is not in love + // Or they already have a mate, do not breed with them + + if ((!PartnerBreedingBehavior->IsInLove()) || (PartnerBreedingBehavior->GetPartner() != nullptr)) + { + return false; + } + + // All conditions met, let's breed! + PartnerBreedingBehavior->EngageLoveMode(m_Me); + MyBreedingBehavior->EngageLoveMode(PotentialPartner); + return true; + } + } Callback(m_Parent); + + World->ForEachEntityInBox(cBoundingBox(m_Parent->GetPosition(), 8, 8), Callback); + if (m_LovePartner != nullptr) + { + return true; // We found love and took control of the monster, prevent other Behaviors from doing so + } + } + + return false; } @@ -143,18 +133,18 @@ bool cBehaviorBreeder::ActiveTick() void cBehaviorBreeder::Tick() { - if (m_MatingTimer > 0) - { - m_MatingTimer--; - } - if (m_LoveCooldown > 0) - { - m_LoveCooldown--; - } - if (m_LoveTimer > 0) - { - m_LoveTimer--; - } + if (m_MatingTimer > 0) + { + m_MatingTimer--; + } + if (m_LoveCooldown > 0) + { + m_LoveCooldown--; + } + if (m_LoveTimer > 0) + { + m_LoveTimer--; + } } @@ -163,10 +153,10 @@ void cBehaviorBreeder::Tick() void cBehaviorBreeder::Destroyed() { - if (m_LovePartner != nullptr) - { - m_LovePartner->GetBehaviorBreeder()->ResetLoveMode(); - } + if (m_LovePartner != nullptr) + { + m_LovePartner->GetBehaviorBreeder()->ResetLoveMode(); + } } @@ -175,28 +165,28 @@ void cBehaviorBreeder::Destroyed() void cBehaviorBreeder::OnRightClicked(cPlayer & a_Player) { - // If a player holding breeding items right-clicked me, go into love mode - if ((m_LoveCooldown == 0) && !IsInLove() && !m_Parent->IsBaby()) - { - short HeldItem = a_Player.GetEquippedItem().m_ItemType; - if (m_BreedingItems.ContainsType(HeldItem)) - { - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - } - m_LoveTimer = 20 * 30; // half a minute - m_Parent->GetWorld()->BroadcastEntityStatus(*m_Parent, cEntity::eEntityStatus::esMobInLove); - } - } + // If a player holding breeding items right-clicked me, go into love mode + if ((m_LoveCooldown == 0) && !IsInLove() && !m_Parent->IsBaby()) + { + short HeldItem = a_Player.GetEquippedItem().m_ItemType; + if (m_BreedingItems.ContainsType(HeldItem)) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + m_LoveTimer = 20 * 30; // half a minute + m_Parent->GetWorld()->BroadcastEntityStatus(*m_Parent, cEntity::eEntityStatus::esMobInLove); + } + } } void cBehaviorBreeder::EngageLoveMode(cMonster * a_Partner) { - m_LovePartner = a_Partner; - m_MatingTimer = 50; // about 3 seconds of mating + m_LovePartner = a_Partner; + m_MatingTimer = 50; // about 3 seconds of mating } @@ -205,13 +195,13 @@ void cBehaviorBreeder::EngageLoveMode(cMonster * a_Partner) void cBehaviorBreeder::ResetLoveMode() { - m_LovePartner = nullptr; - m_LoveTimer = 0; - m_MatingTimer = 0; - m_LoveCooldown = 20 * 60 * 5; // 5 minutes + 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_Parent->GetWorld()->BroadcastEntityMetadata(*m_Parent); + // 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_Parent->GetWorld()->BroadcastEntityMetadata(*m_Parent); } @@ -220,7 +210,7 @@ void cBehaviorBreeder::ResetLoveMode() bool cBehaviorBreeder::IsInLove() const { - return m_LoveTimer > 0; + return m_LoveTimer > 0; } @@ -229,5 +219,5 @@ bool cBehaviorBreeder::IsInLove() const bool cBehaviorBreeder::IsInLoveCooldown() const { - return (m_LoveCooldown > 0); + return (m_LoveCooldown > 0); } diff --git a/src/Mobs/Behaviors/BehaviorBreeder.h b/src/Mobs/Behaviors/BehaviorBreeder.h index 4d7dc1aa4..fa52a40d4 100644 --- a/src/Mobs/Behaviors/BehaviorBreeder.h +++ b/src/Mobs/Behaviors/BehaviorBreeder.h @@ -17,44 +17,42 @@ class cBehaviorBreeder { public: - cBehaviorBreeder(cMonster * a_Parent, cItems & a_BreedingItems); + cBehaviorBreeder(cMonster * a_Parent, cItems & a_BreedingItems); - // Functions our host Monster should invoke: - void Tick(); - bool ActiveTick(); - void OnRightClicked(cPlayer & a_Player); - void Destroyed(); + // Functions our host Monster should invoke: + void Tick(); + bool ActiveTick(); + void OnRightClicked(cPlayer & a_Player); + void Destroyed(); - /** Returns the partner which the monster is currently mating with. */ - cMonster * GetPartner(void) const { return m_LovePartner; } + /** Returns the partner which the monster is currently mating with. */ + cMonster * GetPartner(void) const { return m_LovePartner; } - /** Start the mating process. Causes the monster to keep bumping into the partner until m_MatingTimer reaches zero. */ - void EngageLoveMode(cMonster * a_Partner); + /** Start the mating process. Causes the monster to keep bumping into the partner until m_MatingTimer reaches zero. */ + void EngageLoveMode(cMonster * a_Partner); - /** Finish the mating process. Called after a baby is born. Resets all breeding related timers and sets m_LoveCooldown to 20 minutes. */ - void ResetLoveMode(); + /** Finish the mating process. Called after a baby is born. Resets all breeding related timers and sets m_LoveCooldown to 20 minutes. */ + void ResetLoveMode(); - /** Returns whether the monster has just been fed and is ready to mate. If this is "true" and GetPartner isn't "nullptr", then the monster is mating. */ - bool IsInLove() const; + /** Returns whether the monster has just been fed and is ready to mate. If this is "true" and GetPartner isn't "nullptr", then the monster is mating. */ + bool IsInLove() const; - /** Returns whether the monster is tired of breeding and is in the cooldown state. */ - bool IsInLoveCooldown() const; + /** Returns whether the monster is tired of breeding and is in the cooldown state. */ + bool IsInLoveCooldown() const; private: - /** Our parent */ - cMonster * m_Parent; + /** Our parent */ + cMonster * m_Parent; - /** The monster's breeding partner. */ - cMonster * m_LovePartner; + /** The monster's breeding partner. */ + cMonster * m_LovePartner; - /** If above 0, the monster is in love mode, and will breed if a nearby monster is also in love mode. Decrements by 1 per tick till reaching zero. */ - int m_LoveTimer; + /** If above 0, the monster is in love mode, and will breed if a nearby monster is also in love mode. Decrements by 1 per tick till reaching zero. */ + int m_LoveTimer; - /** If above 0, the monster is in cooldown mode and will refuse to breed. Decrements by 1 per tick till reaching zero. */ - int m_LoveCooldown; + /** If above 0, the monster is in cooldown mode and will refuse to breed. Decrements by 1 per tick till reaching zero. */ + int m_LoveCooldown; - /** The monster is engaged in mating, once this reaches zero, a baby will be born. Decrements by 1 per tick till reaching zero, then a baby is made and ResetLoveMode() is called. */ - int m_MatingTimer; - - cItems & m_BreedingItems; + /** The monster is engaged in mating, once this reaches zero, a baby will be born. Decrements by 1 per tick till reaching zero, then a baby is made and ResetLoveMode() is called. */ + int m_MatingTimer; }; diff --git a/src/Mobs/Behaviors/BehaviorItemFollower.cpp b/src/Mobs/Behaviors/BehaviorItemFollower.cpp index 89e25ed57..275cb8c24 100644 --- a/src/Mobs/Behaviors/BehaviorItemFollower.cpp +++ b/src/Mobs/Behaviors/BehaviorItemFollower.cpp @@ -21,7 +21,7 @@ bool cBehaviorItemFollower::ActiveTick() { cWorld * World = m_Parent->GetWorld(); cItems FollowedItems; - m_ParentInterface->GetFollowedItems(FollowedItems); + m_Parent->GetFollowedItems(FollowedItems); if (FollowedItems.Size() > 0) { cPlayer * a_Closest_Player = m_Parent->GetNearestPlayer(); diff --git a/src/Mobs/Behaviors/BehaviorItemFollower.h b/src/Mobs/Behaviors/BehaviorItemFollower.h index 2abdeb381..28f00c473 100644 --- a/src/Mobs/Behaviors/BehaviorItemFollower.h +++ b/src/Mobs/Behaviors/BehaviorItemFollower.h @@ -3,20 +3,16 @@ // Makes the mob follow specific held items class cBehaviorItemFollower; -class iBehaviorItemFollower; - //fwds class cMonster; class cItems; - - - - class cBehaviorItemFollower { public: - cBehaviorItemFollower(cMonster * a_Parent); + cBehaviorItemFollower(cMonster * a_Parent, cItems & a_Items); + + void GetBreedingItems(cItems & a_Items); // Functions our host Monster should invoke: bool ActiveTick(); diff --git a/src/Mobs/Blaze.cpp b/src/Mobs/Blaze.cpp index 7ada21369..e9126ff2d 100644 --- a/src/Mobs/Blaze.cpp +++ b/src/Mobs/Blaze.cpp @@ -9,7 +9,7 @@ cBlaze::cBlaze(void) : - super("Blaze", mtBlaze, "entity.blaze.hurt", "entity.blaze.death", 0.6, 1.8) + super("Blaze", mtBlaze, "entity.blaze.hurt", "entity.blaze.death", 0.6, 1.8, 15) { SetGravity(-8.0f); SetAirDrag(0.05f); diff --git a/src/Mobs/CaveSpider.cpp b/src/Mobs/CaveSpider.cpp index 8d8e15d85..78e04f7e0 100644 --- a/src/Mobs/CaveSpider.cpp +++ b/src/Mobs/CaveSpider.cpp @@ -8,7 +8,7 @@ cCaveSpider::cCaveSpider(void) : - super("CaveSpider", mtCaveSpider, "entity.spider.hurt", "entity.spider.death", 0.7, 0.5) + super("CaveSpider", mtCaveSpider, "entity.spider.hurt", "entity.spider.death", 0.7, 0.5, 15) { } diff --git a/src/Mobs/Chicken.cpp b/src/Mobs/Chicken.cpp index 1068295e6..80cff7fb8 100644 --- a/src/Mobs/Chicken.cpp +++ b/src/Mobs/Chicken.cpp @@ -5,16 +5,12 @@ - - - - cChicken::cChicken(void) : - super("Chicken", mtChicken, "entity.chicken.hurt", "entity.chicken.death", 0.3, 0.4), - m_EggDropTimer(0) + super("Chicken", mtChicken, "entity.chicken.hurt", "entity.chicken.death", 0.3, 0.4), + m_EggDropTimer(0) { - SetGravity(-2.0f); - SetAirDrag(0.0f); + SetGravity(-2.0f); + SetAirDrag(0.0f); } @@ -22,36 +18,36 @@ cChicken::cChicken(void) : void cChicken::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 (IsBaby()) - { - return; // Babies don't lay eggs - } - - if ((m_EggDropTimer == 6000) && GetRandomProvider().RandBool()) - { - cItems Drops; - m_EggDropTimer = 0; - Drops.push_back(cItem(E_ITEM_EGG, 1)); - m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); - } - else if (m_EggDropTimer == 12000) - { - cItems Drops; - m_EggDropTimer = 0; - Drops.push_back(cItem(E_ITEM_EGG, 1)); - m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); - } - else - { - m_EggDropTimer++; - } + super::Tick(a_Dt, a_Chunk); + if (!IsTicking()) + { + // The base class tick destroyed us + return; + } + + if (IsBaby()) + { + return; // Babies don't lay eggs + } + + if ((m_EggDropTimer == 6000) && GetRandomProvider().RandBool()) + { + cItems Drops; + m_EggDropTimer = 0; + Drops.push_back(cItem(E_ITEM_EGG, 1)); + m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); + } + else if (m_EggDropTimer == 12000) + { + cItems Drops; + m_EggDropTimer = 0; + Drops.push_back(cItem(E_ITEM_EGG, 1)); + m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); + } + else + { + m_EggDropTimer++; + } } @@ -60,13 +56,13 @@ void cChicken::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) void cChicken::GetDrops(cItems & a_Drops, cEntity * a_Killer) { - unsigned int LootingLevel = 0; - if (a_Killer != nullptr) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_FEATHER); - AddRandomDropItem(a_Drops, 1, 1, IsOnFire() ? E_ITEM_COOKED_CHICKEN : E_ITEM_RAW_CHICKEN); + unsigned int LootingLevel = 0; + if (a_Killer != nullptr) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_FEATHER); + AddRandomDropItem(a_Drops, 1, 1, IsOnFire() ? E_ITEM_COOKED_CHICKEN : E_ITEM_RAW_CHICKEN); } @@ -75,7 +71,7 @@ void cChicken::GetDrops(cItems & a_Drops, cEntity * a_Killer) void cChicken::HandleFalling(void) { - // empty - chickens don't take fall damage + // empty - chickens don't take fall damage } diff --git a/src/Mobs/Chicken.h b/src/Mobs/Chicken.h index 3be338b15..b954c19ec 100644 --- a/src/Mobs/Chicken.h +++ b/src/Mobs/Chicken.h @@ -7,28 +7,28 @@ class cChicken : - public cPassiveMonster + public cPassiveMonster { - typedef cPassiveMonster super; + typedef cPassiveMonster super; public: - cChicken(void); + cChicken(void); - CLASS_PROTODEF(cChicken) + CLASS_PROTODEF(cChicken) - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; - virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; + virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; - virtual void GetFollowedItems(cItems & a_Items) override - { - a_Items.Add(E_ITEM_SEEDS); - } + virtual void GetFollowedItems(cItems & a_Items) override + { + a_Items.Add(E_ITEM_SEEDS); + } - virtual void HandleFalling(void) override; + virtual void HandleFalling(void) override; private: - int m_EggDropTimer; + int m_EggDropTimer; } ; diff --git a/src/Mobs/Cow.cpp b/src/Mobs/Cow.cpp index 9736fe440..c92f2369f 100644 --- a/src/Mobs/Cow.cpp +++ b/src/Mobs/Cow.cpp @@ -6,12 +6,8 @@ - - - - cCow::cCow(void) : - super("Cow", mtCow, "entity.cow.hurt", "entity.cow.death", 0.9, 1.3) + super("Cow", mtCow, "entity.cow.hurt", "entity.cow.death", 0.9, 1.3) { } @@ -21,13 +17,13 @@ cCow::cCow(void) : void cCow::GetDrops(cItems & a_Drops, cEntity * a_Killer) { - unsigned int LootingLevel = 0; - if (a_Killer != nullptr) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER); - AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_STEAK : E_ITEM_RAW_BEEF); + unsigned int LootingLevel = 0; + if (a_Killer != nullptr) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER); + AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_STEAK : E_ITEM_RAW_BEEF); } @@ -36,15 +32,15 @@ void cCow::GetDrops(cItems & a_Drops, cEntity * a_Killer) void cCow::OnRightClicked(cPlayer & a_Player) { - super::OnRightClicked(a_Player); - - short HeldItem = a_Player.GetEquippedItem().m_ItemType; - if (HeldItem == E_ITEM_BUCKET) - { - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - a_Player.GetInventory().AddItem(E_ITEM_MILK); - } - } + super::OnRightClicked(a_Player); + + short HeldItem = a_Player.GetEquippedItem().m_ItemType; + if (HeldItem == E_ITEM_BUCKET) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + a_Player.GetInventory().AddItem(E_ITEM_MILK); + } + } } diff --git a/src/Mobs/Cow.h b/src/Mobs/Cow.h index 569c6e619..7b3cdb56e 100644 --- a/src/Mobs/Cow.h +++ b/src/Mobs/Cow.h @@ -8,22 +8,22 @@ class cCow : - public cPassiveMonster + public cPassiveMonster { - typedef cPassiveMonster super; + typedef cPassiveMonster super; public: - cCow(); + cCow(); - CLASS_PROTODEF(cCow) + CLASS_PROTODEF(cCow) - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; - virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; + virtual void OnRightClicked(cPlayer & a_Player) override; - virtual void GetFollowedItems(cItems & a_Items) override - { - a_Items.Add(E_ITEM_WHEAT); - } + virtual void GetFollowedItems(cItems & a_Items) override + { + a_Items.Add(E_ITEM_WHEAT); + } } ; diff --git a/src/Mobs/Creeper.cpp b/src/Mobs/Creeper.cpp index 505e637b0..f84a8acd7 100644 --- a/src/Mobs/Creeper.cpp +++ b/src/Mobs/Creeper.cpp @@ -125,6 +125,7 @@ bool cCreeper::DoTakeDamage(TakeDamageInfo & a_TDI) +// mobTODO /* bool cCreeper::Attack(std::chrono::milliseconds a_Dt) { diff --git a/src/Mobs/Creeper.h b/src/Mobs/Creeper.h index aea36def3..2ef72650b 100644 --- a/src/Mobs/Creeper.h +++ b/src/Mobs/Creeper.h @@ -8,29 +8,28 @@ class cCreeper : - public cAggressiveMonster + public cAggressiveMonster { - typedef cAggressiveMonster super; + typedef cAggressiveMonster super; public: - cCreeper(void); + cCreeper(void); - CLASS_PROTODEF(cCreeper) + CLASS_PROTODEF(cCreeper) - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; - virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; - virtual bool Attack(std::chrono::milliseconds a_Dt) override; - virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; - virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; + virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; + virtual void OnRightClicked(cPlayer & a_Player) override; - bool IsBlowing(void) const {return m_bIsBlowing; } - bool IsCharged(void) const {return m_bIsCharged; } - bool IsBurnedWithFlintAndSteel(void) const {return m_BurnedWithFlintAndSteel; } + bool IsBlowing(void) const {return m_bIsBlowing; } + bool IsCharged(void) const {return m_bIsCharged; } + bool IsBurnedWithFlintAndSteel(void) const {return m_BurnedWithFlintAndSteel; } private: - bool m_bIsBlowing, m_bIsCharged, m_BurnedWithFlintAndSteel; - int m_ExplodingTimer; + bool m_bIsBlowing, m_bIsCharged, m_BurnedWithFlintAndSteel; + int m_ExplodingTimer; } ; diff --git a/src/Mobs/Ghast.cpp b/src/Mobs/Ghast.cpp index 2488e63b1..97a27be5a 100644 --- a/src/Mobs/Ghast.cpp +++ b/src/Mobs/Ghast.cpp @@ -9,7 +9,7 @@ cGhast::cGhast(void) : - super("Ghast", mtGhast, "entity.ghast.hurt", "entity.ghast.death", 4, 4) + super("Ghast", mtGhast, "entity.ghast.hurt", "entity.ghast.death", 4, 4) { } @@ -19,39 +19,39 @@ cGhast::cGhast(void) : void cGhast::GetDrops(cItems & a_Drops, cEntity * a_Killer) { - unsigned int LootingLevel = 0; - if (a_Killer != nullptr) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER); - AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_GHAST_TEAR); + unsigned int LootingLevel = 0; + if (a_Killer != nullptr) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER); + AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_GHAST_TEAR); } - -bool cGhast::Attack(std::chrono::milliseconds a_Dt) +// mobTODO +/*bool cGhast::Attack(std::chrono::milliseconds a_Dt) { - if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0)) - { - // Setting this higher gives us more wiggle room for attackrate - Vector3d Speed = GetLookVector() * 20; - Speed.y = Speed.y + 1; - - auto GhastBall = cpp14::make_unique(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); - auto GhastBallPtr = GhastBall.get(); - if (!GhastBallPtr->Initialize(std::move(GhastBall), *m_World)) - { - return false; - } - - ResetAttackCooldown(); - return true; - } - return false; -} + if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0)) + { + // Setting this higher gives us more wiggle room for attackrate + Vector3d Speed = GetLookVector() * 20; + Speed.y = Speed.y + 1; + + auto GhastBall = cpp14::make_unique(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); + auto GhastBallPtr = GhastBall.get(); + if (!GhastBallPtr->Initialize(std::move(GhastBall), *m_World)) + { + return false; + } + + ResetAttackCooldown(); + return true; + } + return false; +}*/ diff --git a/src/Mobs/Ghast.h b/src/Mobs/Ghast.h index a41a72ddc..c3423590a 100644 --- a/src/Mobs/Ghast.h +++ b/src/Mobs/Ghast.h @@ -8,19 +8,18 @@ class cGhast : - public cAggressiveMonster + public cAggressiveMonster { - typedef cAggressiveMonster super; + typedef cAggressiveMonster super; public: - cGhast(void); + cGhast(void); - CLASS_PROTODEF(cGhast) + CLASS_PROTODEF(cGhast) - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; - virtual bool Attack(std::chrono::milliseconds a_Dt) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; - bool IsCharging(void) const {return false; } + bool IsCharging(void) const {return false; } } ; diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 059edbcbc..4513ea3f8 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -1167,13 +1167,17 @@ cBehaviorWanderer * cMonster::GetBehaviorWanderer() -void cMonster::InheritFromParents(cMonster * a_Parent1, cMonster * a_Parent2) +void cMonster::InheritFromParents(cPassiveMonster * a_Parent1, cPassiveMonster * a_Parent2) { UNUSED(a_Parent1); UNUSED(a_Parent2); return; } + + + + void cMonster::GetFollowedItems(cItems & a_Items) { return; @@ -1183,6 +1187,11 @@ void cMonster::GetFollowedItems(cItems & a_Items) +void cMonster::GetBreedingItems(cItems & a_Items) +{ + return GetFollowedItems(); +} + std::unique_ptr cMonster::NewMonsterFromType(eMonsterType a_MobType) { auto & Random = GetRandomProvider(); diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index 6308b2945..144228fe7 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -11,6 +11,7 @@ class cClientHandle; //Behavior fwds +class cPassiveMonster; class cBehaviorAggressive; class cBehaviorBreeder; class cBehaviorChaser; @@ -226,9 +227,10 @@ public: virtual cBehaviorStriker * GetBehaviorStriker(); virtual cBehaviorWanderer * GetBehaviorWanderer(); - // Polymorphic behavior functions - virtual void InheritFromParents(cMonster * a_Parent1, cMonster * a_Parent2); + // Polymorphic behavior functions ("Skin-specific") + virtual void InheritFromParents(cPassiveMonster * a_Parent1, cPassiveMonster * a_Parent2); virtual void GetFollowedItems(cItems & a_Items); + virtual void GetBreedingItems(cItems & a_Items); protected: diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp index 1c020232a..f8bc62c09 100644 --- a/src/Mobs/PassiveMonster.cpp +++ b/src/Mobs/PassiveMonster.cpp @@ -9,9 +9,9 @@ -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) : +cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height, cItem & a_BreedingItems, cItem & 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_BehaviorBreeder(this), m_BehaviorItemFollower(this), m_BehaviorCoward(this) { m_EMPersonality = PASSIVE; } diff --git a/src/Mobs/PassiveMonster.h b/src/Mobs/PassiveMonster.h index 012357024..1ab6d27e3 100644 --- a/src/Mobs/PassiveMonster.h +++ b/src/Mobs/PassiveMonster.h @@ -13,7 +13,9 @@ 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); + cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, + const AString & a_SoundHurt, const AString & a_SoundDeath, + double a_Width, double a_Height); virtual ~cPassiveMonster(); virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void OnRightClicked(cPlayer & a_Player) override; diff --git a/src/Mobs/Silverfish.h b/src/Mobs/Silverfish.h index 90ef5ea5d..c5d39a7a4 100644 --- a/src/Mobs/Silverfish.h +++ b/src/Mobs/Silverfish.h @@ -8,17 +8,17 @@ class cSilverfish : - public cAggressiveMonster + public cAggressiveMonster { - typedef cAggressiveMonster super; + typedef cAggressiveMonster super; public: - cSilverfish(void) : - super("Silverfish", mtSilverfish, "entity.silverfish.hurt", "entity.silverfish.death", 0.3, 0.7) - { - } + cSilverfish(void) : + super("Silverfish", mtSilverfish, "entity.silverfish.hurt", "entity.silverfish.death", 0.3, 0.7, 15) + { + } - CLASS_PROTODEF(cSilverfish) + CLASS_PROTODEF(cSilverfish) } ; diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp index e48991a06..22ea3e1bc 100644 --- a/src/Mobs/Skeleton.cpp +++ b/src/Mobs/Skeleton.cpp @@ -10,10 +10,10 @@ cSkeleton::cSkeleton(bool IsWither) : - super("Skeleton", mtSkeleton, "entity.skeleton.hurt", "entity.skeleton.death", 0.6, 1.8), - m_bIsWither(IsWither) + super("Skeleton", mtSkeleton, "entity.skeleton.hurt", "entity.skeleton.death", 0.6, 1.8), + m_bIsWither(IsWither) { - SetBurnsInDaylight(true); + SetBurnsInDaylight(true); } @@ -22,54 +22,54 @@ cSkeleton::cSkeleton(bool IsWither) : void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer) { - unsigned int LootingLevel = 0; - if (a_Killer != nullptr) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - if (IsWither()) - { - AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_COAL); - cItems RareDrops; - RareDrops.Add(cItem(E_ITEM_HEAD, 1, 1)); - AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); - } - else - { - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ARROW); - - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_BONE); - AddRandomArmorDropItem(a_Drops, LootingLevel); - AddRandomWeaponDropItem(a_Drops, LootingLevel); + unsigned int LootingLevel = 0; + if (a_Killer != nullptr) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + if (IsWither()) + { + AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_COAL); + cItems RareDrops; + RareDrops.Add(cItem(E_ITEM_HEAD, 1, 1)); + AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); + } + else + { + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ARROW); + + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_BONE); + AddRandomArmorDropItem(a_Drops, LootingLevel); + AddRandomWeaponDropItem(a_Drops, LootingLevel); } - -bool cSkeleton::Attack(std::chrono::milliseconds a_Dt) +//mobTodo +/*bool cSkeleton::Attack(std::chrono::milliseconds a_Dt) { - StopMovingToPosition(); // Todo handle this in a better way, the skeleton does some uneeded recalcs due to inStateChasing - auto & Random = GetRandomProvider(); - if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0)) - { - Vector3d Inaccuracy = Vector3d(Random.RandReal(-0.25, 0.25), Random.RandReal(-0.25, 0.25), Random.RandReal(-0.25, 0.25)); - Vector3d Speed = (GetTarget()->GetPosition() + Inaccuracy - GetPosition()) * 5; - Speed.y += Random.RandInt(-1, 1); - - auto Arrow = cpp14::make_unique(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); - auto ArrowPtr = Arrow.get(); - if (!ArrowPtr->Initialize(std::move(Arrow), *m_World)) - { - return false; - } - - ResetAttackCooldown(); - return true; - } - return false; -} + StopMovingToPosition(); // Todo handle this in a better way, the skeleton does some uneeded recalcs due to inStateChasing + auto & Random = GetRandomProvider(); + if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0)) + { + Vector3d Inaccuracy = Vector3d(Random.RandReal(-0.25, 0.25), Random.RandReal(-0.25, 0.25), Random.RandReal(-0.25, 0.25)); + Vector3d Speed = (GetTarget()->GetPosition() + Inaccuracy - GetPosition()) * 5; + Speed.y += Random.RandInt(-1, 1); + + auto Arrow = cpp14::make_unique(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); + auto ArrowPtr = Arrow.get(); + if (!ArrowPtr->Initialize(std::move(Arrow), *m_World)) + { + return false; + } + + ResetAttackCooldown(); + return true; + } + return false; +}*/ @@ -77,8 +77,8 @@ bool cSkeleton::Attack(std::chrono::milliseconds a_Dt) void cSkeleton::SpawnOn(cClientHandle & a_ClientHandle) { - super::SpawnOn(a_ClientHandle); - a_ClientHandle.SendEntityEquipment(*this, 0, cItem(E_ITEM_BOW)); + super::SpawnOn(a_ClientHandle); + a_ClientHandle.SendEntityEquipment(*this, 0, cItem(E_ITEM_BOW)); } diff --git a/src/Mobs/Skeleton.h b/src/Mobs/Skeleton.h index 0316fb9b5..91e094c4c 100644 --- a/src/Mobs/Skeleton.h +++ b/src/Mobs/Skeleton.h @@ -8,26 +8,26 @@ class cSkeleton : - public cAggressiveMonster + public cAggressiveMonster { - typedef cAggressiveMonster super; + typedef cAggressiveMonster super; public: - cSkeleton(bool IsWither); + cSkeleton(bool IsWither); - CLASS_PROTODEF(cSkeleton) + CLASS_PROTODEF(cSkeleton) - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; - virtual bool Attack(std::chrono::milliseconds a_Dt) override; - virtual void SpawnOn(cClientHandle & a_ClientHandle) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; + /*virtual bool Attack(std::chrono::milliseconds a_Dt) override;*/ + virtual void SpawnOn(cClientHandle & a_ClientHandle) override; - virtual bool IsUndead(void) override { return true; } + virtual bool IsUndead(void) override { return true; } - bool IsWither(void) const { return m_bIsWither; } + bool IsWither(void) const { return m_bIsWither; } private: - bool m_bIsWither; + bool m_bIsWither; } ; diff --git a/src/Mobs/Slime.cpp b/src/Mobs/Slime.cpp index 291a3a57f..df4c2f6ee 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); } @@ -29,33 +29,33 @@ 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); + } } - -bool cSlime::Attack(std::chrono::milliseconds a_Dt) +//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 @@ bool cSlime::Attack(std::chrono::milliseconds a_Dt) 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(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(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/Slime.h b/src/Mobs/Slime.h index c78461a02..26bc6716d 100644 --- a/src/Mobs/Slime.h +++ b/src/Mobs/Slime.h @@ -8,32 +8,32 @@ class cSlime : - public cAggressiveMonster + public cAggressiveMonster { - typedef cAggressiveMonster super; + typedef cAggressiveMonster super; public: - /** Creates a slime of the specified size; size can be 1, 2 or 4, with 1 is the smallest and 4 is the tallest. */ - cSlime(int a_Size); + /** Creates a slime of the specified size; size can be 1, 2 or 4, with 1 is the smallest and 4 is the tallest. */ + cSlime(int a_Size); - CLASS_PROTODEF(cSlime) + CLASS_PROTODEF(cSlime) - // cAggressiveMonster overrides: - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; - virtual bool Attack(std::chrono::milliseconds a_Dt) override; - virtual void KilledBy(TakeDamageInfo & a_TDI) override; + // cAggressiveMonster overrides: + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; + // virtual bool Attack(std::chrono::milliseconds a_Dt) override; + virtual void KilledBy(TakeDamageInfo & a_TDI) override; - int GetSize(void) const { return m_Size; } + int GetSize(void) const { return m_Size; } - /** Returns the text describing the slime's size, as used by the client's resource subsystem for sounds. - Returns either "big" or "small". */ - static AString GetSizeName(int a_Size); + /** Returns the text describing the slime's size, as used by the client's resource subsystem for sounds. + Returns either "big" or "small". */ + static AString GetSizeName(int a_Size); protected: - /** Size of the slime, with 1 being the smallest. - Vanilla uses sizes 1, 2 and 4 only. */ - int m_Size; + /** Size of the slime, with 1 being the smallest. + Vanilla uses sizes 1, 2 and 4 only. */ + int m_Size; } ; diff --git a/src/Mobs/Spider.cpp b/src/Mobs/Spider.cpp index 971ff22f6..89bd04ff5 100644 --- a/src/Mobs/Spider.cpp +++ b/src/Mobs/Spider.cpp @@ -9,7 +9,7 @@ cSpider::cSpider(void) : - super("Spider", mtSpider, "entity.spider.hurt", "entity.spider.death", 1.4, 0.9) + super("Spider", mtSpider, "entity.spider.hurt", "entity.spider.death", 1.4, 0.9, 11) { } @@ -19,16 +19,16 @@ cSpider::cSpider(void) : void cSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer) { - unsigned int LootingLevel = 0; - if (a_Killer != nullptr) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STRING); - if ((a_Killer != nullptr) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) - { - AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_SPIDER_EYE); - } + unsigned int LootingLevel = 0; + if (a_Killer != nullptr) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STRING); + if ((a_Killer != nullptr) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) + { + AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_SPIDER_EYE); + } } @@ -37,24 +37,24 @@ void cSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer) void cSpider::EventSeePlayer(cPlayer * a_Player, cChunk & a_Chunk) { - if (!GetWorld()->IsChunkLighted(GetChunkX(), GetChunkZ())) - { - return; - } - - PREPARE_REL_AND_CHUNK(GetPosition(), a_Chunk); - if (!RelSuccess) - { - return; - } - - if ( - a_Player->CanMobsTarget() && - !((Chunk->GetSkyLightAltered(Rel.x, Rel.y, Rel.z) > 11) || (Chunk->GetBlockLight(Rel.x, Rel.y, Rel.z) > 11)) - ) - { - super::EventSeePlayer(a_Player, a_Chunk); - } + if (!GetWorld()->IsChunkLighted(GetChunkX(), GetChunkZ())) + { + return; + } + + PREPARE_REL_AND_CHUNK(GetPosition(), a_Chunk); + if (!RelSuccess) + { + return; + } + + if ( + a_Player->CanMobsTarget() && + !((Chunk->GetSkyLightAltered(Rel.x, Rel.y, Rel.z) > 11) || (Chunk->GetBlockLight(Rel.x, Rel.y, Rel.z) > 11)) + ) + { + super::EventSeePlayer(a_Player, a_Chunk); + } } @@ -63,21 +63,21 @@ void cSpider::EventSeePlayer(cPlayer * a_Player, cChunk & a_Chunk) bool cSpider::DoTakeDamage(TakeDamageInfo & a_TDI) { - if (!super::DoTakeDamage(a_TDI)) - { - return false; - } - - // If the source of the damage is not from an pawn entity, switch to idle - if ((a_TDI.Attacker == nullptr) || !a_TDI.Attacker->IsPawn()) - { - m_EMState = IDLE; - } - else - { - // If the source of the damage is from a pawn entity, chase that entity - m_EMState = CHASING; - } - - return true; + if (!super::DoTakeDamage(a_TDI)) + { + return false; + } + + // If the source of the damage is not from an pawn entity, switch to idle + if ((a_TDI.Attacker == nullptr) || !a_TDI.Attacker->IsPawn()) + { + m_EMState = IDLE; + } + else + { + // If the source of the damage is from a pawn entity, chase that entity + m_EMState = CHASING; + } + + return true; } diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 33a9b31ee..520de483d 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(currTarget)->GetUUID() == m_OwnerUUID)) - { - SetTarget(PreviousTarget); // Do not attack owner - } - else - { - SetIsSitting(false); - NotifyAlliesOfFight(static_cast(a_TDI.Attacker)); - } - } - else - { - m_IsAngry = true; - } - } - else if (m_IsTame) - { - SetIsSitting(false); - NotifyAlliesOfFight(static_cast(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(currTarget)->GetUUID() == m_OwnerUUID)) + { + SetTarget(PreviousTarget); // Do not attack owner + } + else + { + SetIsSitting(false); + NotifyAlliesOfFight(static_cast(a_TDI.Attacker)); + } + } + else + { + m_IsAngry = true; + } + } + else if (m_IsTame) + { + SetIsSitting(false); + NotifyAlliesOfFight(static_cast(a_TDI.Attacker)); + } + } + + m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face + return true; } @@ -75,43 +75,43 @@ 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) +/*bool cWolf::Attack(std::chrono::milliseconds a_Dt) { - UNUSED(a_Dt); + UNUSED(a_Dt); - if ((GetTarget() != nullptr) && (GetTarget()->IsPlayer())) - { - if (static_cast(GetTarget())->GetUUID() == m_OwnerUUID) - { - SetTarget(nullptr); - return false; - } - } + if ((GetTarget() != nullptr) && (GetTarget()->IsPlayer())) + { + if (static_cast(GetTarget())->GetUUID() == m_OwnerUUID) + { + SetTarget(nullptr); + return false; + } + } - NotifyAlliesOfFight(static_cast(GetTarget())); - return super::Attack(a_Dt); + NotifyAlliesOfFight(static_cast(GetTarget())); + return super::Attack(a_Dt); -} +}*/ @@ -119,46 +119,46 @@ bool cWolf::Attack(std::chrono::milliseconds a_Dt) 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(a_Opponent)->GetUUID() == m_OwnerUUID) - { - return; // Our owner has hurt himself, avoid attacking them. - } - - if (a_Opponent->IsMob() && static_cast(a_Opponent)->GetMobType() == mtWolf) - { - cWolf * Wolf = static_cast(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(a_Opponent)->GetUUID() == m_OwnerUUID) + { + return; // Our owner has hurt himself, avoid attacking them. + } + + if (a_Opponent->IsMob() && static_cast(a_Opponent)->GetMobType() == mtWolf) + { + cWolf * Wolf = static_cast(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(GetPosition()), Vector3f{}, 0, 5); - } - else - { - // Taming failed - m_World->BroadcastEntityStatus(*this, esWolfTaming); - m_World->GetBroadcaster().BroadcastParticleEffect("smoke", static_cast(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(GetPosition()), Vector3f{}, 0, 5); + } + else + { + // Taming failed + m_World->BroadcastEntityStatus(*this, esWolfTaming); + m_World->GetBroadcaster().BroadcastParticleEffect("smoke", static_cast(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,92 @@ 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(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); - } - } - } - - if (IsTame() && !IsSitting()) - { - TickFollowPlayer(); - } - else if (IsSitting()) - { - StopMovingToPosition(); - } + 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(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); + } + } + } + + if (IsTame() && !IsSitting()) + { + TickFollowPlayer(); + } + else if (IsSitting()) + { + StopMovingToPosition(); + } } @@ -347,61 +347,61 @@ 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); + } + } + } + } } void cWolf::InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { - if (!IsTame()) - { - cMonster::InStateIdle(a_Dt, a_Chunk); - } + if (!IsTame()) + { + cMonster::InStateIdle(a_Dt, a_Chunk); + } } diff --git a/src/Mobs/Wolf.h b/src/Mobs/Wolf.h index e05fedbf8..f001fb559 100644 --- a/src/Mobs/Wolf.h +++ b/src/Mobs/Wolf.h @@ -9,64 +9,64 @@ class cEntity; class cWolf : - public cPassiveAggressiveMonster + public cPassiveAggressiveMonster { - typedef cPassiveAggressiveMonster super; + typedef cPassiveAggressiveMonster super; public: - cWolf(void); - - CLASS_PROTODEF(cWolf) - - void NotifyAlliesOfFight(cPawn * a_Opponent); - virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; - virtual void OnRightClicked(cPlayer & a_Player) override; - virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; - virtual void TickFollowPlayer(); - virtual bool Attack(std::chrono::milliseconds a_Dt) override; - - // Get functions - bool IsSitting (void) const override { return m_IsSitting; } - bool IsTame (void) const override { return m_IsTame; } - bool IsBegging (void) const { return m_IsBegging; } - bool IsAngry (void) const { return m_IsAngry; } - AString GetOwnerName (void) const { return m_OwnerName; } - AString GetOwnerUUID (void) const { return m_OwnerUUID; } - int GetCollarColor(void) const { return m_CollarColor; } - - // Set functions - void SetIsSitting (bool a_IsSitting) { m_IsSitting = a_IsSitting; } - void SetIsTame (bool a_IsTame) { m_IsTame = a_IsTame; } - void SetIsBegging (bool a_IsBegging) { m_IsBegging = a_IsBegging; } - void SetIsAngry (bool a_IsAngry) { m_IsAngry = a_IsAngry; } - void SetCollarColor(int a_CollarColor) { m_CollarColor = a_CollarColor; } - void SetOwner (const AString & a_NewOwnerName, const AString & a_NewOwnerUUID) - { - m_OwnerName = a_NewOwnerName; - m_OwnerUUID = a_NewOwnerUUID; - } - - /** Notfies the wolf of a nearby fight. - The wolf may then decide to attack a_Opponent. - If a_IsPlayer is true, then the player whose ID is a_PlayerID is fighting a_Opponent - If false, then a wolf owned by the player whose ID is a_PlayerID is fighting a_Opponent - @param a_PlayerID The ID of the fighting player, or the ID of the owner whose wolf is fighting. - @param a_Opponent The opponent who is being faught. - @param a_IsPlayerInvolved Whether the fighter a player or a wolf. */ - void ReceiveNearbyFightInfo(AString a_PlayerID, cPawn * a_Opponent, bool a_IsPlayerInvolved); - - virtual void InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; + cWolf(void); + + CLASS_PROTODEF(cWolf) + + void NotifyAlliesOfFight(cPawn * a_Opponent); + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; + virtual void TickFollowPlayer(); + //virtual bool Attack(std::chrono::milliseconds a_Dt) override; + + // Get functions + bool IsSitting (void) const override { return m_IsSitting; } + bool IsTame (void) const override { return m_IsTame; } + bool IsBegging (void) const { return m_IsBegging; } + bool IsAngry (void) const { return m_IsAngry; } + AString GetOwnerName (void) const { return m_OwnerName; } + AString GetOwnerUUID (void) const { return m_OwnerUUID; } + int GetCollarColor(void) const { return m_CollarColor; } + + // Set functions + void SetIsSitting (bool a_IsSitting) { m_IsSitting = a_IsSitting; } + void SetIsTame (bool a_IsTame) { m_IsTame = a_IsTame; } + void SetIsBegging (bool a_IsBegging) { m_IsBegging = a_IsBegging; } + void SetIsAngry (bool a_IsAngry) { m_IsAngry = a_IsAngry; } + void SetCollarColor(int a_CollarColor) { m_CollarColor = a_CollarColor; } + void SetOwner (const AString & a_NewOwnerName, const AString & a_NewOwnerUUID) + { + m_OwnerName = a_NewOwnerName; + m_OwnerUUID = a_NewOwnerUUID; + } + + /** Notfies the wolf of a nearby fight. + The wolf may then decide to attack a_Opponent. + If a_IsPlayer is true, then the player whose ID is a_PlayerID is fighting a_Opponent + If false, then a wolf owned by the player whose ID is a_PlayerID is fighting a_Opponent + @param a_PlayerID The ID of the fighting player, or the ID of the owner whose wolf is fighting. + @param a_Opponent The opponent who is being faught. + @param a_IsPlayerInvolved Whether the fighter a player or a wolf. */ + void ReceiveNearbyFightInfo(AString a_PlayerID, cPawn * a_Opponent, bool a_IsPlayerInvolved); + + virtual void InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; protected: - bool m_IsSitting; - bool m_IsTame; - bool m_IsBegging; - bool m_IsAngry; - AString m_OwnerName; - AString m_OwnerUUID; - int m_CollarColor; - int m_NotificationCooldown; + bool m_IsSitting; + bool m_IsTame; + bool m_IsBegging; + bool m_IsAngry; + AString m_OwnerName; + AString m_OwnerUUID; + int m_CollarColor; + int m_NotificationCooldown; } ; -- cgit v1.2.3