From 77a36b58d8731821c88493742781cee0602d12ef Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Thu, 21 Aug 2014 08:12:05 -0600 Subject: Moved old mob code into its own sub directory --- src/Mobs/AggressiveMonster.cpp | 124 --- src/Mobs/AggressiveMonster.h | 33 - src/Mobs/Bat.cpp | 14 - src/Mobs/Bat.h | 25 - src/Mobs/Blaze.cpp | 57 -- src/Mobs/Blaze.h | 22 - src/Mobs/CaveSpider.cpp | 61 -- src/Mobs/CaveSpider.h | 26 - src/Mobs/Chicken.cpp | 66 -- src/Mobs/Chicken.h | 30 - src/Mobs/Cow.cpp | 48 -- src/Mobs/Cow.h | 29 - src/Mobs/Creeper.cpp | 152 ---- src/Mobs/Creeper.h | 38 - src/Mobs/EnderDragon.cpp | 27 - src/Mobs/EnderDragon.h | 25 - src/Mobs/Enderman.cpp | 183 ----- src/Mobs/Enderman.h | 42 - src/Mobs/Ghast.cpp | 61 -- src/Mobs/Ghast.h | 28 - src/Mobs/Giant.cpp | 27 - src/Mobs/Giant.h | 25 - src/Mobs/Horse.cpp | 157 ---- src/Mobs/Horse.h | 44 - src/Mobs/IronGolem.cpp | 28 - src/Mobs/IronGolem.h | 29 - src/Mobs/MagmaCube.cpp | 30 - src/Mobs/MagmaCube.h | 31 - src/Mobs/Monster.cpp | 1045 ------------------------ src/Mobs/Monster.h | 271 ------ src/Mobs/Mooshroom.cpp | 75 -- src/Mobs/Mooshroom.h | 28 - src/Mobs/Ocelot.h | 26 - src/Mobs/Old Mobs/AggressiveMonster.cpp | 124 +++ src/Mobs/Old Mobs/AggressiveMonster.h | 33 + src/Mobs/Old Mobs/Bat.cpp | 14 + src/Mobs/Old Mobs/Bat.h | 25 + src/Mobs/Old Mobs/Blaze.cpp | 57 ++ src/Mobs/Old Mobs/Blaze.h | 22 + src/Mobs/Old Mobs/CaveSpider.cpp | 61 ++ src/Mobs/Old Mobs/CaveSpider.h | 26 + src/Mobs/Old Mobs/Chicken.cpp | 66 ++ src/Mobs/Old Mobs/Chicken.h | 30 + src/Mobs/Old Mobs/Cow.cpp | 48 ++ src/Mobs/Old Mobs/Cow.h | 29 + src/Mobs/Old Mobs/Creeper.cpp | 152 ++++ src/Mobs/Old Mobs/Creeper.h | 38 + src/Mobs/Old Mobs/EnderDragon.cpp | 27 + src/Mobs/Old Mobs/EnderDragon.h | 25 + src/Mobs/Old Mobs/Enderman.cpp | 183 +++++ src/Mobs/Old Mobs/Enderman.h | 42 + src/Mobs/Old Mobs/Ghast.cpp | 61 ++ src/Mobs/Old Mobs/Ghast.h | 28 + src/Mobs/Old Mobs/Giant.cpp | 27 + src/Mobs/Old Mobs/Giant.h | 25 + src/Mobs/Old Mobs/Horse.cpp | 157 ++++ src/Mobs/Old Mobs/Horse.h | 44 + src/Mobs/Old Mobs/IronGolem.cpp | 28 + src/Mobs/Old Mobs/IronGolem.h | 29 + src/Mobs/Old Mobs/MagmaCube.cpp | 30 + src/Mobs/Old Mobs/MagmaCube.h | 31 + src/Mobs/Old Mobs/Monster.cpp | 1045 ++++++++++++++++++++++++ src/Mobs/Old Mobs/Monster.h | 271 ++++++ src/Mobs/Old Mobs/Mooshroom.cpp | 75 ++ src/Mobs/Old Mobs/Mooshroom.h | 28 + src/Mobs/Old Mobs/Ocelot.h | 26 + src/Mobs/Old Mobs/PassiveAggressiveMonster.cpp | 41 + src/Mobs/Old Mobs/PassiveAggressiveMonster.h | 23 + src/Mobs/Old Mobs/PassiveMonster.cpp | 65 ++ src/Mobs/Old Mobs/PassiveMonster.h | 30 + src/Mobs/Old Mobs/Pig.cpp | 100 +++ src/Mobs/Old Mobs/Pig.h | 36 + src/Mobs/Old Mobs/Sheep.cpp | 154 ++++ src/Mobs/Old Mobs/Sheep.h | 50 ++ src/Mobs/Old Mobs/Silverfish.h | 26 + src/Mobs/Old Mobs/Skeleton.cpp | 107 +++ src/Mobs/Old Mobs/Skeleton.h | 37 + src/Mobs/Old Mobs/Slime.cpp | 106 +++ src/Mobs/Old Mobs/Slime.h | 41 + src/Mobs/Old Mobs/SnowGolem.cpp | 46 ++ src/Mobs/Old Mobs/SnowGolem.h | 26 + src/Mobs/Old Mobs/Spider.cpp | 35 + src/Mobs/Old Mobs/Spider.h | 25 + src/Mobs/Old Mobs/Squid.cpp | 62 ++ src/Mobs/Old Mobs/Squid.h | 31 + src/Mobs/Old Mobs/Villager.cpp | 197 +++++ src/Mobs/Old Mobs/Villager.h | 66 ++ src/Mobs/Old Mobs/Witch.cpp | 47 ++ src/Mobs/Old Mobs/Witch.h | 28 + src/Mobs/Old Mobs/Wither.cpp | 136 +++ src/Mobs/Old Mobs/Wither.h | 45 + src/Mobs/Old Mobs/Wolf.cpp | 246 ++++++ src/Mobs/Old Mobs/Wolf.h | 61 ++ src/Mobs/Old Mobs/Zombie.cpp | 62 ++ src/Mobs/Old Mobs/Zombie.h | 36 + src/Mobs/Old Mobs/ZombiePigman.cpp | 53 ++ src/Mobs/Old Mobs/ZombiePigman.h | 27 + src/Mobs/PassiveAggressiveMonster.cpp | 41 - src/Mobs/PassiveAggressiveMonster.h | 23 - src/Mobs/PassiveMonster.cpp | 65 -- src/Mobs/PassiveMonster.h | 30 - src/Mobs/Pig.cpp | 100 --- src/Mobs/Pig.h | 36 - src/Mobs/Sheep.cpp | 154 ---- src/Mobs/Sheep.h | 50 -- src/Mobs/Silverfish.h | 26 - src/Mobs/Skeleton.cpp | 107 --- src/Mobs/Skeleton.h | 37 - src/Mobs/Slime.cpp | 106 --- src/Mobs/Slime.h | 41 - src/Mobs/SnowGolem.cpp | 46 -- src/Mobs/SnowGolem.h | 26 - src/Mobs/Spider.cpp | 35 - src/Mobs/Spider.h | 25 - src/Mobs/Squid.cpp | 62 -- src/Mobs/Squid.h | 31 - src/Mobs/Villager.cpp | 197 ----- src/Mobs/Villager.h | 66 -- src/Mobs/Witch.cpp | 47 -- src/Mobs/Witch.h | 28 - src/Mobs/Wither.cpp | 136 --- src/Mobs/Wither.h | 45 - src/Mobs/Wolf.cpp | 246 ------ src/Mobs/Wolf.h | 61 -- src/Mobs/Zombie.cpp | 62 -- src/Mobs/Zombie.h | 36 - src/Mobs/ZombiePigman.cpp | 53 -- src/Mobs/ZombiePigman.h | 27 - 128 files changed, 4952 insertions(+), 4952 deletions(-) delete mode 100644 src/Mobs/AggressiveMonster.cpp delete mode 100644 src/Mobs/AggressiveMonster.h delete mode 100644 src/Mobs/Bat.cpp delete mode 100644 src/Mobs/Bat.h delete mode 100644 src/Mobs/Blaze.cpp delete mode 100644 src/Mobs/Blaze.h delete mode 100644 src/Mobs/CaveSpider.cpp delete mode 100644 src/Mobs/CaveSpider.h delete mode 100644 src/Mobs/Chicken.cpp delete mode 100644 src/Mobs/Chicken.h delete mode 100644 src/Mobs/Cow.cpp delete mode 100644 src/Mobs/Cow.h delete mode 100644 src/Mobs/Creeper.cpp delete mode 100644 src/Mobs/Creeper.h delete mode 100644 src/Mobs/EnderDragon.cpp delete mode 100644 src/Mobs/EnderDragon.h delete mode 100644 src/Mobs/Enderman.cpp delete mode 100644 src/Mobs/Enderman.h delete mode 100644 src/Mobs/Ghast.cpp delete mode 100644 src/Mobs/Ghast.h delete mode 100644 src/Mobs/Giant.cpp delete mode 100644 src/Mobs/Giant.h delete mode 100644 src/Mobs/Horse.cpp delete mode 100644 src/Mobs/Horse.h delete mode 100644 src/Mobs/IronGolem.cpp delete mode 100644 src/Mobs/IronGolem.h delete mode 100644 src/Mobs/MagmaCube.cpp delete mode 100644 src/Mobs/MagmaCube.h delete mode 100644 src/Mobs/Monster.cpp delete mode 100644 src/Mobs/Monster.h delete mode 100644 src/Mobs/Mooshroom.cpp delete mode 100644 src/Mobs/Mooshroom.h delete mode 100644 src/Mobs/Ocelot.h create mode 100644 src/Mobs/Old Mobs/AggressiveMonster.cpp create mode 100644 src/Mobs/Old Mobs/AggressiveMonster.h create mode 100644 src/Mobs/Old Mobs/Bat.cpp create mode 100644 src/Mobs/Old Mobs/Bat.h create mode 100644 src/Mobs/Old Mobs/Blaze.cpp create mode 100644 src/Mobs/Old Mobs/Blaze.h create mode 100644 src/Mobs/Old Mobs/CaveSpider.cpp create mode 100644 src/Mobs/Old Mobs/CaveSpider.h create mode 100644 src/Mobs/Old Mobs/Chicken.cpp create mode 100644 src/Mobs/Old Mobs/Chicken.h create mode 100644 src/Mobs/Old Mobs/Cow.cpp create mode 100644 src/Mobs/Old Mobs/Cow.h create mode 100644 src/Mobs/Old Mobs/Creeper.cpp create mode 100644 src/Mobs/Old Mobs/Creeper.h create mode 100644 src/Mobs/Old Mobs/EnderDragon.cpp create mode 100644 src/Mobs/Old Mobs/EnderDragon.h create mode 100644 src/Mobs/Old Mobs/Enderman.cpp create mode 100644 src/Mobs/Old Mobs/Enderman.h create mode 100644 src/Mobs/Old Mobs/Ghast.cpp create mode 100644 src/Mobs/Old Mobs/Ghast.h create mode 100644 src/Mobs/Old Mobs/Giant.cpp create mode 100644 src/Mobs/Old Mobs/Giant.h create mode 100644 src/Mobs/Old Mobs/Horse.cpp create mode 100644 src/Mobs/Old Mobs/Horse.h create mode 100644 src/Mobs/Old Mobs/IronGolem.cpp create mode 100644 src/Mobs/Old Mobs/IronGolem.h create mode 100644 src/Mobs/Old Mobs/MagmaCube.cpp create mode 100644 src/Mobs/Old Mobs/MagmaCube.h create mode 100644 src/Mobs/Old Mobs/Monster.cpp create mode 100644 src/Mobs/Old Mobs/Monster.h create mode 100644 src/Mobs/Old Mobs/Mooshroom.cpp create mode 100644 src/Mobs/Old Mobs/Mooshroom.h create mode 100644 src/Mobs/Old Mobs/Ocelot.h create mode 100644 src/Mobs/Old Mobs/PassiveAggressiveMonster.cpp create mode 100644 src/Mobs/Old Mobs/PassiveAggressiveMonster.h create mode 100644 src/Mobs/Old Mobs/PassiveMonster.cpp create mode 100644 src/Mobs/Old Mobs/PassiveMonster.h create mode 100644 src/Mobs/Old Mobs/Pig.cpp create mode 100644 src/Mobs/Old Mobs/Pig.h create mode 100644 src/Mobs/Old Mobs/Sheep.cpp create mode 100644 src/Mobs/Old Mobs/Sheep.h create mode 100644 src/Mobs/Old Mobs/Silverfish.h create mode 100644 src/Mobs/Old Mobs/Skeleton.cpp create mode 100644 src/Mobs/Old Mobs/Skeleton.h create mode 100644 src/Mobs/Old Mobs/Slime.cpp create mode 100644 src/Mobs/Old Mobs/Slime.h create mode 100644 src/Mobs/Old Mobs/SnowGolem.cpp create mode 100644 src/Mobs/Old Mobs/SnowGolem.h create mode 100644 src/Mobs/Old Mobs/Spider.cpp create mode 100644 src/Mobs/Old Mobs/Spider.h create mode 100644 src/Mobs/Old Mobs/Squid.cpp create mode 100644 src/Mobs/Old Mobs/Squid.h create mode 100644 src/Mobs/Old Mobs/Villager.cpp create mode 100644 src/Mobs/Old Mobs/Villager.h create mode 100644 src/Mobs/Old Mobs/Witch.cpp create mode 100644 src/Mobs/Old Mobs/Witch.h create mode 100644 src/Mobs/Old Mobs/Wither.cpp create mode 100644 src/Mobs/Old Mobs/Wither.h create mode 100644 src/Mobs/Old Mobs/Wolf.cpp create mode 100644 src/Mobs/Old Mobs/Wolf.h create mode 100644 src/Mobs/Old Mobs/Zombie.cpp create mode 100644 src/Mobs/Old Mobs/Zombie.h create mode 100644 src/Mobs/Old Mobs/ZombiePigman.cpp create mode 100644 src/Mobs/Old Mobs/ZombiePigman.h delete mode 100644 src/Mobs/PassiveAggressiveMonster.cpp delete mode 100644 src/Mobs/PassiveAggressiveMonster.h delete mode 100644 src/Mobs/PassiveMonster.cpp delete mode 100644 src/Mobs/PassiveMonster.h delete mode 100644 src/Mobs/Pig.cpp delete mode 100644 src/Mobs/Pig.h delete mode 100644 src/Mobs/Sheep.cpp delete mode 100644 src/Mobs/Sheep.h delete mode 100644 src/Mobs/Silverfish.h delete mode 100644 src/Mobs/Skeleton.cpp delete mode 100644 src/Mobs/Skeleton.h delete mode 100644 src/Mobs/Slime.cpp delete mode 100644 src/Mobs/Slime.h delete mode 100644 src/Mobs/SnowGolem.cpp delete mode 100644 src/Mobs/SnowGolem.h delete mode 100644 src/Mobs/Spider.cpp delete mode 100644 src/Mobs/Spider.h delete mode 100644 src/Mobs/Squid.cpp delete mode 100644 src/Mobs/Squid.h delete mode 100644 src/Mobs/Villager.cpp delete mode 100644 src/Mobs/Villager.h delete mode 100644 src/Mobs/Witch.cpp delete mode 100644 src/Mobs/Witch.h delete mode 100644 src/Mobs/Wither.cpp delete mode 100644 src/Mobs/Wither.h delete mode 100644 src/Mobs/Wolf.cpp delete mode 100644 src/Mobs/Wolf.h delete mode 100644 src/Mobs/Zombie.cpp delete mode 100644 src/Mobs/Zombie.h delete mode 100644 src/Mobs/ZombiePigman.cpp delete mode 100644 src/Mobs/ZombiePigman.h diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp deleted file mode 100644 index 5f5b1853d..000000000 --- a/src/Mobs/AggressiveMonster.cpp +++ /dev/null @@ -1,124 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "AggressiveMonster.h" - -#include "../World.h" -#include "../Entities/Player.h" -#include "../Tracer.h" - - - - - -cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eType 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_EMPersonality = AGGRESSIVE; -} - - - - - -// What to do if in Chasing State -void cAggressiveMonster::InStateChasing(float a_Dt) -{ - super::InStateChasing(a_Dt); - - if (m_Target != NULL) - { - if (m_Target->IsPlayer()) - { - if (((cPlayer *)m_Target)->IsGameModeCreative()) - { - m_EMState = IDLE; - return; - } - } - - if (!IsMovingToTargetPosition()) - { - MoveToPosition(m_Target->GetPosition()); - } - } -} - - - - - -void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity) -{ - if (!((cPlayer *)a_Entity)->IsGameModeCreative()) - { - super::EventSeePlayer(a_Entity); - m_EMState = CHASING; - } -} - - - - - -void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - if (m_EMState == CHASING) - { - CheckEventLostPlayer(); - } - else - { - CheckEventSeePlayer(); - } - - if (m_Target == NULL) - return; - - cTracer LineOfSight(GetWorld()); - Vector3d AttackDirection(m_Target->GetPosition() - GetPosition()); - - if (ReachedFinalDestination() && !LineOfSight.Trace(GetPosition(), AttackDirection, (int)AttackDirection.Length())) - { - // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls) - Attack(a_Dt / 1000); - } -} - - - - - -void cAggressiveMonster::Attack(float a_Dt) -{ - m_AttackInterval += a_Dt * m_AttackRate; - - if ((m_Target == NULL) || (m_AttackInterval < 3.0)) - { - return; - } - - // Setting this higher gives us more wiggle room for attackrate - m_AttackInterval = 0.0; - m_Target->TakeDamage(dtMobAttack, this, m_AttackDamage, 0); -} - - - - -bool cAggressiveMonster::IsMovingToTargetPosition() -{ - // Difference between destination x and target x is negligible (to 10^-12 precision) - if (fabsf((float)m_FinalDestination.x - (float)m_Target->GetPosX()) < std::numeric_limits::epsilon()) - { - return false; - } - // Difference between destination z and target z is negligible (to 10^-12 precision) - else if (fabsf((float)m_FinalDestination.z - (float)m_Target->GetPosZ()) > std::numeric_limits::epsilon()) - { - return false; - } - return true; -} diff --git a/src/Mobs/AggressiveMonster.h b/src/Mobs/AggressiveMonster.h deleted file mode 100644 index d70ff04a3..000000000 --- a/src/Mobs/AggressiveMonster.h +++ /dev/null @@ -1,33 +0,0 @@ - -#pragma once - -#include "Monster.h" - - - - - -class cAggressiveMonster : - public cMonster -{ - typedef cMonster super; - -public: - - cAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); - - virtual void Tick (float a_Dt, cChunk & a_Chunk) override; - virtual void InStateChasing(float a_Dt) override; - - virtual void EventSeePlayer(cEntity *) override; - virtual void Attack(float a_Dt); - -protected: - /** Whether this mob's destination is the same as its target's position. */ - bool IsMovingToTargetPosition(); - -} ; - - - - diff --git a/src/Mobs/Bat.cpp b/src/Mobs/Bat.cpp deleted file mode 100644 index c072d4f48..000000000 --- a/src/Mobs/Bat.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Bat.h" -#include "../Vector3.h" -#include "../Chunk.h" - - -cBat::cBat(void) : - super("Bat", mtBat, "mob.bat.hurt", "mob.bat.death", 0.5, 0.9) -{ -} - - diff --git a/src/Mobs/Bat.h b/src/Mobs/Bat.h deleted file mode 100644 index 6b06aeb4f..000000000 --- a/src/Mobs/Bat.h +++ /dev/null @@ -1,25 +0,0 @@ - -#pragma once - -#include "PassiveMonster.h" - - - - - -class cBat : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - cBat(void); - - CLASS_PROTODEF(cBat) - - bool IsHanging(void) const {return false; } -} ; - - - - diff --git a/src/Mobs/Blaze.cpp b/src/Mobs/Blaze.cpp deleted file mode 100644 index b4104d530..000000000 --- a/src/Mobs/Blaze.cpp +++ /dev/null @@ -1,57 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Blaze.h" -#include "../World.h" -#include "../Entities/FireChargeEntity.h" - - - - -cBlaze::cBlaze(void) : - super("Blaze", mtBlaze, "mob.blaze.hit", "mob.blaze.death", 0.6, 1.8) -{ -} - - - - - -void cBlaze::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - if ((a_Killer != NULL) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) - { - int LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_BLAZE_ROD); - } -} - - - - - -void cBlaze::Attack(float a_Dt) -{ - m_AttackInterval += a_Dt * m_AttackRate; - - if (m_Target != NULL && m_AttackInterval > 3.0) - { - // Setting this higher gives us more wiggle room for attackrate - Vector3d Speed = GetLookVector() * 20; - Speed.y = Speed.y + 1; - cFireChargeEntity * FireCharge = new cFireChargeEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); - if (FireCharge == NULL) - { - return; - } - if (!FireCharge->Initialize(*m_World)) - { - delete FireCharge; - FireCharge = NULL; - return; - } - m_World->BroadcastSpawnEntity(*FireCharge); - m_AttackInterval = 0.0; - // ToDo: Shoot 3 fireballs instead of 1. - } -} diff --git a/src/Mobs/Blaze.h b/src/Mobs/Blaze.h deleted file mode 100644 index f283b1070..000000000 --- a/src/Mobs/Blaze.h +++ /dev/null @@ -1,22 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cBlaze : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cBlaze(void); - - CLASS_PROTODEF(cBlaze) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void Attack(float a_Dt) override; -} ; diff --git a/src/Mobs/CaveSpider.cpp b/src/Mobs/CaveSpider.cpp deleted file mode 100644 index 118a6e93b..000000000 --- a/src/Mobs/CaveSpider.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "CaveSpider.h" -#include "../World.h" - - - - - -cCaveSpider::cCaveSpider(void) : - super("CaveSpider", mtCaveSpider, "mob.spider.say", "mob.spider.death", 0.7, 0.5) -{ -} - - - - - -void cCaveSpider::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - m_EMPersonality = (GetWorld()->GetTimeOfDay() < (12000 + 1000)) ? PASSIVE : AGGRESSIVE; -} - - - - - -void cCaveSpider::Attack(float a_Dt) -{ - super::Attack(a_Dt); - - if (m_Target->IsPawn()) - { - // TODO: Easy = no poison, Medium = 7 seconds, Hard = 15 seconds - ((cPawn *) m_Target)->AddEntityEffect(cEntityEffect::effPoison, 7 * 20, 0); - } -} - - - - - -void cCaveSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STRING); - if ((a_Killer != NULL) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) - { - AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_SPIDER_EYE); - } -} - - - - diff --git a/src/Mobs/CaveSpider.h b/src/Mobs/CaveSpider.h deleted file mode 100644 index f9ed10e1b..000000000 --- a/src/Mobs/CaveSpider.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cCaveSpider : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cCaveSpider(void); - - CLASS_PROTODEF(cCaveSpider) - - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - virtual void Attack(float a_Dt) override; - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; -} ; - - - - diff --git a/src/Mobs/Chicken.cpp b/src/Mobs/Chicken.cpp deleted file mode 100644 index f7e44238f..000000000 --- a/src/Mobs/Chicken.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Chicken.h" -#include "../World.h" - - - - - - - -cChicken::cChicken(void) : - super("Chicken", mtChicken, "mob.chicken.hurt", "mob.chicken.hurt", 0.3, 0.4), - m_EggDropTimer(0) -{ -} - - - - -void cChicken::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - if ((m_EggDropTimer == 6000) && (m_World->GetTickRandomNumber(1) == 0)) - { - 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++; - } -} - - - - - -void cChicken::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - 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); -} - - - - - - - - diff --git a/src/Mobs/Chicken.h b/src/Mobs/Chicken.h deleted file mode 100644 index b1a50b61c..000000000 --- a/src/Mobs/Chicken.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "PassiveMonster.h" - - - - - -class cChicken : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - cChicken(void); - - CLASS_PROTODEF(cChicken) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - - virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_SEEDS); } - -private: - - int m_EggDropTimer; -} ; - - - diff --git a/src/Mobs/Cow.cpp b/src/Mobs/Cow.cpp deleted file mode 100644 index 9914df6b5..000000000 --- a/src/Mobs/Cow.cpp +++ /dev/null @@ -1,48 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Cow.h" -#include "../Entities/Player.h" - - - - - - - -cCow::cCow(void) : - super("Cow", mtCow, "mob.cow.hurt", "mob.cow.hurt", 0.9, 1.3) -{ -} - - - - - -void cCow::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - 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); -} - - - - - -void cCow::OnRightClicked(cPlayer & a_Player) -{ - if ((a_Player.GetEquippedItem().m_ItemType == 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 deleted file mode 100644 index 8814b7e09..000000000 --- a/src/Mobs/Cow.h +++ /dev/null @@ -1,29 +0,0 @@ - -#pragma once - -#include "PassiveMonster.h" - - - - - -class cCow : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - cCow(); - - CLASS_PROTODEF(cCow) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void OnRightClicked(cPlayer & a_Player) override; - - virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); } - -} ; - - - - diff --git a/src/Mobs/Creeper.cpp b/src/Mobs/Creeper.cpp deleted file mode 100644 index 02718edf8..000000000 --- a/src/Mobs/Creeper.cpp +++ /dev/null @@ -1,152 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Creeper.h" -#include "../World.h" -#include "../Entities/ProjectileEntity.h" -#include "../Entities/Player.h" - - - - - -cCreeper::cCreeper(void) : - super("Creeper", mtCreeper, "mob.creeper.say", "mob.creeper.say", 0.6, 1.8), - m_bIsBlowing(false), - m_bIsCharged(false), - m_BurnedWithFlintAndSteel(false), - m_ExplodingTimer(0) -{ -} - - - - - -void cCreeper::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - if (!ReachedFinalDestination() && !m_BurnedWithFlintAndSteel) - { - m_ExplodingTimer = 0; - m_bIsBlowing = false; - m_World->BroadcastEntityMetadata(*this); - } - else - { - if (m_bIsBlowing) - { - m_ExplodingTimer += 1; - } - - if (m_ExplodingTimer == 30) - { - m_World->DoExplosionAt((m_bIsCharged ? 5 : 3), GetPosX(), GetPosY(), GetPosZ(), false, esMonster, this); - Destroy(); // Just in case we aren't killed by the explosion - } - } -} - - - - - -void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - if (m_ExplodingTimer == 30) - { - // Exploded creepers drop naught but charred flesh, which Minecraft doesn't have - return; - } - - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER); - - if ((a_Killer != NULL) && a_Killer->IsProjectile() && (((cProjectileEntity *)a_Killer)->GetCreatorUniqueID() >= 0)) - { - class cProjectileCreatorCallback : public cEntityCallback - { - public: - cProjectileCreatorCallback(void) - { - } - - virtual bool Item(cEntity * a_Entity) override - { - if (a_Entity->IsMob() && ((cMonster *)a_Entity)->GetMobType() == mtSkeleton) - { - return true; - } - return false; - } - }; - - cProjectileCreatorCallback PCC; - if (GetWorld()->DoWithEntityByID(((cProjectileEntity *)a_Killer)->GetCreatorUniqueID(), PCC)) - { - // 12 music discs. TickRand starts from 0 to 11. Disk IDs start at 2256, so add that. There. - AddRandomDropItem(a_Drops, 1, 1, (short)m_World->GetTickRandomNumber(11) + 2256); - } - } -} - - - - - -bool cCreeper::DoTakeDamage(TakeDamageInfo & a_TDI) -{ - if (!super::DoTakeDamage(a_TDI)) - { - return false; - } - - if (a_TDI.DamageType == dtLightning) - { - m_bIsCharged = true; - } - - m_World->BroadcastEntityMetadata(*this); - return true; -} - - - - - -void cCreeper::Attack(float a_Dt) -{ - UNUSED(a_Dt); - - if (!m_bIsBlowing) - { - m_World->BroadcastSoundEffect("game.tnt.primed", GetPosX(), GetPosY(), GetPosZ(), 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); - m_bIsBlowing = true; - m_World->BroadcastEntityMetadata(*this); - } -} - - - - - -void cCreeper::OnRightClicked(cPlayer & a_Player) -{ - if ((a_Player.GetEquippedItem().m_ItemType == E_ITEM_FLINT_AND_STEEL)) - { - if (!a_Player.IsGameModeCreative()) - { - a_Player.UseEquippedItem(); - } - m_World->BroadcastSoundEffect("game.tnt.primed", GetPosX(), GetPosY(), GetPosZ(), 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); - m_bIsBlowing = true; - m_World->BroadcastEntityMetadata(*this); - m_BurnedWithFlintAndSteel = true; - } -} - diff --git a/src/Mobs/Creeper.h b/src/Mobs/Creeper.h deleted file mode 100644 index 747daca09..000000000 --- a/src/Mobs/Creeper.h +++ /dev/null @@ -1,38 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cCreeper : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cCreeper(void); - - CLASS_PROTODEF(cCreeper) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; - virtual void Attack(float a_Dt) override; - virtual void Tick(float 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; } - -private: - - bool m_bIsBlowing, m_bIsCharged, m_BurnedWithFlintAndSteel; - int m_ExplodingTimer; - -} ; - - - - diff --git a/src/Mobs/EnderDragon.cpp b/src/Mobs/EnderDragon.cpp deleted file mode 100644 index acd81cde1..000000000 --- a/src/Mobs/EnderDragon.cpp +++ /dev/null @@ -1,27 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "EnderDragon.h" - - - - - -cEnderDragon::cEnderDragon(void) : - // TODO: Vanilla source says this, but is it right? Dragons fly, they don't stand - super("EnderDragon", mtEnderDragon, "mob.enderdragon.hit", "mob.enderdragon.end", 16.0, 8.0) -{ -} - - - - - -void cEnderDragon::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - return; -} - - - - diff --git a/src/Mobs/EnderDragon.h b/src/Mobs/EnderDragon.h deleted file mode 100644 index 1d4cd657c..000000000 --- a/src/Mobs/EnderDragon.h +++ /dev/null @@ -1,25 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cEnderDragon : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cEnderDragon(void); - - CLASS_PROTODEF(cEnderDragon) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; -} ; - - - - diff --git a/src/Mobs/Enderman.cpp b/src/Mobs/Enderman.cpp deleted file mode 100644 index 51255beb3..000000000 --- a/src/Mobs/Enderman.cpp +++ /dev/null @@ -1,183 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Enderman.h" -#include "../Entities/Player.h" -#include "../Tracer.h" - - - - -//////////////////////////////////////////////////////////////////////////////// -// cPlayerLookCheck -class cPlayerLookCheck : - public cPlayerListCallback -{ -public: - cPlayerLookCheck(Vector3d a_EndermanPos, int a_SightDistance) : - m_Player(NULL), - m_EndermanPos(a_EndermanPos), - m_SightDistance(a_SightDistance) - { - } - - virtual bool Item(cPlayer * a_Player) override - { - // Don't check players who are in creative gamemode - if (a_Player->IsGameModeCreative()) - { - return false; - } - - Vector3d Direction = m_EndermanPos - a_Player->GetPosition(); - - // Don't check players who are more then SightDistance (64) blocks away - if (Direction.Length() > m_SightDistance) - { - return false; - } - - // Don't check if the player has a pumpkin on his head - if (a_Player->GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN) - { - return false; - } - - - Vector3d LookVector = a_Player->GetLookVector(); - double dot = Direction.Dot(LookVector); - - // 0.09 rad ~ 5 degrees - // If the player's crosshair is within 5 degrees of the enderman, it counts as looking - if (dot <= cos(0.09)) - { - return false; - } - - cTracer LineOfSight(a_Player->GetWorld()); - if (LineOfSight.Trace(m_EndermanPos, Direction, (int)Direction.Length())) - { - // No direct line of sight - return false; - } - - m_Player = a_Player; - return true; - } - - cPlayer * GetPlayer(void) const { return m_Player; } - -protected: - cPlayer * m_Player; - Vector3d m_EndermanPos; - int m_SightDistance; -} ; - - - - - -cEnderman::cEnderman(void) : - super("Enderman", mtEnderman, "mob.endermen.hit", "mob.endermen.death", 0.5, 2.9), - m_bIsScreaming(false), - CarriedBlock(E_BLOCK_AIR), - CarriedMeta(0) -{ -} - - - - - -void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_ENDER_PEARL); -} - - - - -void cEnderman::CheckEventSeePlayer() -{ - if (m_Target != NULL) - { - return; - } - - cPlayerLookCheck Callback(GetPosition(), m_SightDistance); - if (m_World->ForEachPlayer(Callback)) - { - return; - } - - ASSERT(Callback.GetPlayer() != NULL); - - if (!CheckLight()) - { - // Insufficient light for enderman to become aggravated - // TODO: Teleport to a suitable location - return; - } - - if (!Callback.GetPlayer()->IsGameModeCreative()) - { - super::EventSeePlayer(Callback.GetPlayer()); - m_EMState = CHASING; - m_bIsScreaming = true; - GetWorld()->BroadcastEntityMetadata(*this); - } -} - - - - - -void cEnderman::CheckEventLostPlayer(void) -{ - super::CheckEventLostPlayer(); - if (!CheckLight()) - { - EventLosePlayer(); - } -} - - - - - -void cEnderman::EventLosePlayer() -{ - super::EventLosePlayer(); - m_bIsScreaming = false; - GetWorld()->BroadcastEntityMetadata(*this); -} - - - - - -bool cEnderman::CheckLight() -{ - int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(POSX_TOINT, POSZ_TOINT, ChunkX, ChunkZ); - - // Check if the chunk the enderman is in is lit - if (!m_World->IsChunkLighted(ChunkX, ChunkZ)) - { - m_World->QueueLightChunk(ChunkX, ChunkZ); - return true; - } - - // Enderman only attack if the skylight is lower or equal to 8 - if (m_World->GetBlockSkyLight(POSX_TOINT, POSY_TOINT, POSZ_TOINT) - GetWorld()->GetSkyDarkness() > 8) - { - return false; - } - - return true; -} diff --git a/src/Mobs/Enderman.h b/src/Mobs/Enderman.h deleted file mode 100644 index 4583746e7..000000000 --- a/src/Mobs/Enderman.h +++ /dev/null @@ -1,42 +0,0 @@ - -#pragma once - -#include "PassiveAggressiveMonster.h" - - - - - -class cEnderman : - public cPassiveAggressiveMonster -{ - typedef cPassiveAggressiveMonster super; - -public: - cEnderman(void); - - CLASS_PROTODEF(cEnderman) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void CheckEventSeePlayer(void) override; - virtual void CheckEventLostPlayer(void) override; - virtual void EventLosePlayer(void) override; - - bool IsScreaming(void) const {return m_bIsScreaming; } - BLOCKTYPE GetCarriedBlock(void) const {return CarriedBlock; } - NIBBLETYPE GetCarriedMeta(void) const {return CarriedMeta; } - - /** Returns if the current sky light level is sufficient for the enderman to become aggravated */ - bool CheckLight(void); - -private: - - bool m_bIsScreaming; - BLOCKTYPE CarriedBlock; - NIBBLETYPE CarriedMeta; - -} ; - - - - diff --git a/src/Mobs/Ghast.cpp b/src/Mobs/Ghast.cpp deleted file mode 100644 index 6aac14779..000000000 --- a/src/Mobs/Ghast.cpp +++ /dev/null @@ -1,61 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Ghast.h" -#include "../World.h" -#include "../Entities/GhastFireballEntity.h" - - - - -cGhast::cGhast(void) : - super("Ghast", mtGhast, "mob.ghast.scream", "mob.ghast.death", 4, 4) -{ -} - - - - - -void cGhast::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - 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); -} - - - - - -void cGhast::Attack(float a_Dt) -{ - m_AttackInterval += a_Dt * m_AttackRate; - - if (m_Target != NULL && m_AttackInterval > 3.0) - { - // Setting this higher gives us more wiggle room for attackrate - Vector3d Speed = GetLookVector() * 20; - Speed.y = Speed.y + 1; - cGhastFireballEntity * GhastBall = new cGhastFireballEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); - if (GhastBall == NULL) - { - return; - } - if (!GhastBall->Initialize(*m_World)) - { - delete GhastBall; - GhastBall = NULL; - return; - } - m_World->BroadcastSpawnEntity(*GhastBall); - m_AttackInterval = 0.0; - } -} - - - diff --git a/src/Mobs/Ghast.h b/src/Mobs/Ghast.h deleted file mode 100644 index 1d4e6b94a..000000000 --- a/src/Mobs/Ghast.h +++ /dev/null @@ -1,28 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cGhast : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cGhast(void); - - CLASS_PROTODEF(cGhast) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void Attack(float a_Dt) override; - - bool IsCharging(void) const {return false; } -} ; - - - - diff --git a/src/Mobs/Giant.cpp b/src/Mobs/Giant.cpp deleted file mode 100644 index bbcad46f0..000000000 --- a/src/Mobs/Giant.cpp +++ /dev/null @@ -1,27 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Giant.h" - - - - - -cGiant::cGiant(void) : - super("Giant", mtGiant, "mob.zombie.hurt", "mob.zombie.death", 3.6, 10.8) -{ - -} - - - - - -void cGiant::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - AddRandomDropItem(a_Drops, 10, 50, E_ITEM_ROTTEN_FLESH); -} - - - - diff --git a/src/Mobs/Giant.h b/src/Mobs/Giant.h deleted file mode 100644 index 7c04c9b4f..000000000 --- a/src/Mobs/Giant.h +++ /dev/null @@ -1,25 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cGiant : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cGiant(void); - - CLASS_PROTODEF(cGiant) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; -} ; - - - - diff --git a/src/Mobs/Horse.cpp b/src/Mobs/Horse.cpp deleted file mode 100644 index 67a09d4ab..000000000 --- a/src/Mobs/Horse.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Horse.h" -#include "../World.h" -#include "../Entities/Player.h" - - - - - -cHorse::cHorse(int Type, int Color, int Style, int TameTimes) : - super("Horse", mtHorse, "mob.horse.hit", "mob.horse.death", 1.4, 1.6), - m_bHasChest(false), - m_bIsEating(false), - m_bIsRearing(false), - m_bIsMouthOpen(false), - m_bIsTame(false), - m_bIsSaddled(false), - m_Type(Type), - m_Color(Color), - m_Style(Style), - m_Armour(0), - m_TimesToTame(TameTimes), - m_TameAttemptTimes(0), - m_RearTickCount(0) -{ -} - - - - - -void cHorse::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - if (!m_bIsMouthOpen) - { - if (m_World->GetTickRandomNumber(50) == 25) - { - m_bIsMouthOpen = true; - } - } - else - { - if (m_World->GetTickRandomNumber(10) == 5) - { - m_bIsMouthOpen = false; - } - } - - if ((m_Attachee != NULL) && (!m_bIsTame)) - { - if (m_TameAttemptTimes < m_TimesToTame) - { - if (m_World->GetTickRandomNumber(50) == 25) - { - m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 0); - m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 2); - m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 6); - m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 8); - - m_Attachee->Detach(); - m_bIsRearing = true; - } - } - else - { - m_bIsTame = true; - } - } - - if (m_bIsRearing) - { - if (m_RearTickCount == 20) - { - m_bIsRearing = false; - m_RearTickCount = 0; - } - else - { - m_RearTickCount++; - } - } - - m_World->BroadcastEntityMetadata(*this); -} - - - - - -void cHorse::OnRightClicked(cPlayer & a_Player) -{ - if (!m_bIsSaddled && m_bIsTame) - { - if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_SADDLE) - { - // Saddle the horse: - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - } - m_bIsSaddled = true; - m_World->BroadcastEntityMetadata(*this); - } - else if (!a_Player.GetEquippedItem().IsEmpty()) - { - // The horse doesn't like being hit, make it rear: - m_bIsRearing = true; - m_RearTickCount = 0; - } - } - else - { - if (m_Attachee != NULL) - { - if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) - { - a_Player.Detach(); - return; - } - - if (m_Attachee->IsPlayer()) - { - return; - } - - m_Attachee->Detach(); - } - - m_TameAttemptTimes++; - a_Player.AttachTo(this); - } -} - - - - - -void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER); - if (m_bIsSaddled) - { - a_Drops.push_back(cItem(E_ITEM_SADDLE, 1)); - } -} - - - - diff --git a/src/Mobs/Horse.h b/src/Mobs/Horse.h deleted file mode 100644 index 47189b3b0..000000000 --- a/src/Mobs/Horse.h +++ /dev/null @@ -1,44 +0,0 @@ - -#pragma once - -#include "PassiveMonster.h" - - - - - -class cHorse : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - cHorse(int Type, int Color, int Style, int TameTimes); - - CLASS_PROTODEF(cHorse) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - virtual void OnRightClicked(cPlayer & a_Player) override; - - bool IsSaddled (void) const {return m_bIsSaddled; } - bool IsChested (void) const {return m_bHasChest; } - bool IsEating (void) const {return m_bIsEating; } - bool IsRearing (void) const {return m_bIsRearing; } - bool IsMthOpen (void) const {return m_bIsMouthOpen; } - bool IsTame (void) const {return m_bIsTame; } - int GetHorseType (void) const {return m_Type; } - int GetHorseColor (void) const {return m_Color; } - int GetHorseStyle (void) const {return m_Style; } - int GetHorseArmour (void) const {return m_Armour;} - -private: - - bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame, m_bIsSaddled; - int m_Type, m_Color, m_Style, m_Armour, m_TimesToTame, m_TameAttemptTimes, m_RearTickCount; - -} ; - - - - diff --git a/src/Mobs/IronGolem.cpp b/src/Mobs/IronGolem.cpp deleted file mode 100644 index dae4615e4..000000000 --- a/src/Mobs/IronGolem.cpp +++ /dev/null @@ -1,28 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "IronGolem.h" - - - - - -cIronGolem::cIronGolem(void) : - super("IronGolem", mtIronGolem, "mob.IronGolem.hit", "mob.IronGolem.death", 1.4, 2.9) -{ -} - - - - - -void cIronGolem::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - UNUSED(a_Killer); - AddRandomDropItem(a_Drops, 0, 5, E_ITEM_IRON); - AddRandomDropItem(a_Drops, 0, 2, E_BLOCK_FLOWER); -} - - - - diff --git a/src/Mobs/IronGolem.h b/src/Mobs/IronGolem.h deleted file mode 100644 index c5341ed76..000000000 --- a/src/Mobs/IronGolem.h +++ /dev/null @@ -1,29 +0,0 @@ - -#pragma once - -#include "PassiveAggressiveMonster.h" - - - - - -class cIronGolem : - public cPassiveAggressiveMonster -{ - typedef cPassiveAggressiveMonster super; - -public: - cIronGolem(void); - - CLASS_PROTODEF(cIronGolem) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - - // Iron golems do not drown nor float - virtual void HandleAir(void) override {} - virtual void SetSwimState(cChunk & a_Chunk) override {} -} ; - - - - diff --git a/src/Mobs/MagmaCube.cpp b/src/Mobs/MagmaCube.cpp deleted file mode 100644 index 3e9abc108..000000000 --- a/src/Mobs/MagmaCube.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "MagmaCube.h" - - - - - -cMagmaCube::cMagmaCube(int a_Size) : - super("MagmaCube", mtMagmaCube, "mob.MagmaCube.big", "mob.MagmaCube.big", 0.6 * a_Size, 0.6 * a_Size), - m_Size(a_Size) -{ -} - - - - - -void cMagmaCube::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - UNUSED(a_Killer); - if (GetSize() > 1) - { - AddRandomUncommonDropItem(a_Drops, 25.0f, E_ITEM_MAGMA_CREAM); - } -} - - - - diff --git a/src/Mobs/MagmaCube.h b/src/Mobs/MagmaCube.h deleted file mode 100644 index bfe63fa2e..000000000 --- a/src/Mobs/MagmaCube.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cMagmaCube : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - /// Creates a MagmaCube of the specified size; size is 1 .. 3, with 1 being the smallest - cMagmaCube(int a_Size); - - CLASS_PROTODEF(cMagmaCube) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - int GetSize(void) const { return m_Size; } - -protected: - - /// Size of the MagmaCube, 1 .. 3, with 1 being the smallest - int m_Size; -} ; - - - - diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp deleted file mode 100644 index fe8a7346f..000000000 --- a/src/Mobs/Monster.cpp +++ /dev/null @@ -1,1045 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "IncludeAllMonsters.h" -#include "../Root.h" -#include "../Server.h" -#include "../ClientHandle.h" -#include "../World.h" -#include "../Entities/Player.h" -#include "../Entities/ExpOrb.h" -#include "../MonsterConfig.h" -#include "../MersenneTwister.h" - -#include "../Chunk.h" -#include "../FastRandom.h" - - - - - -/** Map for eType <-> string -Needs to be alpha-sorted by the strings, because binary search is used in StringToMobType() -The strings need to be lowercase (for more efficient comparisons in StringToMobType()) -*/ -static const struct -{ - cMonster::eType m_Type; - const char * m_lcName; -} g_MobTypeNames[] = -{ - {cMonster::mtBat, "bat"}, - {cMonster::mtBlaze, "blaze"}, - {cMonster::mtCaveSpider, "cavespider"}, - {cMonster::mtChicken, "chicken"}, - {cMonster::mtCow, "cow"}, - {cMonster::mtCreeper, "creeper"}, - {cMonster::mtEnderman, "enderman"}, - {cMonster::mtEnderDragon, "enderdragon"}, - {cMonster::mtGhast, "ghast"}, - {cMonster::mtHorse, "horse"}, - {cMonster::mtIronGolem, "irongolem"}, - {cMonster::mtMagmaCube, "magmacube"}, - {cMonster::mtMooshroom, "mooshroom"}, - {cMonster::mtOcelot, "ocelot"}, - {cMonster::mtPig, "pig"}, - {cMonster::mtSheep, "sheep"}, - {cMonster::mtSilverfish, "silverfish"}, - {cMonster::mtSkeleton, "skeleton"}, - {cMonster::mtSlime, "slime"}, - {cMonster::mtSnowGolem, "snowgolem"}, - {cMonster::mtSpider, "spider"}, - {cMonster::mtSquid, "squid"}, - {cMonster::mtVillager, "villager"}, - {cMonster::mtWitch, "witch"}, - {cMonster::mtWither, "wither"}, - {cMonster::mtWolf, "wolf"}, - {cMonster::mtZombie, "zombie"}, - {cMonster::mtZombiePigman, "zombiepigman"}, -} ; - - - - - -//////////////////////////////////////////////////////////////////////////////// -// cMonster: - -cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) - : super(etMonster, a_Width, a_Height) - , m_EMState(IDLE) - , m_EMPersonality(AGGRESSIVE) - , m_Target(NULL) - , m_bMovingToDestination(false) - , m_LastGroundHeight(POSY_TOINT) - , m_IdleInterval(0) - , m_DestroyTimer(0) - , m_MobType(a_MobType) - , m_SoundHurt(a_SoundHurt) - , m_SoundDeath(a_SoundDeath) - , m_AttackRate(3) - , m_AttackDamage(1) - , m_AttackRange(2) - , m_AttackInterval(0) - , m_SightDistance(25) - , m_DropChanceWeapon(0.085f) - , m_DropChanceHelmet(0.085f) - , m_DropChanceChestplate(0.085f) - , m_DropChanceLeggings(0.085f) - , m_DropChanceBoots(0.085f) - , m_CanPickUpLoot(true) - , m_BurnsInDaylight(false) -{ - if (!a_ConfigName.empty()) - { - GetMonsterConfig(a_ConfigName); - } -} - - - - - -void cMonster::SpawnOn(cClientHandle & a_Client) -{ - a_Client.SendSpawnMob(*this); -} - - - - - -void cMonster::TickPathFinding() -{ - const int PosX = POSX_TOINT; - const int PosY = POSY_TOINT; - const int PosZ = POSZ_TOINT; - - std::vector m_PotentialCoordinates; - m_TraversedCoordinates.push_back(Vector3i(PosX, PosY, PosZ)); - - static const struct // Define which directions to try to move to - { - int x, z; - } gCrossCoords[] = - { - { 1, 0}, - {-1, 0}, - { 0, 1}, - { 0, -1}, - } ; - - if ((PosY - 1 < 0) || (PosY + 2 > cChunkDef::Height) /* PosY + 1 will never be true if PosY + 2 is not */) - { - // Too low/high, can't really do anything - FinishPathFinding(); - return; - } - - for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) - { - if (IsCoordinateInTraversedList(Vector3i(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ))) - { - continue; - } - - BLOCKTYPE BlockAtY = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ); - BLOCKTYPE BlockAtYP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 1, gCrossCoords[i].z + PosZ); - BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ); - int LowestY = FindFirstNonAirBlockPosition(gCrossCoords[i].x + PosX, gCrossCoords[i].z + PosZ); - BLOCKTYPE BlockAtLowestY = m_World->GetBlock(gCrossCoords[i].x + PosX, LowestY, gCrossCoords[i].z + PosZ); - - if ( - (!cBlockInfo::IsSolid(BlockAtY)) && - (!cBlockInfo::IsSolid(BlockAtYP)) && - (!IsBlockLava(BlockAtLowestY)) && - (BlockAtLowestY != E_BLOCK_CACTUS) && - (PosY - LowestY < FALL_DAMAGE_HEIGHT) - ) - { - m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY, gCrossCoords[i].z + PosZ)); - } - else if ( - (cBlockInfo::IsSolid(BlockAtY)) && - (BlockAtY != E_BLOCK_CACTUS) && - (!cBlockInfo::IsSolid(BlockAtYP)) && - (!cBlockInfo::IsSolid(BlockAtYPP)) && - (BlockAtY != E_BLOCK_FENCE) && - (BlockAtY != E_BLOCK_FENCE_GATE) - ) - { - m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY + 1, gCrossCoords[i].z + PosZ)); - } - } - - if (!m_PotentialCoordinates.empty()) - { - Vector3f ShortestCoords = m_PotentialCoordinates.front(); - for (std::vector::const_iterator itr = m_PotentialCoordinates.begin(); itr != m_PotentialCoordinates.end(); ++itr) - { - Vector3f Distance = m_FinalDestination - ShortestCoords; - Vector3f Distance2 = m_FinalDestination - *itr; - if (Distance.SqrLength() > Distance2.SqrLength()) - { - ShortestCoords = *itr; - } - } - - m_Destination = ShortestCoords; - m_Destination.z += 0.5f; - m_Destination.x += 0.5f; - } - else - { - FinishPathFinding(); - } -} - - - - - -void cMonster::MoveToPosition(const Vector3d & a_Position) -{ - FinishPathFinding(); - - m_FinalDestination = a_Position; - m_bMovingToDestination = true; - TickPathFinding(); -} - - - -bool cMonster::IsCoordinateInTraversedList(Vector3i a_Coords) -{ - return (std::find(m_TraversedCoordinates.begin(), m_TraversedCoordinates.end(), a_Coords) != m_TraversedCoordinates.end()); -} - - - - - -bool cMonster::ReachedDestination() -{ - if ((m_Destination - GetPosition()).Length() < 0.5f) - { - return true; - } - - return false; -} - - - - -bool cMonster::ReachedFinalDestination() -{ - if ((GetPosition() - m_FinalDestination).Length() <= m_AttackRange) - { - return true; - } - - return false; -} - - - - - -void cMonster::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - if (m_Health <= 0) - { - // The mob is dead, but we're still animating the "puff" they leave when they die - m_DestroyTimer += a_Dt / 1000; - if (m_DestroyTimer > 1) - { - Destroy(true); - } - return; - } - - if ((m_Target != NULL) && m_Target->IsDestroyed()) - m_Target = NULL; - - // Burning in daylight - HandleDaylightBurning(a_Chunk); - - a_Dt /= 1000; - - if (m_bMovingToDestination) - { - if (m_bOnGround) - { - if (DoesPosYRequireJump((int)floor(m_Destination.y))) - { - m_bOnGround = false; - - // TODO: Change to AddSpeedY once collision detection is fixed - currently, mobs will go into blocks attempting to jump without a teleport - AddPosY(1.2); // Jump!! - } - } - - Vector3f Distance = m_Destination - GetPosition(); - if (!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move - { - Distance.y = 0; - Distance.Normalize(); - - if (m_bOnGround) - { - Distance *= 2.5f; - } - else if (IsSwimming()) - { - Distance *= 1.3f; - } - else - { - // Don't let the mob move too much if he's falling. - Distance *= 0.25f; - } - - AddSpeedX(Distance.x); - AddSpeedZ(Distance.z); - - // It's too buggy! - /* - if (m_EMState == ESCAPING) - { - // Runs Faster when escaping :D otherwise they just walk away - SetSpeedX (GetSpeedX() * 2.f); - SetSpeedZ (GetSpeedZ() * 2.f); - } - */ - } - else - { - if (ReachedFinalDestination()) // If we have reached the ultimate, final destination, stop pathfinding and attack if appropriate - { - FinishPathFinding(); - } - else - { - TickPathFinding(); // We have reached the next point in our path, calculate another point - } - } - } - - SetPitchAndYawFromDestination(); - HandleFalling(); - - switch (m_EMState) - { - case IDLE: - { - // If enemy passive we ignore checks for player visibility - InStateIdle(a_Dt); - break; - } - case CHASING: - { - // If we do not see a player anymore skip chasing action - InStateChasing(a_Dt); - break; - } - case ESCAPING: - { - InStateEscaping(a_Dt); - break; - } - - case ATTACKING: break; - } // switch (m_EMState) - - BroadcastMovementUpdate(); -} - - - - -void cMonster::SetPitchAndYawFromDestination() -{ - Vector3d FinalDestination = m_FinalDestination; - if (m_Target != NULL) - { - if (m_Target->IsPlayer()) - { - FinalDestination.y = ((cPlayer *)m_Target)->GetStance(); - } - else - { - FinalDestination.y = GetHeight(); - } - } - - Vector3d Distance = FinalDestination - GetPosition(); - if (Distance.SqrLength() > 0.1f) - { - { - double Rotation, Pitch; - Distance.Normalize(); - VectorToEuler(Distance.x, Distance.y, Distance.z, Rotation, Pitch); - SetHeadYaw(Rotation); - SetPitch(-Pitch); - } - - { - Vector3d BodyDistance = m_Destination - GetPosition(); - double Rotation, Pitch; - Distance.Normalize(); - VectorToEuler(BodyDistance.x, BodyDistance.y, BodyDistance.z, Rotation, Pitch); - SetYaw(Rotation); - } - } -} - - - - -void cMonster::HandleFalling() -{ - if (m_bOnGround) - { - int Damage = (m_LastGroundHeight - POSY_TOINT) - 3; - - if (Damage > 0) - { - TakeDamage(dtFalling, NULL, Damage, Damage, 0); - - // Fall particles - GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, POSY_TOINT - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */); - } - - m_LastGroundHeight = POSY_TOINT; - } -} - - - - - -int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ) -{ - int PosY = POSY_TOINT; - PosY = Clamp(PosY, 0, cChunkDef::Height); - - if (!cBlockInfo::IsSolid(m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ)))) - { - while (!cBlockInfo::IsSolid(m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))) && (PosY > 0)) - { - PosY--; - } - - return PosY + 1; - } - else - { - while (cBlockInfo::IsSolid(m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))) && (PosY < cChunkDef::Height)) - { - PosY++; - } - - return PosY; - } -} - - - - - - -bool cMonster::DoTakeDamage(TakeDamageInfo & a_TDI) -{ - if (!super::DoTakeDamage(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 != NULL) - { - m_Target = a_TDI.Attacker; - } - return true; -} - - - - - -void cMonster::KilledBy(TakeDamageInfo & a_TDI) -{ - super::KilledBy(a_TDI); - if (m_SoundHurt != "") - { - m_World->BroadcastSoundEffect(m_SoundDeath, GetPosX(), GetPosY(), GetPosZ(), 1.0f, 0.8f); - } - int Reward; - switch (m_MobType) - { - // Animals - case cMonster::mtChicken: - case cMonster::mtCow: - case cMonster::mtHorse: - case cMonster::mtPig: - case cMonster::mtSheep: - case cMonster::mtSquid: - case cMonster::mtMooshroom: - case cMonster::mtOcelot: - case cMonster::mtWolf: - { - Reward = m_World->GetTickRandomNumber(2) + 1; - break; - } - - // Monsters - case cMonster::mtCaveSpider: - case cMonster::mtCreeper: - case cMonster::mtEnderman: - case cMonster::mtGhast: - case cMonster::mtSilverfish: - case cMonster::mtSkeleton: - case cMonster::mtSpider: - case cMonster::mtWitch: - case cMonster::mtZombie: - case cMonster::mtZombiePigman: - case cMonster::mtSlime: - case cMonster::mtMagmaCube: - { - Reward = 6 + (m_World->GetTickRandomNumber(2)); - break; - } - case cMonster::mtBlaze: - { - Reward = 10; - break; - } - - // Bosses - case cMonster::mtEnderDragon: - { - Reward = 12000; - break; - } - case cMonster::mtWither: - { - Reward = 50; - break; - } - - default: - { - Reward = 0; - break; - } - } - if ((a_TDI.Attacker != NULL) && (!IsBaby())) - { - m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), Reward); - } - m_DestroyTimer = 0; -} - - - - - -// Checks to see if EventSeePlayer should be fired -// monster sez: Do I see the player -void cMonster::CheckEventSeePlayer(void) -{ - // TODO: Rewrite this to use cWorld's DoWithPlayers() - cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance, false); - - if (Closest != NULL) - { - EventSeePlayer(Closest); - } -} - - - - - -void cMonster::CheckEventLostPlayer(void) -{ - if (m_Target != NULL) - { - if ((m_Target->GetPosition() - GetPosition()).Length() > m_SightDistance) - { - EventLosePlayer(); - } - } - else - { - EventLosePlayer(); - } -} - - - - - -// What to do if player is seen -// default to change state to chasing -void cMonster::EventSeePlayer(cEntity * a_SeenPlayer) -{ - m_Target = a_SeenPlayer; -} - - - - - -void cMonster::EventLosePlayer(void) -{ - m_Target = NULL; - m_EMState = IDLE; -} - - - - - -void cMonster::InStateIdle(float a_Dt) -{ - if (m_bMovingToDestination) - { - return; // Still getting there - } - - m_IdleInterval += a_Dt; - - if (m_IdleInterval > 1) - { - // At this interval the results are predictable - int rem = m_World->GetTickRandomNumber(6) + 1; - m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds - - Vector3d Dist; - Dist.x = (double)m_World->GetTickRandomNumber(10) - 5; - Dist.z = (double)m_World->GetTickRandomNumber(10) - 5; - - if ((Dist.SqrLength() > 2) && (rem >= 3)) - { - Vector3d Destination(GetPosX() + Dist.x, 0, GetPosZ() + Dist.z); - - int NextHeight = FindFirstNonAirBlockPosition(Destination.x, Destination.z); - - if (IsNextYPosReachable(NextHeight)) - { - Destination.y = NextHeight; - MoveToPosition(Destination); - } - } - } -} - - - - - -// What to do if in Chasing State -// This state should always be defined in each child class -void cMonster::InStateChasing(float a_Dt) -{ - UNUSED(a_Dt); -} - - - - - -// What to do if in Escaping State -void cMonster::InStateEscaping(float a_Dt) -{ - UNUSED(a_Dt); - - if (m_Target != NULL) - { - Vector3d newloc = GetPosition(); - newloc.x = (m_Target->GetPosition().x < newloc.x)? (newloc.x + m_SightDistance): (newloc.x - m_SightDistance); - newloc.z = (m_Target->GetPosition().z < newloc.z)? (newloc.z + m_SightDistance): (newloc.z - m_SightDistance); - MoveToPosition(newloc); - } - else - { - m_EMState = IDLE; // This shouldnt be required but just to be safe - } -} - - - - - -void cMonster::GetMonsterConfig(const AString & a_Name) -{ - cRoot::Get()->GetMonsterConfig()->AssignAttributes(this, a_Name); -} - - - - - -bool cMonster::IsUndead(void) -{ - return false; -} - - - - - -AString cMonster::MobTypeToString(cMonster::eType a_MobType) -{ - // Mob types aren't sorted, so we need to search linearly: - for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) - { - if (g_MobTypeNames[i].m_Type == a_MobType) - { - return g_MobTypeNames[i].m_lcName; - } - } - - // Not found: - return ""; -} - - - - - -cMonster::eType cMonster::StringToMobType(const AString & a_Name) -{ - AString lcName = StrToLower(a_Name); - - // Binary-search for the lowercase name: - int lo = 0, hi = ARRAYCOUNT(g_MobTypeNames) - 1; - while (hi - lo > 1) - { - int mid = (lo + hi) / 2; - int res = strcmp(g_MobTypeNames[mid].m_lcName, lcName.c_str()); - if (res == 0) - { - return g_MobTypeNames[mid].m_Type; - } - if (res < 0) - { - lo = mid; - } - else - { - hi = mid; - } - } - // Range has collapsed to at most two elements, compare each: - if (strcmp(g_MobTypeNames[lo].m_lcName, lcName.c_str()) == 0) - { - return g_MobTypeNames[lo].m_Type; - } - if ((lo != hi) && (strcmp(g_MobTypeNames[hi].m_lcName, lcName.c_str()) == 0)) - { - return g_MobTypeNames[hi].m_Type; - } - - // Not found: - return mtInvalidType; -} - - - - - -cMonster::eFamily cMonster::FamilyFromType(eType a_Type) -{ - // Passive-agressive mobs are counted in mob spawning code as passive - - switch (a_Type) - { - case mtBat: return mfAmbient; - case mtBlaze: return mfHostile; - case mtCaveSpider: return mfHostile; - case mtChicken: return mfPassive; - case mtCow: return mfPassive; - case mtCreeper: return mfHostile; - case mtEnderDragon: return mfNoSpawn; - case mtEnderman: return mfHostile; - case mtGhast: return mfHostile; - case mtGiant: return mfNoSpawn; - case mtHorse: return mfPassive; - case mtIronGolem: return mfPassive; - case mtMagmaCube: return mfHostile; - case mtMooshroom: return mfHostile; - case mtOcelot: return mfPassive; - case mtPig: return mfPassive; - case mtSheep: return mfPassive; - case mtSilverfish: return mfHostile; - case mtSkeleton: return mfHostile; - case mtSlime: return mfHostile; - case mtSnowGolem: return mfNoSpawn; - case mtSpider: return mfHostile; - case mtSquid: return mfWater; - case mtVillager: return mfPassive; - case mtWitch: return mfHostile; - case mtWither: return mfNoSpawn; - case mtWolf: return mfHostile; - case mtZombie: return mfHostile; - case mtZombiePigman: return mfHostile; - - case mtInvalidType: break; - } - ASSERT(!"Unhandled mob type"); - return mfUnhandled; -} - - - - - -int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily) -{ - switch (a_MobFamily) - { - case mfHostile: return 40; - case mfPassive: return 40; - case mfAmbient: return 40; - case mfWater: return 400; - case mfNoSpawn: return -1; - case mfUnhandled: break; - } - ASSERT(!"Unhandled mob family"); - return -1; -} - - - - - -cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType) -{ - cFastRandom Random; - cMonster * toReturn = NULL; - - // Create the mob entity - switch (a_MobType) - { - case mtMagmaCube: - { - toReturn = new cMagmaCube(Random.NextInt(2) + 1); - break; - } - case mtSlime: - { - toReturn = new cSlime(1 << Random.NextInt(3)); // Size 1, 2 or 4 - break; - } - case mtSkeleton: - { - // TODO: Actual detection of spawning in Nether - toReturn = new cSkeleton((Random.NextInt(1) == 0) ? false : true); - break; - } - case mtVillager: - { - int VillagerType = Random.NextInt(6); - if (VillagerType == 6) - { - // Give farmers a better chance of spawning - VillagerType = 0; - } - - toReturn = new cVillager((cVillager::eVillagerType)VillagerType); - break; - } - case mtHorse: - { - // Horses take a type (species), a colour, and a style (dots, stripes, etc.) - int HorseType = Random.NextInt(7); - int HorseColor = Random.NextInt(6); - int HorseStyle = Random.NextInt(6); - int HorseTameTimes = Random.NextInt(6) + 1; - - if ((HorseType == 5) || (HorseType == 6) || (HorseType == 7)) - { - // Increase chances of normal horse (zero) - HorseType = 0; - } - - toReturn = new cHorse(HorseType, HorseColor, HorseStyle, HorseTameTimes); - break; - } - - case mtBat: toReturn = new cBat(); break; - case mtBlaze: toReturn = new cBlaze(); break; - case mtCaveSpider: toReturn = new cCaveSpider(); break; - case mtChicken: toReturn = new cChicken(); break; - case mtCow: toReturn = new cCow(); break; - case mtCreeper: toReturn = new cCreeper(); break; - case mtEnderDragon: toReturn = new cEnderDragon(); break; - case mtEnderman: toReturn = new cEnderman(); break; - case mtGhast: toReturn = new cGhast(); break; - case mtGiant: toReturn = new cGiant(); break; - case mtIronGolem: toReturn = new cIronGolem(); break; - case mtMooshroom: toReturn = new cMooshroom(); break; - case mtOcelot: toReturn = new cOcelot(); break; - case mtPig: toReturn = new cPig(); break; - case mtSheep: toReturn = new cSheep(); break; - case mtSilverfish: toReturn = new cSilverfish(); break; - case mtSnowGolem: toReturn = new cSnowGolem(); break; - case mtSpider: toReturn = new cSpider(); break; - case mtSquid: toReturn = new cSquid(); break; - case mtWitch: toReturn = new cWitch(); break; - case mtWither: toReturn = new cWither(); break; - case mtWolf: toReturn = new cWolf(); break; - case mtZombie: toReturn = new cZombie(false); break; // TODO: Infected zombie parameter - case mtZombiePigman: toReturn = new cZombiePigman(); break; - default: - { - ASSERT(!"Unhandled mob type whilst trying to spawn mob!"); - } - } - return toReturn; -} - - - - - -void cMonster::AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth) -{ - MTRand r1; - int Count = r1.randInt() % (a_Max + 1 - a_Min) + a_Min; - if (Count > 0) - { - a_Drops.push_back(cItem(a_Item, Count, a_ItemHealth)); - } -} - - - - - -void cMonster::AddRandomUncommonDropItem(cItems & a_Drops, float a_Chance, short a_Item, short a_ItemHealth) -{ - MTRand r1; - int Count = r1.randInt() % 1000; - if (Count < (a_Chance * 10)) - { - a_Drops.push_back(cItem(a_Item, 1, a_ItemHealth)); - } -} - - - - - -void cMonster::AddRandomRareDropItem(cItems & a_Drops, cItems & a_Items, short a_LootingLevel) -{ - MTRand r1; - int Count = r1.randInt() % 200; - if (Count < (5 + a_LootingLevel)) - { - int Rare = r1.randInt() % a_Items.Size(); - a_Drops.push_back(a_Items.at(Rare)); - } -} - - - - - -void cMonster::AddRandomArmorDropItem(cItems & a_Drops, short a_LootingLevel) -{ - MTRand r1; - if (r1.randInt() % 200 < ((m_DropChanceHelmet * 200) + (a_LootingLevel * 2))) - { - if (!GetEquippedHelmet().IsEmpty()) a_Drops.push_back(GetEquippedHelmet()); - } - - if (r1.randInt() % 200 < ((m_DropChanceChestplate * 200) + (a_LootingLevel * 2))) - { - if (!GetEquippedChestplate().IsEmpty()) a_Drops.push_back(GetEquippedChestplate()); - } - - if (r1.randInt() % 200 < ((m_DropChanceLeggings * 200) + (a_LootingLevel * 2))) - { - if (!GetEquippedLeggings().IsEmpty()) a_Drops.push_back(GetEquippedLeggings()); - } - - if (r1.randInt() % 200 < ((m_DropChanceBoots * 200) + (a_LootingLevel * 2))) - { - if (!GetEquippedBoots().IsEmpty()) a_Drops.push_back(GetEquippedBoots()); - } -} - - - - - -void cMonster::AddRandomWeaponDropItem(cItems & a_Drops, short a_LootingLevel) -{ - MTRand r1; - if (r1.randInt() % 200 < ((m_DropChanceWeapon * 200) + (a_LootingLevel * 2))) - { - if (!GetEquippedWeapon().IsEmpty()) a_Drops.push_back(GetEquippedWeapon()); - } -} - - - - - -void cMonster::HandleDaylightBurning(cChunk & a_Chunk) -{ - if (!m_BurnsInDaylight) - { - return; - } - - int RelY = POSY_TOINT; - if ((RelY < 0) || (RelY >= cChunkDef::Height)) - { - // Outside the world - return; - } - - int RelX = POSX_TOINT - GetChunkX() * cChunkDef::Width; - int RelZ = POSZ_TOINT - GetChunkZ() * cChunkDef::Width; - - if (!a_Chunk.IsLightValid()) - { - m_World->QueueLightChunk(GetChunkX(), GetChunkZ()); - return; - } - - if ( - (a_Chunk.GetSkyLight(RelX, RelY, RelZ) == 15) && // In the daylight - (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand - (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime - !IsOnFire() && // Not already burning - GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT) // Not raining - ) - { - // Burn for 100 ticks, then decide again - StartBurning(100); - } -} - - - - -cMonster::eFamily cMonster::GetMobFamily(void) const -{ - return FamilyFromType(m_MobType); -} - - - - diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h deleted file mode 100644 index cdbd26c09..000000000 --- a/src/Mobs/Monster.h +++ /dev/null @@ -1,271 +0,0 @@ - -#pragma once - -#include "../Entities/Pawn.h" -#include "../Defines.h" -#include "../BlockID.h" -#include "../Item.h" -#include "../Enchantments.h" - - - - - -class cClientHandle; -class cWorld; - - - - -// tolua_begin -class cMonster : - public cPawn -{ - typedef cPawn super; -public: - /// This identifies individual monster type, as well as their network type-ID - enum eType - { - mtInvalidType = -1, - - mtBat = E_META_SPAWN_EGG_BAT, - mtBlaze = E_META_SPAWN_EGG_BLAZE, - mtCaveSpider = E_META_SPAWN_EGG_CAVE_SPIDER, - mtChicken = E_META_SPAWN_EGG_CHICKEN, - mtCow = E_META_SPAWN_EGG_COW, - mtCreeper = E_META_SPAWN_EGG_CREEPER, - mtEnderDragon = E_META_SPAWN_EGG_ENDER_DRAGON, - mtEnderman = E_META_SPAWN_EGG_ENDERMAN, - mtGhast = E_META_SPAWN_EGG_GHAST, - mtGiant = E_META_SPAWN_EGG_GIANT, - mtHorse = E_META_SPAWN_EGG_HORSE, - mtIronGolem = E_META_SPAWN_EGG_IRON_GOLEM, - mtMagmaCube = E_META_SPAWN_EGG_MAGMA_CUBE, - mtMooshroom = E_META_SPAWN_EGG_MOOSHROOM, - mtOcelot = E_META_SPAWN_EGG_OCELOT, - mtPig = E_META_SPAWN_EGG_PIG, - mtSheep = E_META_SPAWN_EGG_SHEEP, - mtSilverfish = E_META_SPAWN_EGG_SILVERFISH, - mtSkeleton = E_META_SPAWN_EGG_SKELETON, - mtSlime = E_META_SPAWN_EGG_SLIME, - mtSnowGolem = E_META_SPAWN_EGG_SNOW_GOLEM, - mtSpider = E_META_SPAWN_EGG_SPIDER, - mtSquid = E_META_SPAWN_EGG_SQUID, - mtVillager = E_META_SPAWN_EGG_VILLAGER, - mtWitch = E_META_SPAWN_EGG_WITCH, - mtWither = E_META_SPAWN_EGG_WITHER, - mtWolf = E_META_SPAWN_EGG_WOLF, - mtZombie = E_META_SPAWN_EGG_ZOMBIE, - mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN, - } ; - - enum eFamily - { - mfHostile = 0, // Spider, Zombies ... - mfPassive = 1, // Cows, Pigs - mfAmbient = 2, // Bats - mfWater = 3, // Squid - - mfNoSpawn, - mfUnhandled, // Nothing. Be sure this is the last and the others are in order - } ; - - // tolua_end - - enum MState{ATTACKING, IDLE, CHASING, ESCAPING} m_EMState; - enum MPersonality{PASSIVE, AGGRESSIVE, COWARDLY} m_EMPersonality; - - /** Creates the mob object. - If a_ConfigName is not empty, the configuration is loaded using GetMonsterConfig() - a_MobType is the type of the mob (also used in the protocol ( http://wiki.vg/Entities#Mobs 2012_12_22)) - a_SoundHurt and a_SoundDeath are assigned into m_SoundHurt and m_SoundDeath, respectively - */ - cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); - - CLASS_PROTODEF(cMonster) - - virtual void SpawnOn(cClientHandle & a_ClientHandle) override; - - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - - virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; - - virtual void KilledBy(TakeDamageInfo & a_TDI) override; - - virtual void MoveToPosition(const Vector3d & a_Position); // tolua_export - virtual bool ReachedDestination(void); - - // tolua_begin - eType GetMobType(void) const {return m_MobType; } - eFamily GetMobFamily(void) const; - // tolua_end - - virtual void CheckEventSeePlayer(void); - virtual void EventSeePlayer(cEntity * a_Player); - - /// Reads the monster configuration for the specified monster name and assigns it to this object. - void GetMonsterConfig(const AString & a_Name); - - /** Returns whether this mob is undead (skeleton, zombie, etc.) */ - virtual bool IsUndead(void); - - virtual void EventLosePlayer(void); - virtual void CheckEventLostPlayer(void); - - virtual void InStateIdle (float a_Dt); - virtual void InStateChasing (float a_Dt); - virtual void InStateEscaping(float a_Dt); - - int GetAttackRate() { return (int)m_AttackRate; } - void SetAttackRate(float a_AttackRate) { m_AttackRate = a_AttackRate; } - void SetAttackRange(int a_AttackRange) { m_AttackRange = a_AttackRange; } - void SetAttackDamage(int a_AttackDamage) { m_AttackDamage = a_AttackDamage; } - void SetSightDistance(int a_SightDistance) { m_SightDistance = a_SightDistance; } - - float GetDropChanceWeapon() { return m_DropChanceWeapon; } - float GetDropChanceHelmet() { return m_DropChanceHelmet; } - float GetDropChanceChestplate() { return m_DropChanceChestplate; } - float GetDropChanceLeggings() { return m_DropChanceLeggings; } - float GetDropChanceBoots() { return m_DropChanceBoots; } - bool CanPickUpLoot() { return m_CanPickUpLoot; } - void SetDropChanceWeapon(float a_DropChanceWeapon) { m_DropChanceWeapon = a_DropChanceWeapon; } - void SetDropChanceHelmet(float a_DropChanceHelmet) { m_DropChanceHelmet = a_DropChanceHelmet; } - void SetDropChanceChestplate(float a_DropChanceChestplate) { m_DropChanceChestplate = a_DropChanceChestplate; } - 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; } - - /// Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick - void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; } - - // Overridables to handle ageable mobs - virtual bool IsBaby (void) const { return false; } - virtual bool IsTame (void) const { return false; } - virtual bool IsSitting (void) const { return false; } - - // tolua_begin - - /// Translates MobType enum to a string, empty string if unknown - static AString MobTypeToString(eType a_MobType); - - /// Translates MobType string to the enum, mtInvalidType if not recognized - static eType StringToMobType(const AString & a_MobTypeName); - - /// Returns the mob family based on the type - static eFamily FamilyFromType(eType a_MobType); - - /// Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family - static int GetSpawnDelay(cMonster::eFamily a_MobFamily); - - // tolua_end - - /** Creates a new object of the specified mob. - a_MobType is the type of the mob to be created - Asserts and returns null if mob type is not specified - */ - static cMonster * NewMonsterFromType(eType a_MobType); - -protected: - - /* ======= PATHFINDING ======= */ - - /** A pointer to the entity this mobile is aiming to reach */ - cEntity * m_Target; - /** Coordinates of the next position that should be reached */ - Vector3d m_Destination; - /** Coordinates for the ultimate, final destination. */ - Vector3d m_FinalDestination; - /** Returns if the ultimate, final destination has been reached */ - bool ReachedFinalDestination(void); - - /** Stores if mobile is currently moving towards the ultimate, final destination */ - bool m_bMovingToDestination; - - /** Finds the first non-air block position (not the highest, as cWorld::GetHeight does) - If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1 - If current Y is solid, goes up to find first nonsolid block, and returns that */ - int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ); - /** Returns if a monster can actually reach a given height by jumping or walking */ - inline bool IsNextYPosReachable(int a_PosY) - { - return ( - (a_PosY <= POSY_TOINT) || - DoesPosYRequireJump(a_PosY) - ); - } - /** Returns if a monster can reach a given height by jumping */ - inline bool DoesPosYRequireJump(int a_PosY) - { - return ((a_PosY > POSY_TOINT) && (a_PosY == POSY_TOINT + 1)); - } - - /** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */ - std::vector m_TraversedCoordinates; - /** Returns if coordinate is in the traversed list */ - bool IsCoordinateInTraversedList(Vector3i a_Coords); - - /** Finds the next place to go - This is based on the ultimate, final destination and the current position, as well as the traversed coordinates, and any environmental hazards */ - void TickPathFinding(void); - /** Finishes a pathfinding task, be it due to failure or something else */ - inline void FinishPathFinding(void) - { - m_TraversedCoordinates.clear(); - m_bMovingToDestination = false; - } - /** Sets the body yaw and head yaw/pitch based on next/ultimate destinations */ - void SetPitchAndYawFromDestination(void); - - /* =========================== */ - /* ========= FALLING ========= */ - - virtual void HandleFalling(void); - int m_LastGroundHeight; - - /* =========================== */ - - float m_IdleInterval; - float m_DestroyTimer; - - eType m_MobType; - - AString m_SoundHurt; - AString m_SoundDeath; - - float m_AttackRate; - int m_AttackDamage; - int m_AttackRange; - float m_AttackInterval; - int m_SightDistance; - - float m_DropChanceWeapon; - float m_DropChanceHelmet; - float m_DropChanceChestplate; - float m_DropChanceLeggings; - float m_DropChanceBoots; - bool m_CanPickUpLoot; - - void HandleDaylightBurning(cChunk & a_Chunk); - bool m_BurnsInDaylight; - - /** Adds a random number of a_Item between a_Min and a_Max to itemdrops a_Drops*/ - void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0); - - /** Adds a item a_Item with the chance of a_Chance (in percent) to itemdrops a_Drops*/ - void AddRandomUncommonDropItem(cItems & a_Drops, float a_Chance, short a_Item, short a_ItemHealth = 0); - - /** Adds one rare item out of the list of rare items a_Items modified by the looting level a_LootingLevel(I-III or custom) to the itemdrop a_Drops*/ - void AddRandomRareDropItem(cItems & a_Drops, cItems & a_Items, short a_LootingLevel); - - /** Adds armor that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if piccked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop*/ - void AddRandomArmorDropItem(cItems & a_Drops, short a_LootingLevel); - - /** Adds weapon that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if piccked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop*/ - void AddRandomWeaponDropItem(cItems & a_Drops, short a_LootingLevel); - - -} ; // tolua_export - - - - diff --git a/src/Mobs/Mooshroom.cpp b/src/Mobs/Mooshroom.cpp deleted file mode 100644 index 81bd3e3b4..000000000 --- a/src/Mobs/Mooshroom.cpp +++ /dev/null @@ -1,75 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Mooshroom.h" -#include "../Entities/Player.h" - - - - - - - - - - -cMooshroom::cMooshroom(void) : - super("Mooshroom", mtMooshroom, "mob.cow.hurt", "mob.cow.hurt", 0.9, 1.3) -{ -} - - - - - -void cMooshroom::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - 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); -} - - - - - -void cMooshroom::OnRightClicked(cPlayer & a_Player) -{ - switch (a_Player.GetEquippedItem().m_ItemType) - { - case E_ITEM_BUCKET: - { - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - a_Player.GetInventory().AddItem(E_ITEM_MILK); - } - } break; - case E_ITEM_BOWL: - { - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - a_Player.GetInventory().AddItem(E_ITEM_MUSHROOM_SOUP); - } - } break; - case E_ITEM_SHEARS: - { - if (!a_Player.IsGameModeCreative()) - { - a_Player.UseEquippedItem(); - } - - cItems Drops; - Drops.push_back(cItem(E_BLOCK_RED_MUSHROOM, 5, 0)); - m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); - m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), cMonster::mtCow); - Destroy(); - } break; - } -} - diff --git a/src/Mobs/Mooshroom.h b/src/Mobs/Mooshroom.h deleted file mode 100644 index fb002c2bf..000000000 --- a/src/Mobs/Mooshroom.h +++ /dev/null @@ -1,28 +0,0 @@ - -#pragma once - -#include "PassiveMonster.h" - - - - - -class cMooshroom : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - cMooshroom(void); - - CLASS_PROTODEF(cMooshroom) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void OnRightClicked(cPlayer & a_Player) override; - - virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); } -} ; - - - - diff --git a/src/Mobs/Ocelot.h b/src/Mobs/Ocelot.h deleted file mode 100644 index f2727d354..000000000 --- a/src/Mobs/Ocelot.h +++ /dev/null @@ -1,26 +0,0 @@ - -#pragma once - -#include "PassiveMonster.h" - - - - - -class cOcelot : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - cOcelot(void) : - super("Ocelot", mtOcelot, "mob.cat.hitt", "mob.cat.hitt", 0.6, 0.8) - { - } - - CLASS_PROTODEF(cOcelot) -} ; - - - - diff --git a/src/Mobs/Old Mobs/AggressiveMonster.cpp b/src/Mobs/Old Mobs/AggressiveMonster.cpp new file mode 100644 index 000000000..5f5b1853d --- /dev/null +++ b/src/Mobs/Old Mobs/AggressiveMonster.cpp @@ -0,0 +1,124 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "AggressiveMonster.h" + +#include "../World.h" +#include "../Entities/Player.h" +#include "../Tracer.h" + + + + + +cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eType 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_EMPersonality = AGGRESSIVE; +} + + + + + +// What to do if in Chasing State +void cAggressiveMonster::InStateChasing(float a_Dt) +{ + super::InStateChasing(a_Dt); + + if (m_Target != NULL) + { + if (m_Target->IsPlayer()) + { + if (((cPlayer *)m_Target)->IsGameModeCreative()) + { + m_EMState = IDLE; + return; + } + } + + if (!IsMovingToTargetPosition()) + { + MoveToPosition(m_Target->GetPosition()); + } + } +} + + + + + +void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity) +{ + if (!((cPlayer *)a_Entity)->IsGameModeCreative()) + { + super::EventSeePlayer(a_Entity); + m_EMState = CHASING; + } +} + + + + + +void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if (m_EMState == CHASING) + { + CheckEventLostPlayer(); + } + else + { + CheckEventSeePlayer(); + } + + if (m_Target == NULL) + return; + + cTracer LineOfSight(GetWorld()); + Vector3d AttackDirection(m_Target->GetPosition() - GetPosition()); + + if (ReachedFinalDestination() && !LineOfSight.Trace(GetPosition(), AttackDirection, (int)AttackDirection.Length())) + { + // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls) + Attack(a_Dt / 1000); + } +} + + + + + +void cAggressiveMonster::Attack(float a_Dt) +{ + m_AttackInterval += a_Dt * m_AttackRate; + + if ((m_Target == NULL) || (m_AttackInterval < 3.0)) + { + return; + } + + // Setting this higher gives us more wiggle room for attackrate + m_AttackInterval = 0.0; + m_Target->TakeDamage(dtMobAttack, this, m_AttackDamage, 0); +} + + + + +bool cAggressiveMonster::IsMovingToTargetPosition() +{ + // Difference between destination x and target x is negligible (to 10^-12 precision) + if (fabsf((float)m_FinalDestination.x - (float)m_Target->GetPosX()) < std::numeric_limits::epsilon()) + { + return false; + } + // Difference between destination z and target z is negligible (to 10^-12 precision) + else if (fabsf((float)m_FinalDestination.z - (float)m_Target->GetPosZ()) > std::numeric_limits::epsilon()) + { + return false; + } + return true; +} diff --git a/src/Mobs/Old Mobs/AggressiveMonster.h b/src/Mobs/Old Mobs/AggressiveMonster.h new file mode 100644 index 000000000..d70ff04a3 --- /dev/null +++ b/src/Mobs/Old Mobs/AggressiveMonster.h @@ -0,0 +1,33 @@ + +#pragma once + +#include "Monster.h" + + + + + +class cAggressiveMonster : + public cMonster +{ + typedef cMonster super; + +public: + + cAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + + virtual void Tick (float a_Dt, cChunk & a_Chunk) override; + virtual void InStateChasing(float a_Dt) override; + + virtual void EventSeePlayer(cEntity *) override; + virtual void Attack(float a_Dt); + +protected: + /** Whether this mob's destination is the same as its target's position. */ + bool IsMovingToTargetPosition(); + +} ; + + + + diff --git a/src/Mobs/Old Mobs/Bat.cpp b/src/Mobs/Old Mobs/Bat.cpp new file mode 100644 index 000000000..c072d4f48 --- /dev/null +++ b/src/Mobs/Old Mobs/Bat.cpp @@ -0,0 +1,14 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Bat.h" +#include "../Vector3.h" +#include "../Chunk.h" + + +cBat::cBat(void) : + super("Bat", mtBat, "mob.bat.hurt", "mob.bat.death", 0.5, 0.9) +{ +} + + diff --git a/src/Mobs/Old Mobs/Bat.h b/src/Mobs/Old Mobs/Bat.h new file mode 100644 index 000000000..6b06aeb4f --- /dev/null +++ b/src/Mobs/Old Mobs/Bat.h @@ -0,0 +1,25 @@ + +#pragma once + +#include "PassiveMonster.h" + + + + + +class cBat : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + cBat(void); + + CLASS_PROTODEF(cBat) + + bool IsHanging(void) const {return false; } +} ; + + + + diff --git a/src/Mobs/Old Mobs/Blaze.cpp b/src/Mobs/Old Mobs/Blaze.cpp new file mode 100644 index 000000000..b4104d530 --- /dev/null +++ b/src/Mobs/Old Mobs/Blaze.cpp @@ -0,0 +1,57 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Blaze.h" +#include "../World.h" +#include "../Entities/FireChargeEntity.h" + + + + +cBlaze::cBlaze(void) : + super("Blaze", mtBlaze, "mob.blaze.hit", "mob.blaze.death", 0.6, 1.8) +{ +} + + + + + +void cBlaze::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + if ((a_Killer != NULL) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) + { + int LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_BLAZE_ROD); + } +} + + + + + +void cBlaze::Attack(float a_Dt) +{ + m_AttackInterval += a_Dt * m_AttackRate; + + if (m_Target != NULL && m_AttackInterval > 3.0) + { + // Setting this higher gives us more wiggle room for attackrate + Vector3d Speed = GetLookVector() * 20; + Speed.y = Speed.y + 1; + cFireChargeEntity * FireCharge = new cFireChargeEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); + if (FireCharge == NULL) + { + return; + } + if (!FireCharge->Initialize(*m_World)) + { + delete FireCharge; + FireCharge = NULL; + return; + } + m_World->BroadcastSpawnEntity(*FireCharge); + m_AttackInterval = 0.0; + // ToDo: Shoot 3 fireballs instead of 1. + } +} diff --git a/src/Mobs/Old Mobs/Blaze.h b/src/Mobs/Old Mobs/Blaze.h new file mode 100644 index 000000000..f283b1070 --- /dev/null +++ b/src/Mobs/Old Mobs/Blaze.h @@ -0,0 +1,22 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cBlaze : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cBlaze(void); + + CLASS_PROTODEF(cBlaze) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void Attack(float a_Dt) override; +} ; diff --git a/src/Mobs/Old Mobs/CaveSpider.cpp b/src/Mobs/Old Mobs/CaveSpider.cpp new file mode 100644 index 000000000..118a6e93b --- /dev/null +++ b/src/Mobs/Old Mobs/CaveSpider.cpp @@ -0,0 +1,61 @@ +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "CaveSpider.h" +#include "../World.h" + + + + + +cCaveSpider::cCaveSpider(void) : + super("CaveSpider", mtCaveSpider, "mob.spider.say", "mob.spider.death", 0.7, 0.5) +{ +} + + + + + +void cCaveSpider::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + m_EMPersonality = (GetWorld()->GetTimeOfDay() < (12000 + 1000)) ? PASSIVE : AGGRESSIVE; +} + + + + + +void cCaveSpider::Attack(float a_Dt) +{ + super::Attack(a_Dt); + + if (m_Target->IsPawn()) + { + // TODO: Easy = no poison, Medium = 7 seconds, Hard = 15 seconds + ((cPawn *) m_Target)->AddEntityEffect(cEntityEffect::effPoison, 7 * 20, 0); + } +} + + + + + +void cCaveSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STRING); + if ((a_Killer != NULL) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) + { + AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_SPIDER_EYE); + } +} + + + + diff --git a/src/Mobs/Old Mobs/CaveSpider.h b/src/Mobs/Old Mobs/CaveSpider.h new file mode 100644 index 000000000..f9ed10e1b --- /dev/null +++ b/src/Mobs/Old Mobs/CaveSpider.h @@ -0,0 +1,26 @@ +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cCaveSpider : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cCaveSpider(void); + + CLASS_PROTODEF(cCaveSpider) + + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + virtual void Attack(float a_Dt) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; +} ; + + + + diff --git a/src/Mobs/Old Mobs/Chicken.cpp b/src/Mobs/Old Mobs/Chicken.cpp new file mode 100644 index 000000000..f7e44238f --- /dev/null +++ b/src/Mobs/Old Mobs/Chicken.cpp @@ -0,0 +1,66 @@ +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Chicken.h" +#include "../World.h" + + + + + + + +cChicken::cChicken(void) : + super("Chicken", mtChicken, "mob.chicken.hurt", "mob.chicken.hurt", 0.3, 0.4), + m_EggDropTimer(0) +{ +} + + + + +void cChicken::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if ((m_EggDropTimer == 6000) && (m_World->GetTickRandomNumber(1) == 0)) + { + 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++; + } +} + + + + + +void cChicken::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + 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); +} + + + + + + + + diff --git a/src/Mobs/Old Mobs/Chicken.h b/src/Mobs/Old Mobs/Chicken.h new file mode 100644 index 000000000..b1a50b61c --- /dev/null +++ b/src/Mobs/Old Mobs/Chicken.h @@ -0,0 +1,30 @@ +#pragma once + +#include "PassiveMonster.h" + + + + + +class cChicken : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + cChicken(void); + + CLASS_PROTODEF(cChicken) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_SEEDS); } + +private: + + int m_EggDropTimer; +} ; + + + diff --git a/src/Mobs/Old Mobs/Cow.cpp b/src/Mobs/Old Mobs/Cow.cpp new file mode 100644 index 000000000..9914df6b5 --- /dev/null +++ b/src/Mobs/Old Mobs/Cow.cpp @@ -0,0 +1,48 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Cow.h" +#include "../Entities/Player.h" + + + + + + + +cCow::cCow(void) : + super("Cow", mtCow, "mob.cow.hurt", "mob.cow.hurt", 0.9, 1.3) +{ +} + + + + + +void cCow::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + 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); +} + + + + + +void cCow::OnRightClicked(cPlayer & a_Player) +{ + if ((a_Player.GetEquippedItem().m_ItemType == E_ITEM_BUCKET)) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + a_Player.GetInventory().AddItem(E_ITEM_MILK); + } + } +} + diff --git a/src/Mobs/Old Mobs/Cow.h b/src/Mobs/Old Mobs/Cow.h new file mode 100644 index 000000000..8814b7e09 --- /dev/null +++ b/src/Mobs/Old Mobs/Cow.h @@ -0,0 +1,29 @@ + +#pragma once + +#include "PassiveMonster.h" + + + + + +class cCow : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + cCow(); + + CLASS_PROTODEF(cCow) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); } + +} ; + + + + diff --git a/src/Mobs/Old Mobs/Creeper.cpp b/src/Mobs/Old Mobs/Creeper.cpp new file mode 100644 index 000000000..02718edf8 --- /dev/null +++ b/src/Mobs/Old Mobs/Creeper.cpp @@ -0,0 +1,152 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Creeper.h" +#include "../World.h" +#include "../Entities/ProjectileEntity.h" +#include "../Entities/Player.h" + + + + + +cCreeper::cCreeper(void) : + super("Creeper", mtCreeper, "mob.creeper.say", "mob.creeper.say", 0.6, 1.8), + m_bIsBlowing(false), + m_bIsCharged(false), + m_BurnedWithFlintAndSteel(false), + m_ExplodingTimer(0) +{ +} + + + + + +void cCreeper::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if (!ReachedFinalDestination() && !m_BurnedWithFlintAndSteel) + { + m_ExplodingTimer = 0; + m_bIsBlowing = false; + m_World->BroadcastEntityMetadata(*this); + } + else + { + if (m_bIsBlowing) + { + m_ExplodingTimer += 1; + } + + if (m_ExplodingTimer == 30) + { + m_World->DoExplosionAt((m_bIsCharged ? 5 : 3), GetPosX(), GetPosY(), GetPosZ(), false, esMonster, this); + Destroy(); // Just in case we aren't killed by the explosion + } + } +} + + + + + +void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + if (m_ExplodingTimer == 30) + { + // Exploded creepers drop naught but charred flesh, which Minecraft doesn't have + return; + } + + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER); + + if ((a_Killer != NULL) && a_Killer->IsProjectile() && (((cProjectileEntity *)a_Killer)->GetCreatorUniqueID() >= 0)) + { + class cProjectileCreatorCallback : public cEntityCallback + { + public: + cProjectileCreatorCallback(void) + { + } + + virtual bool Item(cEntity * a_Entity) override + { + if (a_Entity->IsMob() && ((cMonster *)a_Entity)->GetMobType() == mtSkeleton) + { + return true; + } + return false; + } + }; + + cProjectileCreatorCallback PCC; + if (GetWorld()->DoWithEntityByID(((cProjectileEntity *)a_Killer)->GetCreatorUniqueID(), PCC)) + { + // 12 music discs. TickRand starts from 0 to 11. Disk IDs start at 2256, so add that. There. + AddRandomDropItem(a_Drops, 1, 1, (short)m_World->GetTickRandomNumber(11) + 2256); + } + } +} + + + + + +bool cCreeper::DoTakeDamage(TakeDamageInfo & a_TDI) +{ + if (!super::DoTakeDamage(a_TDI)) + { + return false; + } + + if (a_TDI.DamageType == dtLightning) + { + m_bIsCharged = true; + } + + m_World->BroadcastEntityMetadata(*this); + return true; +} + + + + + +void cCreeper::Attack(float a_Dt) +{ + UNUSED(a_Dt); + + if (!m_bIsBlowing) + { + m_World->BroadcastSoundEffect("game.tnt.primed", GetPosX(), GetPosY(), GetPosZ(), 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); + m_bIsBlowing = true; + m_World->BroadcastEntityMetadata(*this); + } +} + + + + + +void cCreeper::OnRightClicked(cPlayer & a_Player) +{ + if ((a_Player.GetEquippedItem().m_ItemType == E_ITEM_FLINT_AND_STEEL)) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.UseEquippedItem(); + } + m_World->BroadcastSoundEffect("game.tnt.primed", GetPosX(), GetPosY(), GetPosZ(), 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); + m_bIsBlowing = true; + m_World->BroadcastEntityMetadata(*this); + m_BurnedWithFlintAndSteel = true; + } +} + diff --git a/src/Mobs/Old Mobs/Creeper.h b/src/Mobs/Old Mobs/Creeper.h new file mode 100644 index 000000000..747daca09 --- /dev/null +++ b/src/Mobs/Old Mobs/Creeper.h @@ -0,0 +1,38 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cCreeper : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cCreeper(void); + + CLASS_PROTODEF(cCreeper) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; + virtual void Attack(float a_Dt) override; + virtual void Tick(float 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; } + +private: + + bool m_bIsBlowing, m_bIsCharged, m_BurnedWithFlintAndSteel; + int m_ExplodingTimer; + +} ; + + + + diff --git a/src/Mobs/Old Mobs/EnderDragon.cpp b/src/Mobs/Old Mobs/EnderDragon.cpp new file mode 100644 index 000000000..acd81cde1 --- /dev/null +++ b/src/Mobs/Old Mobs/EnderDragon.cpp @@ -0,0 +1,27 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "EnderDragon.h" + + + + + +cEnderDragon::cEnderDragon(void) : + // TODO: Vanilla source says this, but is it right? Dragons fly, they don't stand + super("EnderDragon", mtEnderDragon, "mob.enderdragon.hit", "mob.enderdragon.end", 16.0, 8.0) +{ +} + + + + + +void cEnderDragon::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + return; +} + + + + diff --git a/src/Mobs/Old Mobs/EnderDragon.h b/src/Mobs/Old Mobs/EnderDragon.h new file mode 100644 index 000000000..1d4cd657c --- /dev/null +++ b/src/Mobs/Old Mobs/EnderDragon.h @@ -0,0 +1,25 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cEnderDragon : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cEnderDragon(void); + + CLASS_PROTODEF(cEnderDragon) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; +} ; + + + + diff --git a/src/Mobs/Old Mobs/Enderman.cpp b/src/Mobs/Old Mobs/Enderman.cpp new file mode 100644 index 000000000..51255beb3 --- /dev/null +++ b/src/Mobs/Old Mobs/Enderman.cpp @@ -0,0 +1,183 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Enderman.h" +#include "../Entities/Player.h" +#include "../Tracer.h" + + + + +//////////////////////////////////////////////////////////////////////////////// +// cPlayerLookCheck +class cPlayerLookCheck : + public cPlayerListCallback +{ +public: + cPlayerLookCheck(Vector3d a_EndermanPos, int a_SightDistance) : + m_Player(NULL), + m_EndermanPos(a_EndermanPos), + m_SightDistance(a_SightDistance) + { + } + + virtual bool Item(cPlayer * a_Player) override + { + // Don't check players who are in creative gamemode + if (a_Player->IsGameModeCreative()) + { + return false; + } + + Vector3d Direction = m_EndermanPos - a_Player->GetPosition(); + + // Don't check players who are more then SightDistance (64) blocks away + if (Direction.Length() > m_SightDistance) + { + return false; + } + + // Don't check if the player has a pumpkin on his head + if (a_Player->GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN) + { + return false; + } + + + Vector3d LookVector = a_Player->GetLookVector(); + double dot = Direction.Dot(LookVector); + + // 0.09 rad ~ 5 degrees + // If the player's crosshair is within 5 degrees of the enderman, it counts as looking + if (dot <= cos(0.09)) + { + return false; + } + + cTracer LineOfSight(a_Player->GetWorld()); + if (LineOfSight.Trace(m_EndermanPos, Direction, (int)Direction.Length())) + { + // No direct line of sight + return false; + } + + m_Player = a_Player; + return true; + } + + cPlayer * GetPlayer(void) const { return m_Player; } + +protected: + cPlayer * m_Player; + Vector3d m_EndermanPos; + int m_SightDistance; +} ; + + + + + +cEnderman::cEnderman(void) : + super("Enderman", mtEnderman, "mob.endermen.hit", "mob.endermen.death", 0.5, 2.9), + m_bIsScreaming(false), + CarriedBlock(E_BLOCK_AIR), + CarriedMeta(0) +{ +} + + + + + +void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_ENDER_PEARL); +} + + + + +void cEnderman::CheckEventSeePlayer() +{ + if (m_Target != NULL) + { + return; + } + + cPlayerLookCheck Callback(GetPosition(), m_SightDistance); + if (m_World->ForEachPlayer(Callback)) + { + return; + } + + ASSERT(Callback.GetPlayer() != NULL); + + if (!CheckLight()) + { + // Insufficient light for enderman to become aggravated + // TODO: Teleport to a suitable location + return; + } + + if (!Callback.GetPlayer()->IsGameModeCreative()) + { + super::EventSeePlayer(Callback.GetPlayer()); + m_EMState = CHASING; + m_bIsScreaming = true; + GetWorld()->BroadcastEntityMetadata(*this); + } +} + + + + + +void cEnderman::CheckEventLostPlayer(void) +{ + super::CheckEventLostPlayer(); + if (!CheckLight()) + { + EventLosePlayer(); + } +} + + + + + +void cEnderman::EventLosePlayer() +{ + super::EventLosePlayer(); + m_bIsScreaming = false; + GetWorld()->BroadcastEntityMetadata(*this); +} + + + + + +bool cEnderman::CheckLight() +{ + int ChunkX, ChunkZ; + cChunkDef::BlockToChunk(POSX_TOINT, POSZ_TOINT, ChunkX, ChunkZ); + + // Check if the chunk the enderman is in is lit + if (!m_World->IsChunkLighted(ChunkX, ChunkZ)) + { + m_World->QueueLightChunk(ChunkX, ChunkZ); + return true; + } + + // Enderman only attack if the skylight is lower or equal to 8 + if (m_World->GetBlockSkyLight(POSX_TOINT, POSY_TOINT, POSZ_TOINT) - GetWorld()->GetSkyDarkness() > 8) + { + return false; + } + + return true; +} diff --git a/src/Mobs/Old Mobs/Enderman.h b/src/Mobs/Old Mobs/Enderman.h new file mode 100644 index 000000000..4583746e7 --- /dev/null +++ b/src/Mobs/Old Mobs/Enderman.h @@ -0,0 +1,42 @@ + +#pragma once + +#include "PassiveAggressiveMonster.h" + + + + + +class cEnderman : + public cPassiveAggressiveMonster +{ + typedef cPassiveAggressiveMonster super; + +public: + cEnderman(void); + + CLASS_PROTODEF(cEnderman) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void CheckEventSeePlayer(void) override; + virtual void CheckEventLostPlayer(void) override; + virtual void EventLosePlayer(void) override; + + bool IsScreaming(void) const {return m_bIsScreaming; } + BLOCKTYPE GetCarriedBlock(void) const {return CarriedBlock; } + NIBBLETYPE GetCarriedMeta(void) const {return CarriedMeta; } + + /** Returns if the current sky light level is sufficient for the enderman to become aggravated */ + bool CheckLight(void); + +private: + + bool m_bIsScreaming; + BLOCKTYPE CarriedBlock; + NIBBLETYPE CarriedMeta; + +} ; + + + + diff --git a/src/Mobs/Old Mobs/Ghast.cpp b/src/Mobs/Old Mobs/Ghast.cpp new file mode 100644 index 000000000..6aac14779 --- /dev/null +++ b/src/Mobs/Old Mobs/Ghast.cpp @@ -0,0 +1,61 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Ghast.h" +#include "../World.h" +#include "../Entities/GhastFireballEntity.h" + + + + +cGhast::cGhast(void) : + super("Ghast", mtGhast, "mob.ghast.scream", "mob.ghast.death", 4, 4) +{ +} + + + + + +void cGhast::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + 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); +} + + + + + +void cGhast::Attack(float a_Dt) +{ + m_AttackInterval += a_Dt * m_AttackRate; + + if (m_Target != NULL && m_AttackInterval > 3.0) + { + // Setting this higher gives us more wiggle room for attackrate + Vector3d Speed = GetLookVector() * 20; + Speed.y = Speed.y + 1; + cGhastFireballEntity * GhastBall = new cGhastFireballEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); + if (GhastBall == NULL) + { + return; + } + if (!GhastBall->Initialize(*m_World)) + { + delete GhastBall; + GhastBall = NULL; + return; + } + m_World->BroadcastSpawnEntity(*GhastBall); + m_AttackInterval = 0.0; + } +} + + + diff --git a/src/Mobs/Old Mobs/Ghast.h b/src/Mobs/Old Mobs/Ghast.h new file mode 100644 index 000000000..1d4e6b94a --- /dev/null +++ b/src/Mobs/Old Mobs/Ghast.h @@ -0,0 +1,28 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cGhast : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cGhast(void); + + CLASS_PROTODEF(cGhast) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void Attack(float a_Dt) override; + + bool IsCharging(void) const {return false; } +} ; + + + + diff --git a/src/Mobs/Old Mobs/Giant.cpp b/src/Mobs/Old Mobs/Giant.cpp new file mode 100644 index 000000000..bbcad46f0 --- /dev/null +++ b/src/Mobs/Old Mobs/Giant.cpp @@ -0,0 +1,27 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Giant.h" + + + + + +cGiant::cGiant(void) : + super("Giant", mtGiant, "mob.zombie.hurt", "mob.zombie.death", 3.6, 10.8) +{ + +} + + + + + +void cGiant::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + AddRandomDropItem(a_Drops, 10, 50, E_ITEM_ROTTEN_FLESH); +} + + + + diff --git a/src/Mobs/Old Mobs/Giant.h b/src/Mobs/Old Mobs/Giant.h new file mode 100644 index 000000000..7c04c9b4f --- /dev/null +++ b/src/Mobs/Old Mobs/Giant.h @@ -0,0 +1,25 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cGiant : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cGiant(void); + + CLASS_PROTODEF(cGiant) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; +} ; + + + + diff --git a/src/Mobs/Old Mobs/Horse.cpp b/src/Mobs/Old Mobs/Horse.cpp new file mode 100644 index 000000000..67a09d4ab --- /dev/null +++ b/src/Mobs/Old Mobs/Horse.cpp @@ -0,0 +1,157 @@ +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Horse.h" +#include "../World.h" +#include "../Entities/Player.h" + + + + + +cHorse::cHorse(int Type, int Color, int Style, int TameTimes) : + super("Horse", mtHorse, "mob.horse.hit", "mob.horse.death", 1.4, 1.6), + m_bHasChest(false), + m_bIsEating(false), + m_bIsRearing(false), + m_bIsMouthOpen(false), + m_bIsTame(false), + m_bIsSaddled(false), + m_Type(Type), + m_Color(Color), + m_Style(Style), + m_Armour(0), + m_TimesToTame(TameTimes), + m_TameAttemptTimes(0), + m_RearTickCount(0) +{ +} + + + + + +void cHorse::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if (!m_bIsMouthOpen) + { + if (m_World->GetTickRandomNumber(50) == 25) + { + m_bIsMouthOpen = true; + } + } + else + { + if (m_World->GetTickRandomNumber(10) == 5) + { + m_bIsMouthOpen = false; + } + } + + if ((m_Attachee != NULL) && (!m_bIsTame)) + { + if (m_TameAttemptTimes < m_TimesToTame) + { + if (m_World->GetTickRandomNumber(50) == 25) + { + m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 0); + m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 2); + m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 6); + m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 8); + + m_Attachee->Detach(); + m_bIsRearing = true; + } + } + else + { + m_bIsTame = true; + } + } + + if (m_bIsRearing) + { + if (m_RearTickCount == 20) + { + m_bIsRearing = false; + m_RearTickCount = 0; + } + else + { + m_RearTickCount++; + } + } + + m_World->BroadcastEntityMetadata(*this); +} + + + + + +void cHorse::OnRightClicked(cPlayer & a_Player) +{ + if (!m_bIsSaddled && m_bIsTame) + { + if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_SADDLE) + { + // Saddle the horse: + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + m_bIsSaddled = true; + m_World->BroadcastEntityMetadata(*this); + } + else if (!a_Player.GetEquippedItem().IsEmpty()) + { + // The horse doesn't like being hit, make it rear: + m_bIsRearing = true; + m_RearTickCount = 0; + } + } + else + { + if (m_Attachee != NULL) + { + if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) + { + a_Player.Detach(); + return; + } + + if (m_Attachee->IsPlayer()) + { + return; + } + + m_Attachee->Detach(); + } + + m_TameAttemptTimes++; + a_Player.AttachTo(this); + } +} + + + + + +void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER); + if (m_bIsSaddled) + { + a_Drops.push_back(cItem(E_ITEM_SADDLE, 1)); + } +} + + + + diff --git a/src/Mobs/Old Mobs/Horse.h b/src/Mobs/Old Mobs/Horse.h new file mode 100644 index 000000000..47189b3b0 --- /dev/null +++ b/src/Mobs/Old Mobs/Horse.h @@ -0,0 +1,44 @@ + +#pragma once + +#include "PassiveMonster.h" + + + + + +class cHorse : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + cHorse(int Type, int Color, int Style, int TameTimes); + + CLASS_PROTODEF(cHorse) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + + bool IsSaddled (void) const {return m_bIsSaddled; } + bool IsChested (void) const {return m_bHasChest; } + bool IsEating (void) const {return m_bIsEating; } + bool IsRearing (void) const {return m_bIsRearing; } + bool IsMthOpen (void) const {return m_bIsMouthOpen; } + bool IsTame (void) const {return m_bIsTame; } + int GetHorseType (void) const {return m_Type; } + int GetHorseColor (void) const {return m_Color; } + int GetHorseStyle (void) const {return m_Style; } + int GetHorseArmour (void) const {return m_Armour;} + +private: + + bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame, m_bIsSaddled; + int m_Type, m_Color, m_Style, m_Armour, m_TimesToTame, m_TameAttemptTimes, m_RearTickCount; + +} ; + + + + diff --git a/src/Mobs/Old Mobs/IronGolem.cpp b/src/Mobs/Old Mobs/IronGolem.cpp new file mode 100644 index 000000000..dae4615e4 --- /dev/null +++ b/src/Mobs/Old Mobs/IronGolem.cpp @@ -0,0 +1,28 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "IronGolem.h" + + + + + +cIronGolem::cIronGolem(void) : + super("IronGolem", mtIronGolem, "mob.IronGolem.hit", "mob.IronGolem.death", 1.4, 2.9) +{ +} + + + + + +void cIronGolem::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + UNUSED(a_Killer); + AddRandomDropItem(a_Drops, 0, 5, E_ITEM_IRON); + AddRandomDropItem(a_Drops, 0, 2, E_BLOCK_FLOWER); +} + + + + diff --git a/src/Mobs/Old Mobs/IronGolem.h b/src/Mobs/Old Mobs/IronGolem.h new file mode 100644 index 000000000..c5341ed76 --- /dev/null +++ b/src/Mobs/Old Mobs/IronGolem.h @@ -0,0 +1,29 @@ + +#pragma once + +#include "PassiveAggressiveMonster.h" + + + + + +class cIronGolem : + public cPassiveAggressiveMonster +{ + typedef cPassiveAggressiveMonster super; + +public: + cIronGolem(void); + + CLASS_PROTODEF(cIronGolem) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + + // Iron golems do not drown nor float + virtual void HandleAir(void) override {} + virtual void SetSwimState(cChunk & a_Chunk) override {} +} ; + + + + diff --git a/src/Mobs/Old Mobs/MagmaCube.cpp b/src/Mobs/Old Mobs/MagmaCube.cpp new file mode 100644 index 000000000..3e9abc108 --- /dev/null +++ b/src/Mobs/Old Mobs/MagmaCube.cpp @@ -0,0 +1,30 @@ +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "MagmaCube.h" + + + + + +cMagmaCube::cMagmaCube(int a_Size) : + super("MagmaCube", mtMagmaCube, "mob.MagmaCube.big", "mob.MagmaCube.big", 0.6 * a_Size, 0.6 * a_Size), + m_Size(a_Size) +{ +} + + + + + +void cMagmaCube::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + UNUSED(a_Killer); + if (GetSize() > 1) + { + AddRandomUncommonDropItem(a_Drops, 25.0f, E_ITEM_MAGMA_CREAM); + } +} + + + + diff --git a/src/Mobs/Old Mobs/MagmaCube.h b/src/Mobs/Old Mobs/MagmaCube.h new file mode 100644 index 000000000..bfe63fa2e --- /dev/null +++ b/src/Mobs/Old Mobs/MagmaCube.h @@ -0,0 +1,31 @@ +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cMagmaCube : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + /// Creates a MagmaCube of the specified size; size is 1 .. 3, with 1 being the smallest + cMagmaCube(int a_Size); + + CLASS_PROTODEF(cMagmaCube) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + int GetSize(void) const { return m_Size; } + +protected: + + /// Size of the MagmaCube, 1 .. 3, with 1 being the smallest + int m_Size; +} ; + + + + diff --git a/src/Mobs/Old Mobs/Monster.cpp b/src/Mobs/Old Mobs/Monster.cpp new file mode 100644 index 000000000..fe8a7346f --- /dev/null +++ b/src/Mobs/Old Mobs/Monster.cpp @@ -0,0 +1,1045 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "IncludeAllMonsters.h" +#include "../Root.h" +#include "../Server.h" +#include "../ClientHandle.h" +#include "../World.h" +#include "../Entities/Player.h" +#include "../Entities/ExpOrb.h" +#include "../MonsterConfig.h" +#include "../MersenneTwister.h" + +#include "../Chunk.h" +#include "../FastRandom.h" + + + + + +/** Map for eType <-> string +Needs to be alpha-sorted by the strings, because binary search is used in StringToMobType() +The strings need to be lowercase (for more efficient comparisons in StringToMobType()) +*/ +static const struct +{ + cMonster::eType m_Type; + const char * m_lcName; +} g_MobTypeNames[] = +{ + {cMonster::mtBat, "bat"}, + {cMonster::mtBlaze, "blaze"}, + {cMonster::mtCaveSpider, "cavespider"}, + {cMonster::mtChicken, "chicken"}, + {cMonster::mtCow, "cow"}, + {cMonster::mtCreeper, "creeper"}, + {cMonster::mtEnderman, "enderman"}, + {cMonster::mtEnderDragon, "enderdragon"}, + {cMonster::mtGhast, "ghast"}, + {cMonster::mtHorse, "horse"}, + {cMonster::mtIronGolem, "irongolem"}, + {cMonster::mtMagmaCube, "magmacube"}, + {cMonster::mtMooshroom, "mooshroom"}, + {cMonster::mtOcelot, "ocelot"}, + {cMonster::mtPig, "pig"}, + {cMonster::mtSheep, "sheep"}, + {cMonster::mtSilverfish, "silverfish"}, + {cMonster::mtSkeleton, "skeleton"}, + {cMonster::mtSlime, "slime"}, + {cMonster::mtSnowGolem, "snowgolem"}, + {cMonster::mtSpider, "spider"}, + {cMonster::mtSquid, "squid"}, + {cMonster::mtVillager, "villager"}, + {cMonster::mtWitch, "witch"}, + {cMonster::mtWither, "wither"}, + {cMonster::mtWolf, "wolf"}, + {cMonster::mtZombie, "zombie"}, + {cMonster::mtZombiePigman, "zombiepigman"}, +} ; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cMonster: + +cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) + : super(etMonster, a_Width, a_Height) + , m_EMState(IDLE) + , m_EMPersonality(AGGRESSIVE) + , m_Target(NULL) + , m_bMovingToDestination(false) + , m_LastGroundHeight(POSY_TOINT) + , m_IdleInterval(0) + , m_DestroyTimer(0) + , m_MobType(a_MobType) + , m_SoundHurt(a_SoundHurt) + , m_SoundDeath(a_SoundDeath) + , m_AttackRate(3) + , m_AttackDamage(1) + , m_AttackRange(2) + , m_AttackInterval(0) + , m_SightDistance(25) + , m_DropChanceWeapon(0.085f) + , m_DropChanceHelmet(0.085f) + , m_DropChanceChestplate(0.085f) + , m_DropChanceLeggings(0.085f) + , m_DropChanceBoots(0.085f) + , m_CanPickUpLoot(true) + , m_BurnsInDaylight(false) +{ + if (!a_ConfigName.empty()) + { + GetMonsterConfig(a_ConfigName); + } +} + + + + + +void cMonster::SpawnOn(cClientHandle & a_Client) +{ + a_Client.SendSpawnMob(*this); +} + + + + + +void cMonster::TickPathFinding() +{ + const int PosX = POSX_TOINT; + const int PosY = POSY_TOINT; + const int PosZ = POSZ_TOINT; + + std::vector m_PotentialCoordinates; + m_TraversedCoordinates.push_back(Vector3i(PosX, PosY, PosZ)); + + static const struct // Define which directions to try to move to + { + int x, z; + } gCrossCoords[] = + { + { 1, 0}, + {-1, 0}, + { 0, 1}, + { 0, -1}, + } ; + + if ((PosY - 1 < 0) || (PosY + 2 > cChunkDef::Height) /* PosY + 1 will never be true if PosY + 2 is not */) + { + // Too low/high, can't really do anything + FinishPathFinding(); + return; + } + + for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) + { + if (IsCoordinateInTraversedList(Vector3i(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ))) + { + continue; + } + + BLOCKTYPE BlockAtY = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ); + BLOCKTYPE BlockAtYP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 1, gCrossCoords[i].z + PosZ); + BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ); + int LowestY = FindFirstNonAirBlockPosition(gCrossCoords[i].x + PosX, gCrossCoords[i].z + PosZ); + BLOCKTYPE BlockAtLowestY = m_World->GetBlock(gCrossCoords[i].x + PosX, LowestY, gCrossCoords[i].z + PosZ); + + if ( + (!cBlockInfo::IsSolid(BlockAtY)) && + (!cBlockInfo::IsSolid(BlockAtYP)) && + (!IsBlockLava(BlockAtLowestY)) && + (BlockAtLowestY != E_BLOCK_CACTUS) && + (PosY - LowestY < FALL_DAMAGE_HEIGHT) + ) + { + m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY, gCrossCoords[i].z + PosZ)); + } + else if ( + (cBlockInfo::IsSolid(BlockAtY)) && + (BlockAtY != E_BLOCK_CACTUS) && + (!cBlockInfo::IsSolid(BlockAtYP)) && + (!cBlockInfo::IsSolid(BlockAtYPP)) && + (BlockAtY != E_BLOCK_FENCE) && + (BlockAtY != E_BLOCK_FENCE_GATE) + ) + { + m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY + 1, gCrossCoords[i].z + PosZ)); + } + } + + if (!m_PotentialCoordinates.empty()) + { + Vector3f ShortestCoords = m_PotentialCoordinates.front(); + for (std::vector::const_iterator itr = m_PotentialCoordinates.begin(); itr != m_PotentialCoordinates.end(); ++itr) + { + Vector3f Distance = m_FinalDestination - ShortestCoords; + Vector3f Distance2 = m_FinalDestination - *itr; + if (Distance.SqrLength() > Distance2.SqrLength()) + { + ShortestCoords = *itr; + } + } + + m_Destination = ShortestCoords; + m_Destination.z += 0.5f; + m_Destination.x += 0.5f; + } + else + { + FinishPathFinding(); + } +} + + + + + +void cMonster::MoveToPosition(const Vector3d & a_Position) +{ + FinishPathFinding(); + + m_FinalDestination = a_Position; + m_bMovingToDestination = true; + TickPathFinding(); +} + + + +bool cMonster::IsCoordinateInTraversedList(Vector3i a_Coords) +{ + return (std::find(m_TraversedCoordinates.begin(), m_TraversedCoordinates.end(), a_Coords) != m_TraversedCoordinates.end()); +} + + + + + +bool cMonster::ReachedDestination() +{ + if ((m_Destination - GetPosition()).Length() < 0.5f) + { + return true; + } + + return false; +} + + + + +bool cMonster::ReachedFinalDestination() +{ + if ((GetPosition() - m_FinalDestination).Length() <= m_AttackRange) + { + return true; + } + + return false; +} + + + + + +void cMonster::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if (m_Health <= 0) + { + // The mob is dead, but we're still animating the "puff" they leave when they die + m_DestroyTimer += a_Dt / 1000; + if (m_DestroyTimer > 1) + { + Destroy(true); + } + return; + } + + if ((m_Target != NULL) && m_Target->IsDestroyed()) + m_Target = NULL; + + // Burning in daylight + HandleDaylightBurning(a_Chunk); + + a_Dt /= 1000; + + if (m_bMovingToDestination) + { + if (m_bOnGround) + { + if (DoesPosYRequireJump((int)floor(m_Destination.y))) + { + m_bOnGround = false; + + // TODO: Change to AddSpeedY once collision detection is fixed - currently, mobs will go into blocks attempting to jump without a teleport + AddPosY(1.2); // Jump!! + } + } + + Vector3f Distance = m_Destination - GetPosition(); + if (!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move + { + Distance.y = 0; + Distance.Normalize(); + + if (m_bOnGround) + { + Distance *= 2.5f; + } + else if (IsSwimming()) + { + Distance *= 1.3f; + } + else + { + // Don't let the mob move too much if he's falling. + Distance *= 0.25f; + } + + AddSpeedX(Distance.x); + AddSpeedZ(Distance.z); + + // It's too buggy! + /* + if (m_EMState == ESCAPING) + { + // Runs Faster when escaping :D otherwise they just walk away + SetSpeedX (GetSpeedX() * 2.f); + SetSpeedZ (GetSpeedZ() * 2.f); + } + */ + } + else + { + if (ReachedFinalDestination()) // If we have reached the ultimate, final destination, stop pathfinding and attack if appropriate + { + FinishPathFinding(); + } + else + { + TickPathFinding(); // We have reached the next point in our path, calculate another point + } + } + } + + SetPitchAndYawFromDestination(); + HandleFalling(); + + switch (m_EMState) + { + case IDLE: + { + // If enemy passive we ignore checks for player visibility + InStateIdle(a_Dt); + break; + } + case CHASING: + { + // If we do not see a player anymore skip chasing action + InStateChasing(a_Dt); + break; + } + case ESCAPING: + { + InStateEscaping(a_Dt); + break; + } + + case ATTACKING: break; + } // switch (m_EMState) + + BroadcastMovementUpdate(); +} + + + + +void cMonster::SetPitchAndYawFromDestination() +{ + Vector3d FinalDestination = m_FinalDestination; + if (m_Target != NULL) + { + if (m_Target->IsPlayer()) + { + FinalDestination.y = ((cPlayer *)m_Target)->GetStance(); + } + else + { + FinalDestination.y = GetHeight(); + } + } + + Vector3d Distance = FinalDestination - GetPosition(); + if (Distance.SqrLength() > 0.1f) + { + { + double Rotation, Pitch; + Distance.Normalize(); + VectorToEuler(Distance.x, Distance.y, Distance.z, Rotation, Pitch); + SetHeadYaw(Rotation); + SetPitch(-Pitch); + } + + { + Vector3d BodyDistance = m_Destination - GetPosition(); + double Rotation, Pitch; + Distance.Normalize(); + VectorToEuler(BodyDistance.x, BodyDistance.y, BodyDistance.z, Rotation, Pitch); + SetYaw(Rotation); + } + } +} + + + + +void cMonster::HandleFalling() +{ + if (m_bOnGround) + { + int Damage = (m_LastGroundHeight - POSY_TOINT) - 3; + + if (Damage > 0) + { + TakeDamage(dtFalling, NULL, Damage, Damage, 0); + + // Fall particles + GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, POSY_TOINT - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */); + } + + m_LastGroundHeight = POSY_TOINT; + } +} + + + + + +int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ) +{ + int PosY = POSY_TOINT; + PosY = Clamp(PosY, 0, cChunkDef::Height); + + if (!cBlockInfo::IsSolid(m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ)))) + { + while (!cBlockInfo::IsSolid(m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))) && (PosY > 0)) + { + PosY--; + } + + return PosY + 1; + } + else + { + while (cBlockInfo::IsSolid(m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))) && (PosY < cChunkDef::Height)) + { + PosY++; + } + + return PosY; + } +} + + + + + + +bool cMonster::DoTakeDamage(TakeDamageInfo & a_TDI) +{ + if (!super::DoTakeDamage(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 != NULL) + { + m_Target = a_TDI.Attacker; + } + return true; +} + + + + + +void cMonster::KilledBy(TakeDamageInfo & a_TDI) +{ + super::KilledBy(a_TDI); + if (m_SoundHurt != "") + { + m_World->BroadcastSoundEffect(m_SoundDeath, GetPosX(), GetPosY(), GetPosZ(), 1.0f, 0.8f); + } + int Reward; + switch (m_MobType) + { + // Animals + case cMonster::mtChicken: + case cMonster::mtCow: + case cMonster::mtHorse: + case cMonster::mtPig: + case cMonster::mtSheep: + case cMonster::mtSquid: + case cMonster::mtMooshroom: + case cMonster::mtOcelot: + case cMonster::mtWolf: + { + Reward = m_World->GetTickRandomNumber(2) + 1; + break; + } + + // Monsters + case cMonster::mtCaveSpider: + case cMonster::mtCreeper: + case cMonster::mtEnderman: + case cMonster::mtGhast: + case cMonster::mtSilverfish: + case cMonster::mtSkeleton: + case cMonster::mtSpider: + case cMonster::mtWitch: + case cMonster::mtZombie: + case cMonster::mtZombiePigman: + case cMonster::mtSlime: + case cMonster::mtMagmaCube: + { + Reward = 6 + (m_World->GetTickRandomNumber(2)); + break; + } + case cMonster::mtBlaze: + { + Reward = 10; + break; + } + + // Bosses + case cMonster::mtEnderDragon: + { + Reward = 12000; + break; + } + case cMonster::mtWither: + { + Reward = 50; + break; + } + + default: + { + Reward = 0; + break; + } + } + if ((a_TDI.Attacker != NULL) && (!IsBaby())) + { + m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), Reward); + } + m_DestroyTimer = 0; +} + + + + + +// Checks to see if EventSeePlayer should be fired +// monster sez: Do I see the player +void cMonster::CheckEventSeePlayer(void) +{ + // TODO: Rewrite this to use cWorld's DoWithPlayers() + cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance, false); + + if (Closest != NULL) + { + EventSeePlayer(Closest); + } +} + + + + + +void cMonster::CheckEventLostPlayer(void) +{ + if (m_Target != NULL) + { + if ((m_Target->GetPosition() - GetPosition()).Length() > m_SightDistance) + { + EventLosePlayer(); + } + } + else + { + EventLosePlayer(); + } +} + + + + + +// What to do if player is seen +// default to change state to chasing +void cMonster::EventSeePlayer(cEntity * a_SeenPlayer) +{ + m_Target = a_SeenPlayer; +} + + + + + +void cMonster::EventLosePlayer(void) +{ + m_Target = NULL; + m_EMState = IDLE; +} + + + + + +void cMonster::InStateIdle(float a_Dt) +{ + if (m_bMovingToDestination) + { + return; // Still getting there + } + + m_IdleInterval += a_Dt; + + if (m_IdleInterval > 1) + { + // At this interval the results are predictable + int rem = m_World->GetTickRandomNumber(6) + 1; + m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds + + Vector3d Dist; + Dist.x = (double)m_World->GetTickRandomNumber(10) - 5; + Dist.z = (double)m_World->GetTickRandomNumber(10) - 5; + + if ((Dist.SqrLength() > 2) && (rem >= 3)) + { + Vector3d Destination(GetPosX() + Dist.x, 0, GetPosZ() + Dist.z); + + int NextHeight = FindFirstNonAirBlockPosition(Destination.x, Destination.z); + + if (IsNextYPosReachable(NextHeight)) + { + Destination.y = NextHeight; + MoveToPosition(Destination); + } + } + } +} + + + + + +// What to do if in Chasing State +// This state should always be defined in each child class +void cMonster::InStateChasing(float a_Dt) +{ + UNUSED(a_Dt); +} + + + + + +// What to do if in Escaping State +void cMonster::InStateEscaping(float a_Dt) +{ + UNUSED(a_Dt); + + if (m_Target != NULL) + { + Vector3d newloc = GetPosition(); + newloc.x = (m_Target->GetPosition().x < newloc.x)? (newloc.x + m_SightDistance): (newloc.x - m_SightDistance); + newloc.z = (m_Target->GetPosition().z < newloc.z)? (newloc.z + m_SightDistance): (newloc.z - m_SightDistance); + MoveToPosition(newloc); + } + else + { + m_EMState = IDLE; // This shouldnt be required but just to be safe + } +} + + + + + +void cMonster::GetMonsterConfig(const AString & a_Name) +{ + cRoot::Get()->GetMonsterConfig()->AssignAttributes(this, a_Name); +} + + + + + +bool cMonster::IsUndead(void) +{ + return false; +} + + + + + +AString cMonster::MobTypeToString(cMonster::eType a_MobType) +{ + // Mob types aren't sorted, so we need to search linearly: + for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) + { + if (g_MobTypeNames[i].m_Type == a_MobType) + { + return g_MobTypeNames[i].m_lcName; + } + } + + // Not found: + return ""; +} + + + + + +cMonster::eType cMonster::StringToMobType(const AString & a_Name) +{ + AString lcName = StrToLower(a_Name); + + // Binary-search for the lowercase name: + int lo = 0, hi = ARRAYCOUNT(g_MobTypeNames) - 1; + while (hi - lo > 1) + { + int mid = (lo + hi) / 2; + int res = strcmp(g_MobTypeNames[mid].m_lcName, lcName.c_str()); + if (res == 0) + { + return g_MobTypeNames[mid].m_Type; + } + if (res < 0) + { + lo = mid; + } + else + { + hi = mid; + } + } + // Range has collapsed to at most two elements, compare each: + if (strcmp(g_MobTypeNames[lo].m_lcName, lcName.c_str()) == 0) + { + return g_MobTypeNames[lo].m_Type; + } + if ((lo != hi) && (strcmp(g_MobTypeNames[hi].m_lcName, lcName.c_str()) == 0)) + { + return g_MobTypeNames[hi].m_Type; + } + + // Not found: + return mtInvalidType; +} + + + + + +cMonster::eFamily cMonster::FamilyFromType(eType a_Type) +{ + // Passive-agressive mobs are counted in mob spawning code as passive + + switch (a_Type) + { + case mtBat: return mfAmbient; + case mtBlaze: return mfHostile; + case mtCaveSpider: return mfHostile; + case mtChicken: return mfPassive; + case mtCow: return mfPassive; + case mtCreeper: return mfHostile; + case mtEnderDragon: return mfNoSpawn; + case mtEnderman: return mfHostile; + case mtGhast: return mfHostile; + case mtGiant: return mfNoSpawn; + case mtHorse: return mfPassive; + case mtIronGolem: return mfPassive; + case mtMagmaCube: return mfHostile; + case mtMooshroom: return mfHostile; + case mtOcelot: return mfPassive; + case mtPig: return mfPassive; + case mtSheep: return mfPassive; + case mtSilverfish: return mfHostile; + case mtSkeleton: return mfHostile; + case mtSlime: return mfHostile; + case mtSnowGolem: return mfNoSpawn; + case mtSpider: return mfHostile; + case mtSquid: return mfWater; + case mtVillager: return mfPassive; + case mtWitch: return mfHostile; + case mtWither: return mfNoSpawn; + case mtWolf: return mfHostile; + case mtZombie: return mfHostile; + case mtZombiePigman: return mfHostile; + + case mtInvalidType: break; + } + ASSERT(!"Unhandled mob type"); + return mfUnhandled; +} + + + + + +int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily) +{ + switch (a_MobFamily) + { + case mfHostile: return 40; + case mfPassive: return 40; + case mfAmbient: return 40; + case mfWater: return 400; + case mfNoSpawn: return -1; + case mfUnhandled: break; + } + ASSERT(!"Unhandled mob family"); + return -1; +} + + + + + +cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType) +{ + cFastRandom Random; + cMonster * toReturn = NULL; + + // Create the mob entity + switch (a_MobType) + { + case mtMagmaCube: + { + toReturn = new cMagmaCube(Random.NextInt(2) + 1); + break; + } + case mtSlime: + { + toReturn = new cSlime(1 << Random.NextInt(3)); // Size 1, 2 or 4 + break; + } + case mtSkeleton: + { + // TODO: Actual detection of spawning in Nether + toReturn = new cSkeleton((Random.NextInt(1) == 0) ? false : true); + break; + } + case mtVillager: + { + int VillagerType = Random.NextInt(6); + if (VillagerType == 6) + { + // Give farmers a better chance of spawning + VillagerType = 0; + } + + toReturn = new cVillager((cVillager::eVillagerType)VillagerType); + break; + } + case mtHorse: + { + // Horses take a type (species), a colour, and a style (dots, stripes, etc.) + int HorseType = Random.NextInt(7); + int HorseColor = Random.NextInt(6); + int HorseStyle = Random.NextInt(6); + int HorseTameTimes = Random.NextInt(6) + 1; + + if ((HorseType == 5) || (HorseType == 6) || (HorseType == 7)) + { + // Increase chances of normal horse (zero) + HorseType = 0; + } + + toReturn = new cHorse(HorseType, HorseColor, HorseStyle, HorseTameTimes); + break; + } + + case mtBat: toReturn = new cBat(); break; + case mtBlaze: toReturn = new cBlaze(); break; + case mtCaveSpider: toReturn = new cCaveSpider(); break; + case mtChicken: toReturn = new cChicken(); break; + case mtCow: toReturn = new cCow(); break; + case mtCreeper: toReturn = new cCreeper(); break; + case mtEnderDragon: toReturn = new cEnderDragon(); break; + case mtEnderman: toReturn = new cEnderman(); break; + case mtGhast: toReturn = new cGhast(); break; + case mtGiant: toReturn = new cGiant(); break; + case mtIronGolem: toReturn = new cIronGolem(); break; + case mtMooshroom: toReturn = new cMooshroom(); break; + case mtOcelot: toReturn = new cOcelot(); break; + case mtPig: toReturn = new cPig(); break; + case mtSheep: toReturn = new cSheep(); break; + case mtSilverfish: toReturn = new cSilverfish(); break; + case mtSnowGolem: toReturn = new cSnowGolem(); break; + case mtSpider: toReturn = new cSpider(); break; + case mtSquid: toReturn = new cSquid(); break; + case mtWitch: toReturn = new cWitch(); break; + case mtWither: toReturn = new cWither(); break; + case mtWolf: toReturn = new cWolf(); break; + case mtZombie: toReturn = new cZombie(false); break; // TODO: Infected zombie parameter + case mtZombiePigman: toReturn = new cZombiePigman(); break; + default: + { + ASSERT(!"Unhandled mob type whilst trying to spawn mob!"); + } + } + return toReturn; +} + + + + + +void cMonster::AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth) +{ + MTRand r1; + int Count = r1.randInt() % (a_Max + 1 - a_Min) + a_Min; + if (Count > 0) + { + a_Drops.push_back(cItem(a_Item, Count, a_ItemHealth)); + } +} + + + + + +void cMonster::AddRandomUncommonDropItem(cItems & a_Drops, float a_Chance, short a_Item, short a_ItemHealth) +{ + MTRand r1; + int Count = r1.randInt() % 1000; + if (Count < (a_Chance * 10)) + { + a_Drops.push_back(cItem(a_Item, 1, a_ItemHealth)); + } +} + + + + + +void cMonster::AddRandomRareDropItem(cItems & a_Drops, cItems & a_Items, short a_LootingLevel) +{ + MTRand r1; + int Count = r1.randInt() % 200; + if (Count < (5 + a_LootingLevel)) + { + int Rare = r1.randInt() % a_Items.Size(); + a_Drops.push_back(a_Items.at(Rare)); + } +} + + + + + +void cMonster::AddRandomArmorDropItem(cItems & a_Drops, short a_LootingLevel) +{ + MTRand r1; + if (r1.randInt() % 200 < ((m_DropChanceHelmet * 200) + (a_LootingLevel * 2))) + { + if (!GetEquippedHelmet().IsEmpty()) a_Drops.push_back(GetEquippedHelmet()); + } + + if (r1.randInt() % 200 < ((m_DropChanceChestplate * 200) + (a_LootingLevel * 2))) + { + if (!GetEquippedChestplate().IsEmpty()) a_Drops.push_back(GetEquippedChestplate()); + } + + if (r1.randInt() % 200 < ((m_DropChanceLeggings * 200) + (a_LootingLevel * 2))) + { + if (!GetEquippedLeggings().IsEmpty()) a_Drops.push_back(GetEquippedLeggings()); + } + + if (r1.randInt() % 200 < ((m_DropChanceBoots * 200) + (a_LootingLevel * 2))) + { + if (!GetEquippedBoots().IsEmpty()) a_Drops.push_back(GetEquippedBoots()); + } +} + + + + + +void cMonster::AddRandomWeaponDropItem(cItems & a_Drops, short a_LootingLevel) +{ + MTRand r1; + if (r1.randInt() % 200 < ((m_DropChanceWeapon * 200) + (a_LootingLevel * 2))) + { + if (!GetEquippedWeapon().IsEmpty()) a_Drops.push_back(GetEquippedWeapon()); + } +} + + + + + +void cMonster::HandleDaylightBurning(cChunk & a_Chunk) +{ + if (!m_BurnsInDaylight) + { + return; + } + + int RelY = POSY_TOINT; + if ((RelY < 0) || (RelY >= cChunkDef::Height)) + { + // Outside the world + return; + } + + int RelX = POSX_TOINT - GetChunkX() * cChunkDef::Width; + int RelZ = POSZ_TOINT - GetChunkZ() * cChunkDef::Width; + + if (!a_Chunk.IsLightValid()) + { + m_World->QueueLightChunk(GetChunkX(), GetChunkZ()); + return; + } + + if ( + (a_Chunk.GetSkyLight(RelX, RelY, RelZ) == 15) && // In the daylight + (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand + (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime + !IsOnFire() && // Not already burning + GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT) // Not raining + ) + { + // Burn for 100 ticks, then decide again + StartBurning(100); + } +} + + + + +cMonster::eFamily cMonster::GetMobFamily(void) const +{ + return FamilyFromType(m_MobType); +} + + + + diff --git a/src/Mobs/Old Mobs/Monster.h b/src/Mobs/Old Mobs/Monster.h new file mode 100644 index 000000000..cdbd26c09 --- /dev/null +++ b/src/Mobs/Old Mobs/Monster.h @@ -0,0 +1,271 @@ + +#pragma once + +#include "../Entities/Pawn.h" +#include "../Defines.h" +#include "../BlockID.h" +#include "../Item.h" +#include "../Enchantments.h" + + + + + +class cClientHandle; +class cWorld; + + + + +// tolua_begin +class cMonster : + public cPawn +{ + typedef cPawn super; +public: + /// This identifies individual monster type, as well as their network type-ID + enum eType + { + mtInvalidType = -1, + + mtBat = E_META_SPAWN_EGG_BAT, + mtBlaze = E_META_SPAWN_EGG_BLAZE, + mtCaveSpider = E_META_SPAWN_EGG_CAVE_SPIDER, + mtChicken = E_META_SPAWN_EGG_CHICKEN, + mtCow = E_META_SPAWN_EGG_COW, + mtCreeper = E_META_SPAWN_EGG_CREEPER, + mtEnderDragon = E_META_SPAWN_EGG_ENDER_DRAGON, + mtEnderman = E_META_SPAWN_EGG_ENDERMAN, + mtGhast = E_META_SPAWN_EGG_GHAST, + mtGiant = E_META_SPAWN_EGG_GIANT, + mtHorse = E_META_SPAWN_EGG_HORSE, + mtIronGolem = E_META_SPAWN_EGG_IRON_GOLEM, + mtMagmaCube = E_META_SPAWN_EGG_MAGMA_CUBE, + mtMooshroom = E_META_SPAWN_EGG_MOOSHROOM, + mtOcelot = E_META_SPAWN_EGG_OCELOT, + mtPig = E_META_SPAWN_EGG_PIG, + mtSheep = E_META_SPAWN_EGG_SHEEP, + mtSilverfish = E_META_SPAWN_EGG_SILVERFISH, + mtSkeleton = E_META_SPAWN_EGG_SKELETON, + mtSlime = E_META_SPAWN_EGG_SLIME, + mtSnowGolem = E_META_SPAWN_EGG_SNOW_GOLEM, + mtSpider = E_META_SPAWN_EGG_SPIDER, + mtSquid = E_META_SPAWN_EGG_SQUID, + mtVillager = E_META_SPAWN_EGG_VILLAGER, + mtWitch = E_META_SPAWN_EGG_WITCH, + mtWither = E_META_SPAWN_EGG_WITHER, + mtWolf = E_META_SPAWN_EGG_WOLF, + mtZombie = E_META_SPAWN_EGG_ZOMBIE, + mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN, + } ; + + enum eFamily + { + mfHostile = 0, // Spider, Zombies ... + mfPassive = 1, // Cows, Pigs + mfAmbient = 2, // Bats + mfWater = 3, // Squid + + mfNoSpawn, + mfUnhandled, // Nothing. Be sure this is the last and the others are in order + } ; + + // tolua_end + + enum MState{ATTACKING, IDLE, CHASING, ESCAPING} m_EMState; + enum MPersonality{PASSIVE, AGGRESSIVE, COWARDLY} m_EMPersonality; + + /** Creates the mob object. + If a_ConfigName is not empty, the configuration is loaded using GetMonsterConfig() + a_MobType is the type of the mob (also used in the protocol ( http://wiki.vg/Entities#Mobs 2012_12_22)) + a_SoundHurt and a_SoundDeath are assigned into m_SoundHurt and m_SoundDeath, respectively + */ + cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + + CLASS_PROTODEF(cMonster) + + virtual void SpawnOn(cClientHandle & a_ClientHandle) override; + + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; + + virtual void KilledBy(TakeDamageInfo & a_TDI) override; + + virtual void MoveToPosition(const Vector3d & a_Position); // tolua_export + virtual bool ReachedDestination(void); + + // tolua_begin + eType GetMobType(void) const {return m_MobType; } + eFamily GetMobFamily(void) const; + // tolua_end + + virtual void CheckEventSeePlayer(void); + virtual void EventSeePlayer(cEntity * a_Player); + + /// Reads the monster configuration for the specified monster name and assigns it to this object. + void GetMonsterConfig(const AString & a_Name); + + /** Returns whether this mob is undead (skeleton, zombie, etc.) */ + virtual bool IsUndead(void); + + virtual void EventLosePlayer(void); + virtual void CheckEventLostPlayer(void); + + virtual void InStateIdle (float a_Dt); + virtual void InStateChasing (float a_Dt); + virtual void InStateEscaping(float a_Dt); + + int GetAttackRate() { return (int)m_AttackRate; } + void SetAttackRate(float a_AttackRate) { m_AttackRate = a_AttackRate; } + void SetAttackRange(int a_AttackRange) { m_AttackRange = a_AttackRange; } + void SetAttackDamage(int a_AttackDamage) { m_AttackDamage = a_AttackDamage; } + void SetSightDistance(int a_SightDistance) { m_SightDistance = a_SightDistance; } + + float GetDropChanceWeapon() { return m_DropChanceWeapon; } + float GetDropChanceHelmet() { return m_DropChanceHelmet; } + float GetDropChanceChestplate() { return m_DropChanceChestplate; } + float GetDropChanceLeggings() { return m_DropChanceLeggings; } + float GetDropChanceBoots() { return m_DropChanceBoots; } + bool CanPickUpLoot() { return m_CanPickUpLoot; } + void SetDropChanceWeapon(float a_DropChanceWeapon) { m_DropChanceWeapon = a_DropChanceWeapon; } + void SetDropChanceHelmet(float a_DropChanceHelmet) { m_DropChanceHelmet = a_DropChanceHelmet; } + void SetDropChanceChestplate(float a_DropChanceChestplate) { m_DropChanceChestplate = a_DropChanceChestplate; } + 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; } + + /// Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick + void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; } + + // Overridables to handle ageable mobs + virtual bool IsBaby (void) const { return false; } + virtual bool IsTame (void) const { return false; } + virtual bool IsSitting (void) const { return false; } + + // tolua_begin + + /// Translates MobType enum to a string, empty string if unknown + static AString MobTypeToString(eType a_MobType); + + /// Translates MobType string to the enum, mtInvalidType if not recognized + static eType StringToMobType(const AString & a_MobTypeName); + + /// Returns the mob family based on the type + static eFamily FamilyFromType(eType a_MobType); + + /// Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family + static int GetSpawnDelay(cMonster::eFamily a_MobFamily); + + // tolua_end + + /** Creates a new object of the specified mob. + a_MobType is the type of the mob to be created + Asserts and returns null if mob type is not specified + */ + static cMonster * NewMonsterFromType(eType a_MobType); + +protected: + + /* ======= PATHFINDING ======= */ + + /** A pointer to the entity this mobile is aiming to reach */ + cEntity * m_Target; + /** Coordinates of the next position that should be reached */ + Vector3d m_Destination; + /** Coordinates for the ultimate, final destination. */ + Vector3d m_FinalDestination; + /** Returns if the ultimate, final destination has been reached */ + bool ReachedFinalDestination(void); + + /** Stores if mobile is currently moving towards the ultimate, final destination */ + bool m_bMovingToDestination; + + /** Finds the first non-air block position (not the highest, as cWorld::GetHeight does) + If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1 + If current Y is solid, goes up to find first nonsolid block, and returns that */ + int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ); + /** Returns if a monster can actually reach a given height by jumping or walking */ + inline bool IsNextYPosReachable(int a_PosY) + { + return ( + (a_PosY <= POSY_TOINT) || + DoesPosYRequireJump(a_PosY) + ); + } + /** Returns if a monster can reach a given height by jumping */ + inline bool DoesPosYRequireJump(int a_PosY) + { + return ((a_PosY > POSY_TOINT) && (a_PosY == POSY_TOINT + 1)); + } + + /** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */ + std::vector m_TraversedCoordinates; + /** Returns if coordinate is in the traversed list */ + bool IsCoordinateInTraversedList(Vector3i a_Coords); + + /** Finds the next place to go + This is based on the ultimate, final destination and the current position, as well as the traversed coordinates, and any environmental hazards */ + void TickPathFinding(void); + /** Finishes a pathfinding task, be it due to failure or something else */ + inline void FinishPathFinding(void) + { + m_TraversedCoordinates.clear(); + m_bMovingToDestination = false; + } + /** Sets the body yaw and head yaw/pitch based on next/ultimate destinations */ + void SetPitchAndYawFromDestination(void); + + /* =========================== */ + /* ========= FALLING ========= */ + + virtual void HandleFalling(void); + int m_LastGroundHeight; + + /* =========================== */ + + float m_IdleInterval; + float m_DestroyTimer; + + eType m_MobType; + + AString m_SoundHurt; + AString m_SoundDeath; + + float m_AttackRate; + int m_AttackDamage; + int m_AttackRange; + float m_AttackInterval; + int m_SightDistance; + + float m_DropChanceWeapon; + float m_DropChanceHelmet; + float m_DropChanceChestplate; + float m_DropChanceLeggings; + float m_DropChanceBoots; + bool m_CanPickUpLoot; + + void HandleDaylightBurning(cChunk & a_Chunk); + bool m_BurnsInDaylight; + + /** Adds a random number of a_Item between a_Min and a_Max to itemdrops a_Drops*/ + void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0); + + /** Adds a item a_Item with the chance of a_Chance (in percent) to itemdrops a_Drops*/ + void AddRandomUncommonDropItem(cItems & a_Drops, float a_Chance, short a_Item, short a_ItemHealth = 0); + + /** Adds one rare item out of the list of rare items a_Items modified by the looting level a_LootingLevel(I-III or custom) to the itemdrop a_Drops*/ + void AddRandomRareDropItem(cItems & a_Drops, cItems & a_Items, short a_LootingLevel); + + /** Adds armor that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if piccked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop*/ + void AddRandomArmorDropItem(cItems & a_Drops, short a_LootingLevel); + + /** Adds weapon that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if piccked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop*/ + void AddRandomWeaponDropItem(cItems & a_Drops, short a_LootingLevel); + + +} ; // tolua_export + + + + diff --git a/src/Mobs/Old Mobs/Mooshroom.cpp b/src/Mobs/Old Mobs/Mooshroom.cpp new file mode 100644 index 000000000..81bd3e3b4 --- /dev/null +++ b/src/Mobs/Old Mobs/Mooshroom.cpp @@ -0,0 +1,75 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Mooshroom.h" +#include "../Entities/Player.h" + + + + + + + + + + +cMooshroom::cMooshroom(void) : + super("Mooshroom", mtMooshroom, "mob.cow.hurt", "mob.cow.hurt", 0.9, 1.3) +{ +} + + + + + +void cMooshroom::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + 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); +} + + + + + +void cMooshroom::OnRightClicked(cPlayer & a_Player) +{ + switch (a_Player.GetEquippedItem().m_ItemType) + { + case E_ITEM_BUCKET: + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + a_Player.GetInventory().AddItem(E_ITEM_MILK); + } + } break; + case E_ITEM_BOWL: + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + a_Player.GetInventory().AddItem(E_ITEM_MUSHROOM_SOUP); + } + } break; + case E_ITEM_SHEARS: + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.UseEquippedItem(); + } + + cItems Drops; + Drops.push_back(cItem(E_BLOCK_RED_MUSHROOM, 5, 0)); + m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); + m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), cMonster::mtCow); + Destroy(); + } break; + } +} + diff --git a/src/Mobs/Old Mobs/Mooshroom.h b/src/Mobs/Old Mobs/Mooshroom.h new file mode 100644 index 000000000..fb002c2bf --- /dev/null +++ b/src/Mobs/Old Mobs/Mooshroom.h @@ -0,0 +1,28 @@ + +#pragma once + +#include "PassiveMonster.h" + + + + + +class cMooshroom : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + cMooshroom(void); + + CLASS_PROTODEF(cMooshroom) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); } +} ; + + + + diff --git a/src/Mobs/Old Mobs/Ocelot.h b/src/Mobs/Old Mobs/Ocelot.h new file mode 100644 index 000000000..f2727d354 --- /dev/null +++ b/src/Mobs/Old Mobs/Ocelot.h @@ -0,0 +1,26 @@ + +#pragma once + +#include "PassiveMonster.h" + + + + + +class cOcelot : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + cOcelot(void) : + super("Ocelot", mtOcelot, "mob.cat.hitt", "mob.cat.hitt", 0.6, 0.8) + { + } + + CLASS_PROTODEF(cOcelot) +} ; + + + + diff --git a/src/Mobs/Old Mobs/PassiveAggressiveMonster.cpp b/src/Mobs/Old Mobs/PassiveAggressiveMonster.cpp new file mode 100644 index 000000000..24501b1ba --- /dev/null +++ b/src/Mobs/Old Mobs/PassiveAggressiveMonster.cpp @@ -0,0 +1,41 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "PassiveAggressiveMonster.h" + +#include "../Entities/Player.h" + + + + + +cPassiveAggressiveMonster::cPassiveAggressiveMonster(const AString & a_ConfigName, eType 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_EMPersonality = PASSIVE; +} + + + + + +bool cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI) +{ + if (!super::DoTakeDamage(a_TDI)) + { + return false; + } + + if ((m_Target != NULL) && (m_Target->IsPlayer())) + { + if (!((cPlayer *)m_Target)->IsGameModeCreative()) + { + m_EMState = CHASING; + } + } + return true; +} + + + + diff --git a/src/Mobs/Old Mobs/PassiveAggressiveMonster.h b/src/Mobs/Old Mobs/PassiveAggressiveMonster.h new file mode 100644 index 000000000..a0da50e8e --- /dev/null +++ b/src/Mobs/Old Mobs/PassiveAggressiveMonster.h @@ -0,0 +1,23 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cPassiveAggressiveMonster : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cPassiveAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; +} ; + + + + diff --git a/src/Mobs/Old Mobs/PassiveMonster.cpp b/src/Mobs/Old Mobs/PassiveMonster.cpp new file mode 100644 index 000000000..2861d7314 --- /dev/null +++ b/src/Mobs/Old Mobs/PassiveMonster.cpp @@ -0,0 +1,65 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "PassiveMonster.h" +#include "../World.h" +#include "../Entities/Player.h" + + + + +cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eType 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_EMPersonality = PASSIVE; +} + + + + + +bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI) +{ + if (!super::DoTakeDamage(a_TDI)) + { + return false; + } + if ((a_TDI.Attacker != this) && (a_TDI.Attacker != NULL)) + { + m_EMState = ESCAPING; + } + return true; +} + + + + + +void cPassiveMonster::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if (m_EMState == ESCAPING) + { + CheckEventLostPlayer(); + } + cItem FollowedItem = GetFollowedItem(); + if (FollowedItem.IsEmpty()) + { + return; + } + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + if (a_Closest_Player != NULL) + { + if (a_Closest_Player->GetEquippedItem().IsEqual(FollowedItem)) + { + Vector3d PlayerPos = a_Closest_Player->GetPosition(); + MoveToPosition(PlayerPos); + } + } +} + + + + + diff --git a/src/Mobs/Old Mobs/PassiveMonster.h b/src/Mobs/Old Mobs/PassiveMonster.h new file mode 100644 index 000000000..70574585a --- /dev/null +++ b/src/Mobs/Old Mobs/PassiveMonster.h @@ -0,0 +1,30 @@ + +#pragma once + +#include "Monster.h" + + + + + +class cPassiveMonster : + public cMonster +{ + typedef cMonster super; + +public: + cPassiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + + /// When hit by someone, run away + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; + /** Returns the item that the animal of this class follows when a player holds it in hand + Return an empty item not to follow (default). */ + virtual const cItem GetFollowedItem(void) const { return cItem(); } + +} ; + + + + diff --git a/src/Mobs/Old Mobs/Pig.cpp b/src/Mobs/Old Mobs/Pig.cpp new file mode 100644 index 000000000..1f77cf613 --- /dev/null +++ b/src/Mobs/Old Mobs/Pig.cpp @@ -0,0 +1,100 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Pig.h" +#include "../Entities/Player.h" +#include "../World.h" + + + + + +cPig::cPig(void) : + super("Pig", mtPig, "mob.pig.say", "mob.pig.death", 0.9, 0.9), + m_bIsSaddled(false) +{ +} + + + + + +void cPig::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_COOKED_PORKCHOP : E_ITEM_RAW_PORKCHOP); + if (m_bIsSaddled) + { + a_Drops.push_back(cItem(E_ITEM_SADDLE, 1)); + } +} + + + + + +void cPig::OnRightClicked(cPlayer & a_Player) +{ + if (m_bIsSaddled) + { + if (m_Attachee != NULL) + { + if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) + { + // This player is already sitting in, they want out. + a_Player.Detach(); + return; + } + + if (m_Attachee->IsPlayer()) + { + // Another player is already sitting in here, cannot attach + return; + } + + // Detach whatever is sitting in this pig now: + m_Attachee->Detach(); + } + + // Attach the player to this pig + a_Player.AttachTo(this); + } + else if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_SADDLE) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + + // Set saddle state & broadcast metadata + m_bIsSaddled = true; + m_World->BroadcastEntityMetadata(*this); + } +} + + + + + +void cPig::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + // If the attachee player is holding a carrot-on-stick, let them drive this pig: + if (m_bIsSaddled && (m_Attachee != NULL)) + { + if (m_Attachee->IsPlayer() && (m_Attachee->GetEquippedWeapon().m_ItemType == E_ITEM_CARROT_ON_STICK)) + { + MoveToPosition((m_Attachee->GetPosition()) + (m_Attachee->GetLookVector()*10)); + m_bMovingToDestination = true; + } + } +} + + + + diff --git a/src/Mobs/Old Mobs/Pig.h b/src/Mobs/Old Mobs/Pig.h new file mode 100644 index 000000000..534a0ca6f --- /dev/null +++ b/src/Mobs/Old Mobs/Pig.h @@ -0,0 +1,36 @@ + +#pragma once + +#include "PassiveMonster.h" + + + + + +class cPig : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + cPig(void); + + CLASS_PROTODEF(cPig) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_CARROT); } + + bool IsSaddled(void) const { return m_bIsSaddled; } + +private: + + bool m_bIsSaddled; + +} ; + + + + diff --git a/src/Mobs/Old Mobs/Sheep.cpp b/src/Mobs/Old Mobs/Sheep.cpp new file mode 100644 index 000000000..9fb47201d --- /dev/null +++ b/src/Mobs/Old Mobs/Sheep.cpp @@ -0,0 +1,154 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Sheep.h" +#include "../BlockID.h" +#include "../Entities/Player.h" +#include "../World.h" +#include "FastRandom.h" + + + + + +cSheep::cSheep(int a_Color) : + super("Sheep", mtSheep, "mob.sheep.say", "mob.sheep.say", 0.6, 1.3), + m_IsSheared(false), + m_WoolColor(a_Color), + m_TimeToStopEating(-1) +{ + // Generate random wool color. + if (m_WoolColor == -1) + { + m_WoolColor = GenerateNaturalRandomColor(); + } + + if ((m_WoolColor < 0) || (m_WoolColor > 15)) + { + m_WoolColor = 0; + } +} + + + + + +void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + if (!m_IsSheared) + { + a_Drops.push_back(cItem(E_BLOCK_WOOL, 1, m_WoolColor)); + } +} + + + + + +void cSheep::OnRightClicked(cPlayer & a_Player) +{ + const cItem & EquippedItem = a_Player.GetEquippedItem(); + if ((EquippedItem.m_ItemType == E_ITEM_SHEARS) && !IsSheared() && !IsBaby()) + { + m_IsSheared = true; + m_World->BroadcastEntityMetadata(*this); + a_Player.UseEquippedItem(); + + cItems Drops; + int NumDrops = m_World->GetTickRandomNumber(2) + 1; + Drops.push_back(cItem(E_BLOCK_WOOL, NumDrops, m_WoolColor)); + m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); + m_World->BroadcastSoundEffect("mob.sheep.shear", GetPosX(), GetPosY(), GetPosZ(), 1.0f, 1.0f); + } + else if ((EquippedItem.m_ItemType == E_ITEM_DYE) && (m_WoolColor != 15 - EquippedItem.m_ItemDamage)) + { + m_WoolColor = 15 - EquippedItem.m_ItemDamage; + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + m_World->BroadcastEntityMetadata(*this); + } +} + + + + + +void cSheep::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + int PosX = POSX_TOINT; + int PosY = POSY_TOINT - 1; + int PosZ = POSZ_TOINT; + + if ((PosY <= 0) || (PosY > cChunkDef::Height)) + { + return; + } + + if (m_TimeToStopEating > 0) + { + m_bMovingToDestination = false; // The sheep should not move when he's eating + m_TimeToStopEating--; + + if (m_TimeToStopEating == 0) + { + if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS) // Make sure grass hasn't been destroyed in the meantime + { + // The sheep ate the grass so we change it to dirt + m_World->SetBlock(PosX, PosY, PosZ, E_BLOCK_DIRT, 0); + GetWorld()->BroadcastSoundParticleEffect(2001, PosX, PosY, PosX, E_BLOCK_GRASS); + m_IsSheared = false; + m_World->BroadcastEntityMetadata(*this); + } + } + } + else + { + if (m_World->GetTickRandomNumber(600) == 1) + { + if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS) + { + m_World->BroadcastEntityStatus(*this, esSheepEating); + m_TimeToStopEating = 40; + } + } + } +} + + + + + +NIBBLETYPE cSheep::GenerateNaturalRandomColor(void) +{ + cFastRandom Random; + int Chance = Random.NextInt(101); + + if (Chance <= 81) + { + return E_META_WOOL_WHITE; + } + else if (Chance <= 86) + { + return E_META_WOOL_BLACK; + } + else if (Chance <= 91) + { + return E_META_WOOL_GRAY; + } + else if (Chance <= 96) + { + return E_META_WOOL_LIGHTGRAY; + } + else if (Chance <= 99) + { + return E_META_WOOL_BROWN; + } + else + { + return E_META_WOOL_PINK; + } +} + diff --git a/src/Mobs/Old Mobs/Sheep.h b/src/Mobs/Old Mobs/Sheep.h new file mode 100644 index 000000000..28e1c7254 --- /dev/null +++ b/src/Mobs/Old Mobs/Sheep.h @@ -0,0 +1,50 @@ + +#pragma once + +#include "PassiveMonster.h" + + + + + +class cSheep : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + + /** The number is the color of the sheep. + Use E_META_WOOL_* constants for the wool color. + If you type -1, the server will generate a random color + with the GenerateNaturalRandomColor() function. */ + cSheep(int a_Color = -1); + + CLASS_PROTODEF(cSheep) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); } + + /** Generates a random color for the sheep like the vanilla server. + The percent's where used are from the wiki: http://minecraft.gamepedia.com/Sheep#Breeding */ + static NIBBLETYPE GenerateNaturalRandomColor(void); + + bool IsSheared(void) const { return m_IsSheared; } + void SetSheared(bool a_IsSheared) { m_IsSheared = a_IsSheared; } + + int GetFurColor(void) const { return m_WoolColor; } + void SetFurColor(int a_WoolColor) { m_WoolColor = a_WoolColor; } + +private: + bool m_IsSheared; + int m_WoolColor; + int m_TimeToStopEating; + +} ; + + + + diff --git a/src/Mobs/Old Mobs/Silverfish.h b/src/Mobs/Old Mobs/Silverfish.h new file mode 100644 index 000000000..2df333dbc --- /dev/null +++ b/src/Mobs/Old Mobs/Silverfish.h @@ -0,0 +1,26 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cSilverfish : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cSilverfish(void) : + super("Silverfish", mtSilverfish, "mob.silverfish.hit", "mob.silverfish.kill", 0.3, 0.7) + { + } + + CLASS_PROTODEF(cSilverfish) +} ; + + + + diff --git a/src/Mobs/Old Mobs/Skeleton.cpp b/src/Mobs/Old Mobs/Skeleton.cpp new file mode 100644 index 000000000..cd707f4bb --- /dev/null +++ b/src/Mobs/Old Mobs/Skeleton.cpp @@ -0,0 +1,107 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Skeleton.h" +#include "../World.h" +#include "../Entities/ArrowEntity.h" +#include "ClientHandle.h" + + + + +cSkeleton::cSkeleton(bool IsWither) : + super("Skeleton", mtSkeleton, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8), + m_bIsWither(IsWither) +{ + SetBurnsInDaylight(true); +} + + + + + +void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + 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); +} + + + + + +void cSkeleton::MoveToPosition(const Vector3d & a_Position) +{ + // If the destination is sufficiently skylight challenged AND the skeleton isn't on fire then block the movement + if ( + !IsOnFire() && + (m_World->GetBlockSkyLight((int)floor(a_Position.x), (int)floor(a_Position.y), (int)floor(a_Position.z)) - m_World->GetSkyDarkness() > 8) + ) + { + m_bMovingToDestination = false; + return; + } + + super::MoveToPosition(a_Position); +} + + + + + +void cSkeleton::Attack(float a_Dt) +{ + m_AttackInterval += a_Dt * m_AttackRate; + + if (m_Target != NULL && m_AttackInterval > 3.0) + { + // Setting this higher gives us more wiggle room for attackrate + Vector3d Speed = GetLookVector() * 20; + Speed.y = Speed.y + 1; + cArrowEntity * Arrow = new cArrowEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); + if (Arrow == NULL) + { + return; + } + if (!Arrow->Initialize(*m_World)) + { + delete Arrow; + Arrow = NULL; + return; + } + m_World->BroadcastSpawnEntity(*Arrow); + m_AttackInterval = 0.0; + } +} + + + + + +void cSkeleton::SpawnOn(cClientHandle & a_ClientHandle) +{ + super::SpawnOn(a_ClientHandle); + a_ClientHandle.SendEntityEquipment(*this, 0, cItem(E_ITEM_BOW)); +} + + + + diff --git a/src/Mobs/Old Mobs/Skeleton.h b/src/Mobs/Old Mobs/Skeleton.h new file mode 100644 index 000000000..577588b32 --- /dev/null +++ b/src/Mobs/Old Mobs/Skeleton.h @@ -0,0 +1,37 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cSkeleton : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cSkeleton(bool IsWither); + + CLASS_PROTODEF(cSkeleton) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void MoveToPosition(const Vector3d & a_Position) override; + virtual void Attack(float a_Dt) override; + virtual void SpawnOn(cClientHandle & a_ClientHandle) override; + + virtual bool IsUndead(void) override { return true; } + + bool IsWither(void) const { return m_bIsWither; } + +private: + + bool m_bIsWither; + +} ; + + + + diff --git a/src/Mobs/Old Mobs/Slime.cpp b/src/Mobs/Old Mobs/Slime.cpp new file mode 100644 index 000000000..b709ec664 --- /dev/null +++ b/src/Mobs/Old Mobs/Slime.cpp @@ -0,0 +1,106 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Slime.h" +#include "FastRandom.h" +#include "World.h" + + + + + +cSlime::cSlime(int a_Size) : + super("Slime", + mtSlime, + Printf("mob.slime.%s", GetSizeName(a_Size).c_str()), + Printf("mob.slime.%s", 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); +} + + + + + +void cSlime::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + 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); + } +} + + + + + +void cSlime::Attack(float a_Dt) +{ + if (m_Size > 1) + { + // Only slimes larger than size 1 attack a player. + super::Attack(a_Dt); + } +} + + + + + +void cSlime::KilledBy(TakeDamageInfo & a_TDI) +{ + if (GetHealth() > 0) + { + return; + } + + if (m_Size != 1) + { + cFastRandom Random; + int SpawnAmount = 2 + Random.NextInt(3); + + 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; + + cSlime * NewSlime = new cSlime(m_Size / 2); + NewSlime->SetPosition(GetPosX() + AddX, GetPosY() + 0.5, GetPosZ() + AddZ); + NewSlime->SetYaw(Random.NextFloat(1.0f) * 360.0f); + m_World->SpawnMobFinalize(NewSlime); + } + } + super::KilledBy(a_TDI); +} + + + + + +const AString cSlime::GetSizeName(int a_Size) const +{ + if (a_Size > 1) + { + return "big"; + } + else + { + return "small"; + } +} + + + + diff --git a/src/Mobs/Old Mobs/Slime.h b/src/Mobs/Old Mobs/Slime.h new file mode 100644 index 000000000..f0b800f94 --- /dev/null +++ b/src/Mobs/Old Mobs/Slime.h @@ -0,0 +1,41 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cSlime : + public cAggressiveMonster +{ + 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); + + CLASS_PROTODEF(cSlime) + + // cAggressiveMonster overrides: + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void Attack(float a_Dt) override; + virtual void KilledBy(TakeDamageInfo & a_TDI) override; + + 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". */ + const AString GetSizeName(int a_Size) const; + +protected: + + /** 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/Old Mobs/SnowGolem.cpp b/src/Mobs/Old Mobs/SnowGolem.cpp new file mode 100644 index 000000000..76334d970 --- /dev/null +++ b/src/Mobs/Old Mobs/SnowGolem.cpp @@ -0,0 +1,46 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "SnowGolem.h" +#include "../World.h" + + + + + +cSnowGolem::cSnowGolem(void) : + super("SnowGolem", mtSnowGolem, "", "", 0.4, 1.8) +{ +} + + + + + +void cSnowGolem::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + UNUSED(a_Killer); + AddRandomDropItem(a_Drops, 0, 15, E_ITEM_SNOWBALL); +} + + + + + +void cSnowGolem::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + if (IsBiomeNoDownfall(m_World->GetBiomeAt((int) floor(GetPosX()), (int) floor(GetPosZ())))) + { + TakeDamage(*this); + } + else + { + BLOCKTYPE BlockBelow = m_World->GetBlock((int) floor(GetPosX()), (int) floor(GetPosY()) - 1, (int) floor(GetPosZ())); + BLOCKTYPE Block = m_World->GetBlock((int) floor(GetPosX()), (int) floor(GetPosY()), (int) floor(GetPosZ())); + if (Block == E_BLOCK_AIR && cBlockInfo::IsSolid(BlockBelow)) + { + m_World->SetBlock((int) floor(GetPosX()), (int) floor(GetPosY()), (int) floor(GetPosZ()), E_BLOCK_SNOW, 0); + } + } +} diff --git a/src/Mobs/Old Mobs/SnowGolem.h b/src/Mobs/Old Mobs/SnowGolem.h new file mode 100644 index 000000000..aba89e52d --- /dev/null +++ b/src/Mobs/Old Mobs/SnowGolem.h @@ -0,0 +1,26 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cSnowGolem : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cSnowGolem(void); + + CLASS_PROTODEF(cSnowGolem) + + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; +} ; + + + + diff --git a/src/Mobs/Old Mobs/Spider.cpp b/src/Mobs/Old Mobs/Spider.cpp new file mode 100644 index 000000000..8b978ff6b --- /dev/null +++ b/src/Mobs/Old Mobs/Spider.cpp @@ -0,0 +1,35 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Spider.h" + + + + + +cSpider::cSpider(void) : + super("Spider", mtSpider, "mob.spider.say", "mob.spider.death", 1.4, 0.9) +{ +} + + + + + +void cSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STRING); + if ((a_Killer != NULL) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) + { + AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_SPIDER_EYE); + } +} + + + + diff --git a/src/Mobs/Old Mobs/Spider.h b/src/Mobs/Old Mobs/Spider.h new file mode 100644 index 000000000..813d2e266 --- /dev/null +++ b/src/Mobs/Old Mobs/Spider.h @@ -0,0 +1,25 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cSpider : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cSpider(void); + + CLASS_PROTODEF(cSpider) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; +} ; + + + + diff --git a/src/Mobs/Old Mobs/Squid.cpp b/src/Mobs/Old Mobs/Squid.cpp new file mode 100644 index 000000000..bd0e141a0 --- /dev/null +++ b/src/Mobs/Old Mobs/Squid.cpp @@ -0,0 +1,62 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Squid.h" +#include "../Vector3.h" +#include "../Chunk.h" + + + + + +cSquid::cSquid(void) : + super("Squid", mtSquid, "", "", 0.95, 0.95) +{ +} + + + + + +void cSquid::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + // Drops 0-3 Ink Sacs + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 3 + LootingLevel, E_ITEM_DYE, E_META_DYE_BLACK); +} + + + + + +void cSquid::Tick(float a_Dt, cChunk & a_Chunk) +{ + // We must first process current location, and only then tick, otherwise we risk processing a location in a chunk + // that is not where the entity currently resides (FS #411) + + Vector3d Pos = GetPosition(); + + // TODO: Not a real behavior, but cool :D + int RelY = (int)floor(Pos.y); + if ((RelY < 0) || (RelY >= cChunkDef::Height)) + { + return; + } + int RelX = (int)floor(Pos.x) - a_Chunk.GetPosX() * cChunkDef::Width; + int RelZ = (int)floor(Pos.z) - a_Chunk.GetPosZ() * cChunkDef::Width; + BLOCKTYPE BlockType; + if (a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockType) && !IsBlockWater(BlockType) && !IsOnFire()) + { + // Burn for 10 ticks, then decide again + StartBurning(10); + } + + super::Tick(a_Dt, a_Chunk); +} + + + diff --git a/src/Mobs/Old Mobs/Squid.h b/src/Mobs/Old Mobs/Squid.h new file mode 100644 index 000000000..b57340427 --- /dev/null +++ b/src/Mobs/Old Mobs/Squid.h @@ -0,0 +1,31 @@ + +#pragma once + +#include "PassiveMonster.h" + + + + + +class cSquid : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + cSquid(); + + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + + CLASS_PROTODEF(cSquid) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + + // Squids do not drown (or float) + virtual void HandleAir(void) override {} + virtual void SetSwimState(cChunk & a_Chunk) override {} +} ; + + + + diff --git a/src/Mobs/Old Mobs/Villager.cpp b/src/Mobs/Old Mobs/Villager.cpp new file mode 100644 index 000000000..1cdac7c74 --- /dev/null +++ b/src/Mobs/Old Mobs/Villager.cpp @@ -0,0 +1,197 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Villager.h" +#include "../World.h" +#include "../BlockArea.h" +#include "../Blocks/BlockHandler.h" +#include "../BlockInServerPluginInterface.h" + + + + + +cVillager::cVillager(eVillagerType VillagerType) : + super("Villager", mtVillager, "", "", 0.6, 1.8), + m_ActionCountDown(-1), + m_Type(VillagerType), + m_VillagerAction(false) +{ +} + + + + + +bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) +{ + if (!super::DoTakeDamage(a_TDI)) + { + return false; + } + + if ((a_TDI.Attacker != NULL) && a_TDI.Attacker->IsPlayer()) + { + if (m_World->GetTickRandomNumber(5) == 3) + { + m_World->BroadcastEntityStatus(*this, esVillagerAngry); + } + } + return true; +} + + + + + +void cVillager::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if (m_ActionCountDown > -1) + { + m_ActionCountDown--; + if (m_ActionCountDown == 0) + { + switch (m_Type) + { + case vtFarmer: + { + HandleFarmerPlaceCrops(); + } + } + } + return; + } + + if (m_VillagerAction) + { + switch (m_Type) + { + case vtFarmer: + { + HandleFarmerTryHarvestCrops(); + } + } + m_VillagerAction = false; + return; + } + + // Don't always try to do a special action. Each tick has 1% to do a special action. + if (m_World->GetTickRandomNumber(99) != 0) + { + return; + } + + switch (m_Type) + { + case vtFarmer: + { + HandleFarmerPrepareFarmCrops(); + } + } +} + + + + +//////////////////////////////////////////////////////////////////////////////// +// Farmer functions. +void cVillager::HandleFarmerPrepareFarmCrops() +{ + if (!m_World->VillagersShouldHarvestCrops()) + { + return; + } + + cBlockArea Surrounding; + /// Read a 11x7x11 area. + Surrounding.Read( + m_World, + (int) GetPosX() - 5, + (int) GetPosX() + 5, + (int) GetPosY() - 3, + (int) GetPosY() + 3, + (int) GetPosZ() - 5, + (int) GetPosZ() + 5 + ); + + for (int I = 0; I < 5; I++) + { + for (int Y = 0; Y < 6; Y++) + { + // Pick random coordinates and check for crops. + int X = m_World->GetTickRandomNumber(11); + int Z = m_World->GetTickRandomNumber(11); + + // A villager can't farm this. + if (!IsBlockFarmable(Surrounding.GetRelBlockType(X, Y, Z))) + { + continue; + } + if (Surrounding.GetRelBlockMeta(X, Y, Z) != 0x7) + { + continue; + } + + m_VillagerAction = true; + m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); + MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5))); + return; + } // for Y loop. + } // Repeat the procces 5 times. +} + + + + + +void cVillager::HandleFarmerTryHarvestCrops() +{ + // Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks. + if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2) + { + // Check if the blocks didn't change while the villager was walking to the coordinates. + BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7) + { + cBlockHandler * Handler = cBlockInfo::GetHandler(CropBlock); + cChunkInterface ChunkInterface(m_World->GetChunkMap()); + cBlockInServerPluginInterface PluginInterface(*m_World); + Handler->DropBlock(ChunkInterface, *m_World, PluginInterface, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0); + m_ActionCountDown = 20; + } + } +} + + + + +void cVillager::HandleFarmerPlaceCrops() +{ + // Check if there is still farmland at the spot where the crops were. + if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) + { + m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0); + } +} + + + + + +bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType) +{ + switch (a_BlockType) + { + case E_BLOCK_CROPS: + case E_BLOCK_POTATOES: + case E_BLOCK_CARROTS: + { + return true; + } + } + return false; +} + diff --git a/src/Mobs/Old Mobs/Villager.h b/src/Mobs/Old Mobs/Villager.h new file mode 100644 index 000000000..aa81f0790 --- /dev/null +++ b/src/Mobs/Old Mobs/Villager.h @@ -0,0 +1,66 @@ + +#pragma once + +#include "PassiveMonster.h" + + + + + +class cVillager : + public cPassiveMonster +{ + typedef cPassiveMonster super; + +public: + + enum eVillagerType + { + vtFarmer = 0, + vtLibrarian = 1, + vtPriest = 2, + vtBlacksmith = 3, + vtButcher = 4, + vtGeneric = 5, + vtMax + } ; + + cVillager(eVillagerType VillagerType); + + CLASS_PROTODEF(cVillager) + + // cEntity overrides + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; + virtual void Tick (float a_Dt, cChunk & a_Chunk) override; + + // cVillager functions + /** return true if the given blocktype are: crops, potatoes or carrots.*/ + bool IsBlockFarmable(BLOCKTYPE a_BlockType); + + // Farmer functions + /** Searches in a 11x7x11 area for crops. If it found some it will navigate to them.*/ + void HandleFarmerPrepareFarmCrops(); + + /** Looks if the farmer has reached it's destination, and if it's still crops and the destination is closer then 2 blocks it will harvest them.*/ + void HandleFarmerTryHarvestCrops(); + + /** Replaces the crops he harvested.*/ + void HandleFarmerPlaceCrops(); + + // Get and set functions. + int GetVilType(void) const { return m_Type; } + Vector3i GetCropsPos(void) const { return m_CropsPos; } + bool DoesHaveActionActivated(void) const { return m_VillagerAction; } + +private: + + int m_ActionCountDown; + int m_Type; + bool m_VillagerAction; + Vector3i m_CropsPos; + +} ; + + + + diff --git a/src/Mobs/Old Mobs/Witch.cpp b/src/Mobs/Old Mobs/Witch.cpp new file mode 100644 index 000000000..6956f7b7a --- /dev/null +++ b/src/Mobs/Old Mobs/Witch.cpp @@ -0,0 +1,47 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Witch.h" + + + + + +cWitch::cWitch(void) : + super("Witch", mtWitch, "", "", 0.6, 1.8) +{ +} + + + + + +void cWitch::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + MTRand r1; + int DropTypeCount = (r1.randInt() % 3) + 1; + for (int i = 0; i < DropTypeCount; i++) + { + int DropType = r1.randInt() % 7; + switch (DropType) + { + case 0: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GLASS_BOTTLE); break; + case 1: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GLOWSTONE_DUST); break; + case 2: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER); break; + case 3: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_REDSTONE_DUST); break; + case 4: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SPIDER_EYE); break; + case 5: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STICK); break; + case 6: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SUGAR); break; + } + } + AddRandomWeaponDropItem(a_Drops, LootingLevel); +} + + + + diff --git a/src/Mobs/Old Mobs/Witch.h b/src/Mobs/Old Mobs/Witch.h new file mode 100644 index 000000000..bd059f61d --- /dev/null +++ b/src/Mobs/Old Mobs/Witch.h @@ -0,0 +1,28 @@ + +#pragma once + +#include "AggressiveMonster.h" +#include "../MersenneTwister.h" + + + + + +class cWitch : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cWitch(); + + CLASS_PROTODEF(cWitch) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + + bool IsAngry(void) const {return ((m_EMState == ATTACKING) || (m_EMState == CHASING)); } +} ; + + + + diff --git a/src/Mobs/Old Mobs/Wither.cpp b/src/Mobs/Old Mobs/Wither.cpp new file mode 100644 index 000000000..578b47995 --- /dev/null +++ b/src/Mobs/Old Mobs/Wither.cpp @@ -0,0 +1,136 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Wither.h" + +#include "../World.h" +#include "../Entities/Player.h" + + + + + +cWither::cWither(void) : + super("Wither", mtWither, "mob.wither.hurt", "mob.wither.death", 0.9, 4.0), + m_WitherInvulnerableTicks(220) +{ + SetMaxHealth(300); +} + + + + + +bool cWither::IsArmored(void) const +{ + return GetHealth() <= (GetMaxHealth() / 2); +} + + + + + +bool cWither::Initialize(cWorld & a_World) +{ + // Set health before BroadcastSpawnEntity() + SetHealth(GetMaxHealth() / 3); + + return super::Initialize(a_World); +} + + + + + +bool cWither::DoTakeDamage(TakeDamageInfo & a_TDI) +{ + if (a_TDI.DamageType == dtDrowning) + { + return false; + } + + if (m_WitherInvulnerableTicks > 0) + { + return false; + } + + if (IsArmored() && (a_TDI.DamageType == dtRangedAttack)) + { + return false; + } + + return super::DoTakeDamage(a_TDI); +} + + + + + +void cWither::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if (m_WitherInvulnerableTicks > 0) + { + unsigned int NewTicks = m_WitherInvulnerableTicks - 1; + + if (NewTicks == 0) + { + m_World->DoExplosionAt(7.0, GetPosX(), GetPosY(), GetPosZ(), false, esWitherBirth, this); + } + + m_WitherInvulnerableTicks = NewTicks; + + if ((NewTicks % 10) == 0) + { + Heal(10); + } + } + + m_World->BroadcastEntityMetadata(*this); +} + + + + + +void cWither::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + AddRandomDropItem(a_Drops, 1, 1, E_ITEM_NETHER_STAR); +} + + + + + +void cWither::KilledBy(TakeDamageInfo & a_TDI) +{ + super::KilledBy(a_TDI); + + class cPlayerCallback : public cPlayerListCallback + { + Vector3f m_Pos; + + virtual bool Item(cPlayer * a_Player) + { + // TODO 2014-05-21 xdot: Vanilla minecraft uses an AABB check instead of a radius one + double Dist = (a_Player->GetPosition() - m_Pos).Length(); + if (Dist < 50.0) + { + // If player is close, award achievement + a_Player->AwardAchievement(achKillWither); + } + return false; + } + + public: + cPlayerCallback(const Vector3f & a_Pos) : m_Pos(a_Pos) {} + + } PlayerCallback(GetPosition()); + + m_World->ForEachPlayer(PlayerCallback); +} + + + + diff --git a/src/Mobs/Old Mobs/Wither.h b/src/Mobs/Old Mobs/Wither.h new file mode 100644 index 000000000..2403823ed --- /dev/null +++ b/src/Mobs/Old Mobs/Wither.h @@ -0,0 +1,45 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cWither : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cWither(void); + + CLASS_PROTODEF(cWither) + + unsigned int GetWitherInvulnerableTicks(void) const { return m_WitherInvulnerableTicks; } + + void SetWitherInvulnerableTicks(unsigned int a_Ticks) { m_WitherInvulnerableTicks = a_Ticks; } + + /** Returns whether the wither is invulnerable to arrows. */ + bool IsArmored(void) const; + + // cEntity overrides + virtual bool Initialize(cWorld & a_World) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + virtual void KilledBy(TakeDamageInfo & a_TDI) override; + + virtual bool IsUndead(void) override { return true; } + +private: + + /** The number of ticks of invulnerability left after being initially created. Zero once invulnerability has expired. */ + unsigned int m_WitherInvulnerableTicks; + +} ; + + + + diff --git a/src/Mobs/Old Mobs/Wolf.cpp b/src/Mobs/Old Mobs/Wolf.cpp new file mode 100644 index 000000000..4fe1ff1d6 --- /dev/null +++ b/src/Mobs/Old Mobs/Wolf.cpp @@ -0,0 +1,246 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Wolf.h" +#include "../World.h" +#include "../Entities/Player.h" +#include "../Items/ItemHandler.h" + + + + + +cWolf::cWolf(void) : + super("Wolf", mtWolf, "mob.wolf.hurt", "mob.wolf.death", 0.6, 0.8), + m_IsSitting(false), + m_IsTame(false), + m_IsBegging(false), + m_IsAngry(false), + m_OwnerName(""), + m_CollarColor(14) +{ +} + + + + + +bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI) +{ + if (super::DoTakeDamage(a_TDI)) + { + return false; + } + + if (!m_IsTame) + { + m_IsAngry = true; + } + m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face + return true; +} + + + + +void cWolf::Attack(float a_Dt) +{ + UNUSED(a_Dt); + + if ((m_Target != NULL) && (m_Target->IsPlayer())) + { + if (((cPlayer *)m_Target)->GetName() != m_OwnerName) + { + super::Attack(a_Dt); + } + } + else + { + super::Attack(a_Dt); + } +} + + + + + +void cWolf::OnRightClicked(cPlayer & a_Player) +{ + if (!IsTame() && !IsAngry()) + { + // If the player is holding a bone, try to tame the wolf: + if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_BONE) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + + if (m_World->GetTickRandomNumber(7) == 0) + { + // Taming succeeded + SetMaxHealth(20); + SetIsTame(true); + SetOwner(a_Player.GetName(), a_Player.GetUUID()); + m_World->BroadcastEntityStatus(*this, esWolfTamed); + m_World->BroadcastParticleEffect("heart", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); + } + else + { + // Taming failed + m_World->BroadcastEntityStatus(*this, esWolfTaming); + m_World->BroadcastParticleEffect("smoke", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); + } + } + } + else if (IsTame()) + { + // Feed the wolf, restoring its health, or dye its collar: + switch (a_Player.GetEquippedItem().m_ItemType) + { + 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(a_Player.GetEquippedItem().m_ItemType)->GetFoodInfo().FoodLevel); + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + } + break; + } + case E_ITEM_DYE: + { + if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog? + { + SetCollarColor(15 - a_Player.GetEquippedItem().m_ItemDamage); + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + } + break; + } + default: + { + if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog? + { + SetIsSitting(!IsSitting()); + } + } + } + } + + m_World->BroadcastEntityMetadata(*this); +} + + + + + +void cWolf::Tick(float a_Dt, cChunk & a_Chunk) +{ + if (!IsAngry()) + { + cMonster::Tick(a_Dt, a_Chunk); + } + else + { + super::Tick(a_Dt, a_Chunk); + } + + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + if (a_Closest_Player != NULL) + { + 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); + } + } + } + } + + if (IsTame() && !IsSitting()) + { + TickFollowPlayer(); + } + else if (IsSitting()) + { + m_bMovingToDestination = false; + } +} + + + + + +void cWolf::TickFollowPlayer() +{ + class cCallback : + public cPlayerListCallback + { + virtual bool Item(cPlayer * a_Player) override + { + OwnerPos = a_Player->GetPosition(); + return false; + } + public: + Vector3d OwnerPos; + } Callback; + + if (m_World->DoWithPlayer(m_OwnerName, Callback)) + { + // The player is present in the world, follow him: + double Distance = (Callback.OwnerPos - GetPosition()).Length(); + if (Distance > 30) + { + Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z); + TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z); + } + else + { + MoveToPosition(Callback.OwnerPos); + } + } +} + + + + diff --git a/src/Mobs/Old Mobs/Wolf.h b/src/Mobs/Old Mobs/Wolf.h new file mode 100644 index 000000000..7500854f8 --- /dev/null +++ b/src/Mobs/Old Mobs/Wolf.h @@ -0,0 +1,61 @@ + +#pragma once + +#include "PassiveAggressiveMonster.h" +#include "../Entities/Entity.h" + + + + + +class cWolf : + public cPassiveAggressiveMonster +{ + typedef cPassiveAggressiveMonster super; + +public: + cWolf(void); + + CLASS_PROTODEF(cWolf) + + virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + virtual void TickFollowPlayer(); + virtual void Attack(float a_Dt) override; + + // Get functions + bool IsSitting (void) const { return m_IsSitting; } + bool IsTame (void) const { 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; + } + +protected: + + bool m_IsSitting; + bool m_IsTame; + bool m_IsBegging; + bool m_IsAngry; + AString m_OwnerName; + AString m_OwnerUUID; + int m_CollarColor; +} ; + + + + diff --git a/src/Mobs/Old Mobs/Zombie.cpp b/src/Mobs/Old Mobs/Zombie.cpp new file mode 100644 index 000000000..30225c32d --- /dev/null +++ b/src/Mobs/Old Mobs/Zombie.cpp @@ -0,0 +1,62 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Zombie.h" +#include "../World.h" +#include "../LineBlockTracer.h" + + + + + +cZombie::cZombie(bool a_IsVillagerZombie) : + super("Zombie", mtZombie, "mob.zombie.hurt", "mob.zombie.death", 0.6, 1.8), + m_IsVillagerZombie(a_IsVillagerZombie), + m_IsConverting(false) +{ + SetBurnsInDaylight(true); +} + + + + + +void cZombie::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ROTTEN_FLESH); + cItems RareDrops; + RareDrops.Add(cItem(E_ITEM_IRON)); + RareDrops.Add(cItem(E_ITEM_CARROT)); + RareDrops.Add(cItem(E_ITEM_POTATO)); + AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); + AddRandomArmorDropItem(a_Drops, LootingLevel); + AddRandomWeaponDropItem(a_Drops, LootingLevel); +} + + + + + +void cZombie::MoveToPosition(const Vector3d & a_Position) +{ + // If the destination is sufficiently skylight challenged AND the skeleton isn't on fire then block the movement + if ( + !IsOnFire() && + (m_World->GetBlockSkyLight((int)floor(a_Position.x), (int)floor(a_Position.y), (int)floor(a_Position.z)) - m_World->GetSkyDarkness() > 8) + ) + { + m_bMovingToDestination = false; + return; + } + + super::MoveToPosition(a_Position); +} + + + + diff --git a/src/Mobs/Old Mobs/Zombie.h b/src/Mobs/Old Mobs/Zombie.h new file mode 100644 index 000000000..118b6e6e7 --- /dev/null +++ b/src/Mobs/Old Mobs/Zombie.h @@ -0,0 +1,36 @@ +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cZombie : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cZombie(bool a_IsVillagerZombie); + + CLASS_PROTODEF(cZombie) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void MoveToPosition(const Vector3d & a_Position) override; + + virtual bool IsUndead(void) override { return true; } + + bool IsVillagerZombie(void) const { return m_IsVillagerZombie; } + bool IsConverting (void) const { return m_IsConverting; } + +private: + + bool m_IsVillagerZombie; + bool m_IsConverting; + +} ; + + + + diff --git a/src/Mobs/Old Mobs/ZombiePigman.cpp b/src/Mobs/Old Mobs/ZombiePigman.cpp new file mode 100644 index 000000000..05350f877 --- /dev/null +++ b/src/Mobs/Old Mobs/ZombiePigman.cpp @@ -0,0 +1,53 @@ +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "ZombiePigman.h" +#include "../World.h" + + + + + +cZombiePigman::cZombiePigman(void) : + super("ZombiePigman", mtZombiePigman, "mob.zombiepig.zpighurt", "mob.zombiepig.zpigdeath", 0.6, 1.8) +{ +} + + + + + +void cZombiePigman::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_ROTTEN_FLESH); + AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_GOLD_NUGGET); + + cItems RareDrops; + RareDrops.Add(cItem(E_ITEM_GOLD)); + AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); + AddRandomArmorDropItem(a_Drops, LootingLevel); + AddRandomWeaponDropItem(a_Drops, LootingLevel); +} + + + + + +void cZombiePigman::KilledBy(TakeDamageInfo & a_TDI) +{ + super::KilledBy(a_TDI); + + if ((a_TDI.Attacker != NULL) && (a_TDI.Attacker->IsPlayer())) + { + // TODO: Anger all nearby zombie pigmen + // TODO: In vanilla, if one player angers ZPs, do they attack any nearby player, or only that one attacker? + } +} + + + + diff --git a/src/Mobs/Old Mobs/ZombiePigman.h b/src/Mobs/Old Mobs/ZombiePigman.h new file mode 100644 index 000000000..bae0115eb --- /dev/null +++ b/src/Mobs/Old Mobs/ZombiePigman.h @@ -0,0 +1,27 @@ +#pragma once + +#include "PassiveAggressiveMonster.h" + + + + + +class cZombiePigman : + public cPassiveAggressiveMonster +{ + typedef cPassiveAggressiveMonster super; + +public: + cZombiePigman(void); + + CLASS_PROTODEF(cZombiePigman) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void KilledBy(TakeDamageInfo & a_TDI) override; + + virtual bool IsUndead(void) override { return true; } +} ; + + + + diff --git a/src/Mobs/PassiveAggressiveMonster.cpp b/src/Mobs/PassiveAggressiveMonster.cpp deleted file mode 100644 index 24501b1ba..000000000 --- a/src/Mobs/PassiveAggressiveMonster.cpp +++ /dev/null @@ -1,41 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "PassiveAggressiveMonster.h" - -#include "../Entities/Player.h" - - - - - -cPassiveAggressiveMonster::cPassiveAggressiveMonster(const AString & a_ConfigName, eType 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_EMPersonality = PASSIVE; -} - - - - - -bool cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI) -{ - if (!super::DoTakeDamage(a_TDI)) - { - return false; - } - - if ((m_Target != NULL) && (m_Target->IsPlayer())) - { - if (!((cPlayer *)m_Target)->IsGameModeCreative()) - { - m_EMState = CHASING; - } - } - return true; -} - - - - diff --git a/src/Mobs/PassiveAggressiveMonster.h b/src/Mobs/PassiveAggressiveMonster.h deleted file mode 100644 index a0da50e8e..000000000 --- a/src/Mobs/PassiveAggressiveMonster.h +++ /dev/null @@ -1,23 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cPassiveAggressiveMonster : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cPassiveAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); - - virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; -} ; - - - - diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp deleted file mode 100644 index 2861d7314..000000000 --- a/src/Mobs/PassiveMonster.cpp +++ /dev/null @@ -1,65 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "PassiveMonster.h" -#include "../World.h" -#include "../Entities/Player.h" - - - - -cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eType 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_EMPersonality = PASSIVE; -} - - - - - -bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI) -{ - if (!super::DoTakeDamage(a_TDI)) - { - return false; - } - if ((a_TDI.Attacker != this) && (a_TDI.Attacker != NULL)) - { - m_EMState = ESCAPING; - } - return true; -} - - - - - -void cPassiveMonster::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - if (m_EMState == ESCAPING) - { - CheckEventLostPlayer(); - } - cItem FollowedItem = GetFollowedItem(); - if (FollowedItem.IsEmpty()) - { - return; - } - cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); - if (a_Closest_Player != NULL) - { - if (a_Closest_Player->GetEquippedItem().IsEqual(FollowedItem)) - { - Vector3d PlayerPos = a_Closest_Player->GetPosition(); - MoveToPosition(PlayerPos); - } - } -} - - - - - diff --git a/src/Mobs/PassiveMonster.h b/src/Mobs/PassiveMonster.h deleted file mode 100644 index 70574585a..000000000 --- a/src/Mobs/PassiveMonster.h +++ /dev/null @@ -1,30 +0,0 @@ - -#pragma once - -#include "Monster.h" - - - - - -class cPassiveMonster : - public cMonster -{ - typedef cMonster super; - -public: - cPassiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); - - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - - /// When hit by someone, run away - virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; - /** Returns the item that the animal of this class follows when a player holds it in hand - Return an empty item not to follow (default). */ - virtual const cItem GetFollowedItem(void) const { return cItem(); } - -} ; - - - - diff --git a/src/Mobs/Pig.cpp b/src/Mobs/Pig.cpp deleted file mode 100644 index 1f77cf613..000000000 --- a/src/Mobs/Pig.cpp +++ /dev/null @@ -1,100 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Pig.h" -#include "../Entities/Player.h" -#include "../World.h" - - - - - -cPig::cPig(void) : - super("Pig", mtPig, "mob.pig.say", "mob.pig.death", 0.9, 0.9), - m_bIsSaddled(false) -{ -} - - - - - -void cPig::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_COOKED_PORKCHOP : E_ITEM_RAW_PORKCHOP); - if (m_bIsSaddled) - { - a_Drops.push_back(cItem(E_ITEM_SADDLE, 1)); - } -} - - - - - -void cPig::OnRightClicked(cPlayer & a_Player) -{ - if (m_bIsSaddled) - { - if (m_Attachee != NULL) - { - if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) - { - // This player is already sitting in, they want out. - a_Player.Detach(); - return; - } - - if (m_Attachee->IsPlayer()) - { - // Another player is already sitting in here, cannot attach - return; - } - - // Detach whatever is sitting in this pig now: - m_Attachee->Detach(); - } - - // Attach the player to this pig - a_Player.AttachTo(this); - } - else if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_SADDLE) - { - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - } - - // Set saddle state & broadcast metadata - m_bIsSaddled = true; - m_World->BroadcastEntityMetadata(*this); - } -} - - - - - -void cPig::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - // If the attachee player is holding a carrot-on-stick, let them drive this pig: - if (m_bIsSaddled && (m_Attachee != NULL)) - { - if (m_Attachee->IsPlayer() && (m_Attachee->GetEquippedWeapon().m_ItemType == E_ITEM_CARROT_ON_STICK)) - { - MoveToPosition((m_Attachee->GetPosition()) + (m_Attachee->GetLookVector()*10)); - m_bMovingToDestination = true; - } - } -} - - - - diff --git a/src/Mobs/Pig.h b/src/Mobs/Pig.h deleted file mode 100644 index 534a0ca6f..000000000 --- a/src/Mobs/Pig.h +++ /dev/null @@ -1,36 +0,0 @@ - -#pragma once - -#include "PassiveMonster.h" - - - - - -class cPig : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - cPig(void); - - CLASS_PROTODEF(cPig) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void OnRightClicked(cPlayer & a_Player) override; - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - - virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_CARROT); } - - bool IsSaddled(void) const { return m_bIsSaddled; } - -private: - - bool m_bIsSaddled; - -} ; - - - - diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp deleted file mode 100644 index 9fb47201d..000000000 --- a/src/Mobs/Sheep.cpp +++ /dev/null @@ -1,154 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Sheep.h" -#include "../BlockID.h" -#include "../Entities/Player.h" -#include "../World.h" -#include "FastRandom.h" - - - - - -cSheep::cSheep(int a_Color) : - super("Sheep", mtSheep, "mob.sheep.say", "mob.sheep.say", 0.6, 1.3), - m_IsSheared(false), - m_WoolColor(a_Color), - m_TimeToStopEating(-1) -{ - // Generate random wool color. - if (m_WoolColor == -1) - { - m_WoolColor = GenerateNaturalRandomColor(); - } - - if ((m_WoolColor < 0) || (m_WoolColor > 15)) - { - m_WoolColor = 0; - } -} - - - - - -void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - if (!m_IsSheared) - { - a_Drops.push_back(cItem(E_BLOCK_WOOL, 1, m_WoolColor)); - } -} - - - - - -void cSheep::OnRightClicked(cPlayer & a_Player) -{ - const cItem & EquippedItem = a_Player.GetEquippedItem(); - if ((EquippedItem.m_ItemType == E_ITEM_SHEARS) && !IsSheared() && !IsBaby()) - { - m_IsSheared = true; - m_World->BroadcastEntityMetadata(*this); - a_Player.UseEquippedItem(); - - cItems Drops; - int NumDrops = m_World->GetTickRandomNumber(2) + 1; - Drops.push_back(cItem(E_BLOCK_WOOL, NumDrops, m_WoolColor)); - m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); - m_World->BroadcastSoundEffect("mob.sheep.shear", GetPosX(), GetPosY(), GetPosZ(), 1.0f, 1.0f); - } - else if ((EquippedItem.m_ItemType == E_ITEM_DYE) && (m_WoolColor != 15 - EquippedItem.m_ItemDamage)) - { - m_WoolColor = 15 - EquippedItem.m_ItemDamage; - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - } - m_World->BroadcastEntityMetadata(*this); - } -} - - - - - -void cSheep::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - int PosX = POSX_TOINT; - int PosY = POSY_TOINT - 1; - int PosZ = POSZ_TOINT; - - if ((PosY <= 0) || (PosY > cChunkDef::Height)) - { - return; - } - - if (m_TimeToStopEating > 0) - { - m_bMovingToDestination = false; // The sheep should not move when he's eating - m_TimeToStopEating--; - - if (m_TimeToStopEating == 0) - { - if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS) // Make sure grass hasn't been destroyed in the meantime - { - // The sheep ate the grass so we change it to dirt - m_World->SetBlock(PosX, PosY, PosZ, E_BLOCK_DIRT, 0); - GetWorld()->BroadcastSoundParticleEffect(2001, PosX, PosY, PosX, E_BLOCK_GRASS); - m_IsSheared = false; - m_World->BroadcastEntityMetadata(*this); - } - } - } - else - { - if (m_World->GetTickRandomNumber(600) == 1) - { - if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS) - { - m_World->BroadcastEntityStatus(*this, esSheepEating); - m_TimeToStopEating = 40; - } - } - } -} - - - - - -NIBBLETYPE cSheep::GenerateNaturalRandomColor(void) -{ - cFastRandom Random; - int Chance = Random.NextInt(101); - - if (Chance <= 81) - { - return E_META_WOOL_WHITE; - } - else if (Chance <= 86) - { - return E_META_WOOL_BLACK; - } - else if (Chance <= 91) - { - return E_META_WOOL_GRAY; - } - else if (Chance <= 96) - { - return E_META_WOOL_LIGHTGRAY; - } - else if (Chance <= 99) - { - return E_META_WOOL_BROWN; - } - else - { - return E_META_WOOL_PINK; - } -} - diff --git a/src/Mobs/Sheep.h b/src/Mobs/Sheep.h deleted file mode 100644 index 28e1c7254..000000000 --- a/src/Mobs/Sheep.h +++ /dev/null @@ -1,50 +0,0 @@ - -#pragma once - -#include "PassiveMonster.h" - - - - - -class cSheep : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - - /** The number is the color of the sheep. - Use E_META_WOOL_* constants for the wool color. - If you type -1, the server will generate a random color - with the GenerateNaturalRandomColor() function. */ - cSheep(int a_Color = -1); - - CLASS_PROTODEF(cSheep) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void OnRightClicked(cPlayer & a_Player) override; - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - - virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); } - - /** Generates a random color for the sheep like the vanilla server. - The percent's where used are from the wiki: http://minecraft.gamepedia.com/Sheep#Breeding */ - static NIBBLETYPE GenerateNaturalRandomColor(void); - - bool IsSheared(void) const { return m_IsSheared; } - void SetSheared(bool a_IsSheared) { m_IsSheared = a_IsSheared; } - - int GetFurColor(void) const { return m_WoolColor; } - void SetFurColor(int a_WoolColor) { m_WoolColor = a_WoolColor; } - -private: - bool m_IsSheared; - int m_WoolColor; - int m_TimeToStopEating; - -} ; - - - - diff --git a/src/Mobs/Silverfish.h b/src/Mobs/Silverfish.h deleted file mode 100644 index 2df333dbc..000000000 --- a/src/Mobs/Silverfish.h +++ /dev/null @@ -1,26 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cSilverfish : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cSilverfish(void) : - super("Silverfish", mtSilverfish, "mob.silverfish.hit", "mob.silverfish.kill", 0.3, 0.7) - { - } - - CLASS_PROTODEF(cSilverfish) -} ; - - - - diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp deleted file mode 100644 index cd707f4bb..000000000 --- a/src/Mobs/Skeleton.cpp +++ /dev/null @@ -1,107 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Skeleton.h" -#include "../World.h" -#include "../Entities/ArrowEntity.h" -#include "ClientHandle.h" - - - - -cSkeleton::cSkeleton(bool IsWither) : - super("Skeleton", mtSkeleton, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8), - m_bIsWither(IsWither) -{ - SetBurnsInDaylight(true); -} - - - - - -void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - 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); -} - - - - - -void cSkeleton::MoveToPosition(const Vector3d & a_Position) -{ - // If the destination is sufficiently skylight challenged AND the skeleton isn't on fire then block the movement - if ( - !IsOnFire() && - (m_World->GetBlockSkyLight((int)floor(a_Position.x), (int)floor(a_Position.y), (int)floor(a_Position.z)) - m_World->GetSkyDarkness() > 8) - ) - { - m_bMovingToDestination = false; - return; - } - - super::MoveToPosition(a_Position); -} - - - - - -void cSkeleton::Attack(float a_Dt) -{ - m_AttackInterval += a_Dt * m_AttackRate; - - if (m_Target != NULL && m_AttackInterval > 3.0) - { - // Setting this higher gives us more wiggle room for attackrate - Vector3d Speed = GetLookVector() * 20; - Speed.y = Speed.y + 1; - cArrowEntity * Arrow = new cArrowEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed); - if (Arrow == NULL) - { - return; - } - if (!Arrow->Initialize(*m_World)) - { - delete Arrow; - Arrow = NULL; - return; - } - m_World->BroadcastSpawnEntity(*Arrow); - m_AttackInterval = 0.0; - } -} - - - - - -void cSkeleton::SpawnOn(cClientHandle & a_ClientHandle) -{ - 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 deleted file mode 100644 index 577588b32..000000000 --- a/src/Mobs/Skeleton.h +++ /dev/null @@ -1,37 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cSkeleton : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cSkeleton(bool IsWither); - - CLASS_PROTODEF(cSkeleton) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void MoveToPosition(const Vector3d & a_Position) override; - virtual void Attack(float a_Dt) override; - virtual void SpawnOn(cClientHandle & a_ClientHandle) override; - - virtual bool IsUndead(void) override { return true; } - - bool IsWither(void) const { return m_bIsWither; } - -private: - - bool m_bIsWither; - -} ; - - - - diff --git a/src/Mobs/Slime.cpp b/src/Mobs/Slime.cpp deleted file mode 100644 index b709ec664..000000000 --- a/src/Mobs/Slime.cpp +++ /dev/null @@ -1,106 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Slime.h" -#include "FastRandom.h" -#include "World.h" - - - - - -cSlime::cSlime(int a_Size) : - super("Slime", - mtSlime, - Printf("mob.slime.%s", GetSizeName(a_Size).c_str()), - Printf("mob.slime.%s", 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); -} - - - - - -void cSlime::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - 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); - } -} - - - - - -void cSlime::Attack(float a_Dt) -{ - if (m_Size > 1) - { - // Only slimes larger than size 1 attack a player. - super::Attack(a_Dt); - } -} - - - - - -void cSlime::KilledBy(TakeDamageInfo & a_TDI) -{ - if (GetHealth() > 0) - { - return; - } - - if (m_Size != 1) - { - cFastRandom Random; - int SpawnAmount = 2 + Random.NextInt(3); - - 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; - - cSlime * NewSlime = new cSlime(m_Size / 2); - NewSlime->SetPosition(GetPosX() + AddX, GetPosY() + 0.5, GetPosZ() + AddZ); - NewSlime->SetYaw(Random.NextFloat(1.0f) * 360.0f); - m_World->SpawnMobFinalize(NewSlime); - } - } - super::KilledBy(a_TDI); -} - - - - - -const AString cSlime::GetSizeName(int a_Size) const -{ - if (a_Size > 1) - { - return "big"; - } - else - { - return "small"; - } -} - - - - diff --git a/src/Mobs/Slime.h b/src/Mobs/Slime.h deleted file mode 100644 index f0b800f94..000000000 --- a/src/Mobs/Slime.h +++ /dev/null @@ -1,41 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cSlime : - public cAggressiveMonster -{ - 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); - - CLASS_PROTODEF(cSlime) - - // cAggressiveMonster overrides: - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void Attack(float a_Dt) override; - virtual void KilledBy(TakeDamageInfo & a_TDI) override; - - 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". */ - const AString GetSizeName(int a_Size) const; - -protected: - - /** 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/SnowGolem.cpp b/src/Mobs/SnowGolem.cpp deleted file mode 100644 index 76334d970..000000000 --- a/src/Mobs/SnowGolem.cpp +++ /dev/null @@ -1,46 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "SnowGolem.h" -#include "../World.h" - - - - - -cSnowGolem::cSnowGolem(void) : - super("SnowGolem", mtSnowGolem, "", "", 0.4, 1.8) -{ -} - - - - - -void cSnowGolem::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - UNUSED(a_Killer); - AddRandomDropItem(a_Drops, 0, 15, E_ITEM_SNOWBALL); -} - - - - - -void cSnowGolem::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - if (IsBiomeNoDownfall(m_World->GetBiomeAt((int) floor(GetPosX()), (int) floor(GetPosZ())))) - { - TakeDamage(*this); - } - else - { - BLOCKTYPE BlockBelow = m_World->GetBlock((int) floor(GetPosX()), (int) floor(GetPosY()) - 1, (int) floor(GetPosZ())); - BLOCKTYPE Block = m_World->GetBlock((int) floor(GetPosX()), (int) floor(GetPosY()), (int) floor(GetPosZ())); - if (Block == E_BLOCK_AIR && cBlockInfo::IsSolid(BlockBelow)) - { - m_World->SetBlock((int) floor(GetPosX()), (int) floor(GetPosY()), (int) floor(GetPosZ()), E_BLOCK_SNOW, 0); - } - } -} diff --git a/src/Mobs/SnowGolem.h b/src/Mobs/SnowGolem.h deleted file mode 100644 index aba89e52d..000000000 --- a/src/Mobs/SnowGolem.h +++ /dev/null @@ -1,26 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cSnowGolem : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cSnowGolem(void); - - CLASS_PROTODEF(cSnowGolem) - - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; -} ; - - - - diff --git a/src/Mobs/Spider.cpp b/src/Mobs/Spider.cpp deleted file mode 100644 index 8b978ff6b..000000000 --- a/src/Mobs/Spider.cpp +++ /dev/null @@ -1,35 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Spider.h" - - - - - -cSpider::cSpider(void) : - super("Spider", mtSpider, "mob.spider.say", "mob.spider.death", 1.4, 0.9) -{ -} - - - - - -void cSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STRING); - if ((a_Killer != NULL) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) - { - AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_SPIDER_EYE); - } -} - - - - diff --git a/src/Mobs/Spider.h b/src/Mobs/Spider.h deleted file mode 100644 index 813d2e266..000000000 --- a/src/Mobs/Spider.h +++ /dev/null @@ -1,25 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cSpider : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cSpider(void); - - CLASS_PROTODEF(cSpider) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; -} ; - - - - diff --git a/src/Mobs/Squid.cpp b/src/Mobs/Squid.cpp deleted file mode 100644 index bd0e141a0..000000000 --- a/src/Mobs/Squid.cpp +++ /dev/null @@ -1,62 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Squid.h" -#include "../Vector3.h" -#include "../Chunk.h" - - - - - -cSquid::cSquid(void) : - super("Squid", mtSquid, "", "", 0.95, 0.95) -{ -} - - - - - -void cSquid::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - // Drops 0-3 Ink Sacs - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 3 + LootingLevel, E_ITEM_DYE, E_META_DYE_BLACK); -} - - - - - -void cSquid::Tick(float a_Dt, cChunk & a_Chunk) -{ - // We must first process current location, and only then tick, otherwise we risk processing a location in a chunk - // that is not where the entity currently resides (FS #411) - - Vector3d Pos = GetPosition(); - - // TODO: Not a real behavior, but cool :D - int RelY = (int)floor(Pos.y); - if ((RelY < 0) || (RelY >= cChunkDef::Height)) - { - return; - } - int RelX = (int)floor(Pos.x) - a_Chunk.GetPosX() * cChunkDef::Width; - int RelZ = (int)floor(Pos.z) - a_Chunk.GetPosZ() * cChunkDef::Width; - BLOCKTYPE BlockType; - if (a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockType) && !IsBlockWater(BlockType) && !IsOnFire()) - { - // Burn for 10 ticks, then decide again - StartBurning(10); - } - - super::Tick(a_Dt, a_Chunk); -} - - - diff --git a/src/Mobs/Squid.h b/src/Mobs/Squid.h deleted file mode 100644 index b57340427..000000000 --- a/src/Mobs/Squid.h +++ /dev/null @@ -1,31 +0,0 @@ - -#pragma once - -#include "PassiveMonster.h" - - - - - -class cSquid : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - cSquid(); - - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - - CLASS_PROTODEF(cSquid) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - - // Squids do not drown (or float) - virtual void HandleAir(void) override {} - virtual void SetSwimState(cChunk & a_Chunk) override {} -} ; - - - - diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp deleted file mode 100644 index 1cdac7c74..000000000 --- a/src/Mobs/Villager.cpp +++ /dev/null @@ -1,197 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Villager.h" -#include "../World.h" -#include "../BlockArea.h" -#include "../Blocks/BlockHandler.h" -#include "../BlockInServerPluginInterface.h" - - - - - -cVillager::cVillager(eVillagerType VillagerType) : - super("Villager", mtVillager, "", "", 0.6, 1.8), - m_ActionCountDown(-1), - m_Type(VillagerType), - m_VillagerAction(false) -{ -} - - - - - -bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) -{ - if (!super::DoTakeDamage(a_TDI)) - { - return false; - } - - if ((a_TDI.Attacker != NULL) && a_TDI.Attacker->IsPlayer()) - { - if (m_World->GetTickRandomNumber(5) == 3) - { - m_World->BroadcastEntityStatus(*this, esVillagerAngry); - } - } - return true; -} - - - - - -void cVillager::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - if (m_ActionCountDown > -1) - { - m_ActionCountDown--; - if (m_ActionCountDown == 0) - { - switch (m_Type) - { - case vtFarmer: - { - HandleFarmerPlaceCrops(); - } - } - } - return; - } - - if (m_VillagerAction) - { - switch (m_Type) - { - case vtFarmer: - { - HandleFarmerTryHarvestCrops(); - } - } - m_VillagerAction = false; - return; - } - - // Don't always try to do a special action. Each tick has 1% to do a special action. - if (m_World->GetTickRandomNumber(99) != 0) - { - return; - } - - switch (m_Type) - { - case vtFarmer: - { - HandleFarmerPrepareFarmCrops(); - } - } -} - - - - -//////////////////////////////////////////////////////////////////////////////// -// Farmer functions. -void cVillager::HandleFarmerPrepareFarmCrops() -{ - if (!m_World->VillagersShouldHarvestCrops()) - { - return; - } - - cBlockArea Surrounding; - /// Read a 11x7x11 area. - Surrounding.Read( - m_World, - (int) GetPosX() - 5, - (int) GetPosX() + 5, - (int) GetPosY() - 3, - (int) GetPosY() + 3, - (int) GetPosZ() - 5, - (int) GetPosZ() + 5 - ); - - for (int I = 0; I < 5; I++) - { - for (int Y = 0; Y < 6; Y++) - { - // Pick random coordinates and check for crops. - int X = m_World->GetTickRandomNumber(11); - int Z = m_World->GetTickRandomNumber(11); - - // A villager can't farm this. - if (!IsBlockFarmable(Surrounding.GetRelBlockType(X, Y, Z))) - { - continue; - } - if (Surrounding.GetRelBlockMeta(X, Y, Z) != 0x7) - { - continue; - } - - m_VillagerAction = true; - m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); - MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5))); - return; - } // for Y loop. - } // Repeat the procces 5 times. -} - - - - - -void cVillager::HandleFarmerTryHarvestCrops() -{ - // Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks. - if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2) - { - // Check if the blocks didn't change while the villager was walking to the coordinates. - BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); - if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7) - { - cBlockHandler * Handler = cBlockInfo::GetHandler(CropBlock); - cChunkInterface ChunkInterface(m_World->GetChunkMap()); - cBlockInServerPluginInterface PluginInterface(*m_World); - Handler->DropBlock(ChunkInterface, *m_World, PluginInterface, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); - m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0); - m_ActionCountDown = 20; - } - } -} - - - - -void cVillager::HandleFarmerPlaceCrops() -{ - // Check if there is still farmland at the spot where the crops were. - if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) - { - m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0); - } -} - - - - - -bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType) -{ - switch (a_BlockType) - { - case E_BLOCK_CROPS: - case E_BLOCK_POTATOES: - case E_BLOCK_CARROTS: - { - return true; - } - } - return false; -} - diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h deleted file mode 100644 index aa81f0790..000000000 --- a/src/Mobs/Villager.h +++ /dev/null @@ -1,66 +0,0 @@ - -#pragma once - -#include "PassiveMonster.h" - - - - - -class cVillager : - public cPassiveMonster -{ - typedef cPassiveMonster super; - -public: - - enum eVillagerType - { - vtFarmer = 0, - vtLibrarian = 1, - vtPriest = 2, - vtBlacksmith = 3, - vtButcher = 4, - vtGeneric = 5, - vtMax - } ; - - cVillager(eVillagerType VillagerType); - - CLASS_PROTODEF(cVillager) - - // cEntity overrides - virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; - virtual void Tick (float a_Dt, cChunk & a_Chunk) override; - - // cVillager functions - /** return true if the given blocktype are: crops, potatoes or carrots.*/ - bool IsBlockFarmable(BLOCKTYPE a_BlockType); - - // Farmer functions - /** Searches in a 11x7x11 area for crops. If it found some it will navigate to them.*/ - void HandleFarmerPrepareFarmCrops(); - - /** Looks if the farmer has reached it's destination, and if it's still crops and the destination is closer then 2 blocks it will harvest them.*/ - void HandleFarmerTryHarvestCrops(); - - /** Replaces the crops he harvested.*/ - void HandleFarmerPlaceCrops(); - - // Get and set functions. - int GetVilType(void) const { return m_Type; } - Vector3i GetCropsPos(void) const { return m_CropsPos; } - bool DoesHaveActionActivated(void) const { return m_VillagerAction; } - -private: - - int m_ActionCountDown; - int m_Type; - bool m_VillagerAction; - Vector3i m_CropsPos; - -} ; - - - - diff --git a/src/Mobs/Witch.cpp b/src/Mobs/Witch.cpp deleted file mode 100644 index 6956f7b7a..000000000 --- a/src/Mobs/Witch.cpp +++ /dev/null @@ -1,47 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Witch.h" - - - - - -cWitch::cWitch(void) : - super("Witch", mtWitch, "", "", 0.6, 1.8) -{ -} - - - - - -void cWitch::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - MTRand r1; - int DropTypeCount = (r1.randInt() % 3) + 1; - for (int i = 0; i < DropTypeCount; i++) - { - int DropType = r1.randInt() % 7; - switch (DropType) - { - case 0: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GLASS_BOTTLE); break; - case 1: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GLOWSTONE_DUST); break; - case 2: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER); break; - case 3: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_REDSTONE_DUST); break; - case 4: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SPIDER_EYE); break; - case 5: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STICK); break; - case 6: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SUGAR); break; - } - } - AddRandomWeaponDropItem(a_Drops, LootingLevel); -} - - - - diff --git a/src/Mobs/Witch.h b/src/Mobs/Witch.h deleted file mode 100644 index bd059f61d..000000000 --- a/src/Mobs/Witch.h +++ /dev/null @@ -1,28 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" -#include "../MersenneTwister.h" - - - - - -class cWitch : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cWitch(); - - CLASS_PROTODEF(cWitch) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - - bool IsAngry(void) const {return ((m_EMState == ATTACKING) || (m_EMState == CHASING)); } -} ; - - - - diff --git a/src/Mobs/Wither.cpp b/src/Mobs/Wither.cpp deleted file mode 100644 index 578b47995..000000000 --- a/src/Mobs/Wither.cpp +++ /dev/null @@ -1,136 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Wither.h" - -#include "../World.h" -#include "../Entities/Player.h" - - - - - -cWither::cWither(void) : - super("Wither", mtWither, "mob.wither.hurt", "mob.wither.death", 0.9, 4.0), - m_WitherInvulnerableTicks(220) -{ - SetMaxHealth(300); -} - - - - - -bool cWither::IsArmored(void) const -{ - return GetHealth() <= (GetMaxHealth() / 2); -} - - - - - -bool cWither::Initialize(cWorld & a_World) -{ - // Set health before BroadcastSpawnEntity() - SetHealth(GetMaxHealth() / 3); - - return super::Initialize(a_World); -} - - - - - -bool cWither::DoTakeDamage(TakeDamageInfo & a_TDI) -{ - if (a_TDI.DamageType == dtDrowning) - { - return false; - } - - if (m_WitherInvulnerableTicks > 0) - { - return false; - } - - if (IsArmored() && (a_TDI.DamageType == dtRangedAttack)) - { - return false; - } - - return super::DoTakeDamage(a_TDI); -} - - - - - -void cWither::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - if (m_WitherInvulnerableTicks > 0) - { - unsigned int NewTicks = m_WitherInvulnerableTicks - 1; - - if (NewTicks == 0) - { - m_World->DoExplosionAt(7.0, GetPosX(), GetPosY(), GetPosZ(), false, esWitherBirth, this); - } - - m_WitherInvulnerableTicks = NewTicks; - - if ((NewTicks % 10) == 0) - { - Heal(10); - } - } - - m_World->BroadcastEntityMetadata(*this); -} - - - - - -void cWither::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - AddRandomDropItem(a_Drops, 1, 1, E_ITEM_NETHER_STAR); -} - - - - - -void cWither::KilledBy(TakeDamageInfo & a_TDI) -{ - super::KilledBy(a_TDI); - - class cPlayerCallback : public cPlayerListCallback - { - Vector3f m_Pos; - - virtual bool Item(cPlayer * a_Player) - { - // TODO 2014-05-21 xdot: Vanilla minecraft uses an AABB check instead of a radius one - double Dist = (a_Player->GetPosition() - m_Pos).Length(); - if (Dist < 50.0) - { - // If player is close, award achievement - a_Player->AwardAchievement(achKillWither); - } - return false; - } - - public: - cPlayerCallback(const Vector3f & a_Pos) : m_Pos(a_Pos) {} - - } PlayerCallback(GetPosition()); - - m_World->ForEachPlayer(PlayerCallback); -} - - - - diff --git a/src/Mobs/Wither.h b/src/Mobs/Wither.h deleted file mode 100644 index 2403823ed..000000000 --- a/src/Mobs/Wither.h +++ /dev/null @@ -1,45 +0,0 @@ - -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cWither : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cWither(void); - - CLASS_PROTODEF(cWither) - - unsigned int GetWitherInvulnerableTicks(void) const { return m_WitherInvulnerableTicks; } - - void SetWitherInvulnerableTicks(unsigned int a_Ticks) { m_WitherInvulnerableTicks = a_Ticks; } - - /** Returns whether the wither is invulnerable to arrows. */ - bool IsArmored(void) const; - - // cEntity overrides - virtual bool Initialize(cWorld & a_World) override; - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - virtual void KilledBy(TakeDamageInfo & a_TDI) override; - - virtual bool IsUndead(void) override { return true; } - -private: - - /** The number of ticks of invulnerability left after being initially created. Zero once invulnerability has expired. */ - unsigned int m_WitherInvulnerableTicks; - -} ; - - - - diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp deleted file mode 100644 index 4fe1ff1d6..000000000 --- a/src/Mobs/Wolf.cpp +++ /dev/null @@ -1,246 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Wolf.h" -#include "../World.h" -#include "../Entities/Player.h" -#include "../Items/ItemHandler.h" - - - - - -cWolf::cWolf(void) : - super("Wolf", mtWolf, "mob.wolf.hurt", "mob.wolf.death", 0.6, 0.8), - m_IsSitting(false), - m_IsTame(false), - m_IsBegging(false), - m_IsAngry(false), - m_OwnerName(""), - m_CollarColor(14) -{ -} - - - - - -bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI) -{ - if (super::DoTakeDamage(a_TDI)) - { - return false; - } - - if (!m_IsTame) - { - m_IsAngry = true; - } - m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face - return true; -} - - - - -void cWolf::Attack(float a_Dt) -{ - UNUSED(a_Dt); - - if ((m_Target != NULL) && (m_Target->IsPlayer())) - { - if (((cPlayer *)m_Target)->GetName() != m_OwnerName) - { - super::Attack(a_Dt); - } - } - else - { - super::Attack(a_Dt); - } -} - - - - - -void cWolf::OnRightClicked(cPlayer & a_Player) -{ - if (!IsTame() && !IsAngry()) - { - // If the player is holding a bone, try to tame the wolf: - if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_BONE) - { - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - } - - if (m_World->GetTickRandomNumber(7) == 0) - { - // Taming succeeded - SetMaxHealth(20); - SetIsTame(true); - SetOwner(a_Player.GetName(), a_Player.GetUUID()); - m_World->BroadcastEntityStatus(*this, esWolfTamed); - m_World->BroadcastParticleEffect("heart", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); - } - else - { - // Taming failed - m_World->BroadcastEntityStatus(*this, esWolfTaming); - m_World->BroadcastParticleEffect("smoke", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); - } - } - } - else if (IsTame()) - { - // Feed the wolf, restoring its health, or dye its collar: - switch (a_Player.GetEquippedItem().m_ItemType) - { - 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(a_Player.GetEquippedItem().m_ItemType)->GetFoodInfo().FoodLevel); - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - } - } - break; - } - case E_ITEM_DYE: - { - if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog? - { - SetCollarColor(15 - a_Player.GetEquippedItem().m_ItemDamage); - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - } - } - break; - } - default: - { - if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog? - { - SetIsSitting(!IsSitting()); - } - } - } - } - - m_World->BroadcastEntityMetadata(*this); -} - - - - - -void cWolf::Tick(float a_Dt, cChunk & a_Chunk) -{ - if (!IsAngry()) - { - cMonster::Tick(a_Dt, a_Chunk); - } - else - { - super::Tick(a_Dt, a_Chunk); - } - - cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); - if (a_Closest_Player != NULL) - { - 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); - } - } - } - } - - if (IsTame() && !IsSitting()) - { - TickFollowPlayer(); - } - else if (IsSitting()) - { - m_bMovingToDestination = false; - } -} - - - - - -void cWolf::TickFollowPlayer() -{ - class cCallback : - public cPlayerListCallback - { - virtual bool Item(cPlayer * a_Player) override - { - OwnerPos = a_Player->GetPosition(); - return false; - } - public: - Vector3d OwnerPos; - } Callback; - - if (m_World->DoWithPlayer(m_OwnerName, Callback)) - { - // The player is present in the world, follow him: - double Distance = (Callback.OwnerPos - GetPosition()).Length(); - if (Distance > 30) - { - Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z); - TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z); - } - else - { - MoveToPosition(Callback.OwnerPos); - } - } -} - - - - diff --git a/src/Mobs/Wolf.h b/src/Mobs/Wolf.h deleted file mode 100644 index 7500854f8..000000000 --- a/src/Mobs/Wolf.h +++ /dev/null @@ -1,61 +0,0 @@ - -#pragma once - -#include "PassiveAggressiveMonster.h" -#include "../Entities/Entity.h" - - - - - -class cWolf : - public cPassiveAggressiveMonster -{ - typedef cPassiveAggressiveMonster super; - -public: - cWolf(void); - - CLASS_PROTODEF(cWolf) - - virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; - virtual void OnRightClicked(cPlayer & a_Player) override; - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - virtual void TickFollowPlayer(); - virtual void Attack(float a_Dt) override; - - // Get functions - bool IsSitting (void) const { return m_IsSitting; } - bool IsTame (void) const { 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; - } - -protected: - - bool m_IsSitting; - bool m_IsTame; - bool m_IsBegging; - bool m_IsAngry; - AString m_OwnerName; - AString m_OwnerUUID; - int m_CollarColor; -} ; - - - - diff --git a/src/Mobs/Zombie.cpp b/src/Mobs/Zombie.cpp deleted file mode 100644 index 30225c32d..000000000 --- a/src/Mobs/Zombie.cpp +++ /dev/null @@ -1,62 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "Zombie.h" -#include "../World.h" -#include "../LineBlockTracer.h" - - - - - -cZombie::cZombie(bool a_IsVillagerZombie) : - super("Zombie", mtZombie, "mob.zombie.hurt", "mob.zombie.death", 0.6, 1.8), - m_IsVillagerZombie(a_IsVillagerZombie), - m_IsConverting(false) -{ - SetBurnsInDaylight(true); -} - - - - - -void cZombie::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ROTTEN_FLESH); - cItems RareDrops; - RareDrops.Add(cItem(E_ITEM_IRON)); - RareDrops.Add(cItem(E_ITEM_CARROT)); - RareDrops.Add(cItem(E_ITEM_POTATO)); - AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); - AddRandomArmorDropItem(a_Drops, LootingLevel); - AddRandomWeaponDropItem(a_Drops, LootingLevel); -} - - - - - -void cZombie::MoveToPosition(const Vector3d & a_Position) -{ - // If the destination is sufficiently skylight challenged AND the skeleton isn't on fire then block the movement - if ( - !IsOnFire() && - (m_World->GetBlockSkyLight((int)floor(a_Position.x), (int)floor(a_Position.y), (int)floor(a_Position.z)) - m_World->GetSkyDarkness() > 8) - ) - { - m_bMovingToDestination = false; - return; - } - - super::MoveToPosition(a_Position); -} - - - - diff --git a/src/Mobs/Zombie.h b/src/Mobs/Zombie.h deleted file mode 100644 index 118b6e6e7..000000000 --- a/src/Mobs/Zombie.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "AggressiveMonster.h" - - - - - -class cZombie : - public cAggressiveMonster -{ - typedef cAggressiveMonster super; - -public: - cZombie(bool a_IsVillagerZombie); - - CLASS_PROTODEF(cZombie) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void MoveToPosition(const Vector3d & a_Position) override; - - virtual bool IsUndead(void) override { return true; } - - bool IsVillagerZombie(void) const { return m_IsVillagerZombie; } - bool IsConverting (void) const { return m_IsConverting; } - -private: - - bool m_IsVillagerZombie; - bool m_IsConverting; - -} ; - - - - diff --git a/src/Mobs/ZombiePigman.cpp b/src/Mobs/ZombiePigman.cpp deleted file mode 100644 index 05350f877..000000000 --- a/src/Mobs/ZombiePigman.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "ZombiePigman.h" -#include "../World.h" - - - - - -cZombiePigman::cZombiePigman(void) : - super("ZombiePigman", mtZombiePigman, "mob.zombiepig.zpighurt", "mob.zombiepig.zpigdeath", 0.6, 1.8) -{ -} - - - - - -void cZombiePigman::GetDrops(cItems & a_Drops, cEntity * a_Killer) -{ - int LootingLevel = 0; - if (a_Killer != NULL) - { - LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); - } - AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_ROTTEN_FLESH); - AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_GOLD_NUGGET); - - cItems RareDrops; - RareDrops.Add(cItem(E_ITEM_GOLD)); - AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); - AddRandomArmorDropItem(a_Drops, LootingLevel); - AddRandomWeaponDropItem(a_Drops, LootingLevel); -} - - - - - -void cZombiePigman::KilledBy(TakeDamageInfo & a_TDI) -{ - super::KilledBy(a_TDI); - - if ((a_TDI.Attacker != NULL) && (a_TDI.Attacker->IsPlayer())) - { - // TODO: Anger all nearby zombie pigmen - // TODO: In vanilla, if one player angers ZPs, do they attack any nearby player, or only that one attacker? - } -} - - - - diff --git a/src/Mobs/ZombiePigman.h b/src/Mobs/ZombiePigman.h deleted file mode 100644 index bae0115eb..000000000 --- a/src/Mobs/ZombiePigman.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "PassiveAggressiveMonster.h" - - - - - -class cZombiePigman : - public cPassiveAggressiveMonster -{ - typedef cPassiveAggressiveMonster super; - -public: - cZombiePigman(void); - - CLASS_PROTODEF(cZombiePigman) - - virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void KilledBy(TakeDamageInfo & a_TDI) override; - - virtual bool IsUndead(void) override { return true; } -} ; - - - - -- cgit v1.2.3