summaryrefslogtreecommitdiffstats
path: root/source/Mobs
diff options
context:
space:
mode:
Diffstat (limited to 'source/Mobs')
-rw-r--r--source/Mobs/AggressiveMonster.cpp98
-rw-r--r--source/Mobs/AggressiveMonster.h29
-rw-r--r--source/Mobs/Bat.h27
-rw-r--r--source/Mobs/Blaze.cpp27
-rw-r--r--source/Mobs/Blaze.h25
-rw-r--r--source/Mobs/Cavespider.cpp40
-rw-r--r--source/Mobs/Cavespider.h26
-rw-r--r--source/Mobs/Chicken.cpp33
-rw-r--r--source/Mobs/Chicken.h25
-rw-r--r--source/Mobs/Cow.cpp33
-rw-r--r--source/Mobs/Cow.h25
-rw-r--r--source/Mobs/Creeper.cpp28
-rw-r--r--source/Mobs/Creeper.h25
-rw-r--r--source/Mobs/Enderman.cpp27
-rw-r--r--source/Mobs/Enderman.h25
-rw-r--r--source/Mobs/Ghast.cpp27
-rw-r--r--source/Mobs/Ghast.h25
-rw-r--r--source/Mobs/Magmacube.cpp27
-rw-r--r--source/Mobs/Magmacube.h31
-rw-r--r--source/Mobs/Monster.cpp475
-rw-r--r--source/Mobs/Monster.h109
-rw-r--r--source/Mobs/Mooshroom.cpp33
-rw-r--r--source/Mobs/Mooshroom.h25
-rw-r--r--source/Mobs/Ocelot.h27
-rw-r--r--source/Mobs/PassiveAggressiveMonster.cpp38
-rw-r--r--source/Mobs/PassiveAggressiveMonster.h23
-rw-r--r--source/Mobs/PassiveMonster.cpp57
-rw-r--r--source/Mobs/PassiveMonster.h26
-rw-r--r--source/Mobs/Pig.cpp26
-rw-r--r--source/Mobs/Pig.h25
-rw-r--r--source/Mobs/Sheep.cpp32
-rw-r--r--source/Mobs/Sheep.h28
-rw-r--r--source/Mobs/Silverfish.h27
-rw-r--r--source/Mobs/Skeleton.cpp44
-rw-r--r--source/Mobs/Skeleton.h26
-rw-r--r--source/Mobs/Slime.cpp31
-rw-r--r--source/Mobs/Slime.h31
-rw-r--r--source/Mobs/Spider.cpp27
-rw-r--r--source/Mobs/Spider.h25
-rw-r--r--source/Mobs/Squid.cpp57
-rw-r--r--source/Mobs/Squid.h27
-rw-r--r--source/Mobs/Villager.cpp17
-rw-r--r--source/Mobs/Villager.h23
-rw-r--r--source/Mobs/Witch.cpp32
-rw-r--r--source/Mobs/Witch.h25
-rw-r--r--source/Mobs/Wolf.h27
-rw-r--r--source/Mobs/Zombie.cpp44
-rw-r--r--source/Mobs/Zombie.h25
-rw-r--r--source/Mobs/Zombiepigman.cpp60
-rw-r--r--source/Mobs/Zombiepigman.h27
50 files changed, 2102 insertions, 0 deletions
diff --git a/source/Mobs/AggressiveMonster.cpp b/source/Mobs/AggressiveMonster.cpp
new file mode 100644
index 000000000..c6befa0ed
--- /dev/null
+++ b/source/Mobs/AggressiveMonster.cpp
@@ -0,0 +1,98 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "AggressiveMonster.h"
+
+#include "../Vector3f.h"
+#include "../Player.h"
+#include "../MersenneTwister.h"
+
+
+
+
+
+cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) :
+ super(a_ConfigName, a_ProtocolMobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height),
+ m_ChaseTime(999999)
+{
+ m_EMPersonality = AGGRESSIVE;
+}
+
+
+
+
+
+// What to do if in Chasing State
+void cAggressiveMonster::InStateChasing(float a_Dt)
+{
+ super::InStateChasing(a_Dt);
+ m_ChaseTime += a_Dt;
+ if (m_Target != NULL)
+ {
+ if (m_Target->IsPlayer())
+ {
+ cPlayer * Player = (cPlayer *) m_Target;
+ if (Player->GetGameMode() == 1)
+ {
+ m_EMState = IDLE;
+ return;
+ }
+ }
+
+ Vector3f Pos = Vector3f( GetPosition() );
+ Vector3f Their = Vector3f( m_Target->GetPosition() );
+ if ((Their - Pos).Length() <= m_AttackRange)
+ {
+ cMonster::Attack(a_Dt);
+ }
+ MoveToPosition(Their + Vector3f(0, 0.65f, 0));
+ }
+ else if (m_ChaseTime > 5.f)
+ {
+ m_ChaseTime = 0;
+ m_EMState = IDLE;
+ }
+}
+
+
+
+
+
+void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity)
+{
+ super::EventSeePlayer(a_Entity);
+ m_EMState = CHASING;
+}
+
+
+
+
+
+void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+
+ m_SeePlayerInterval += a_Dt;
+
+ if (m_SeePlayerInterval > 1)
+ {
+ int rem = m_World->GetTickRandomNumber(3) + 1; // Check most of the time but miss occasionally
+
+ m_SeePlayerInterval = 0.0;
+ if (rem >= 2)
+ {
+ if (m_EMState == CHASING)
+ {
+ CheckEventLostPlayer();
+ }
+ else
+ {
+ CheckEventSeePlayer();
+ }
+ }
+ }
+}
+
+
+
+
diff --git a/source/Mobs/AggressiveMonster.h b/source/Mobs/AggressiveMonster.h
new file mode 100644
index 000000000..1eff1831e
--- /dev/null
+++ b/source/Mobs/AggressiveMonster.h
@@ -0,0 +1,29 @@
+
+#pragma once
+
+#include "Monster.h"
+
+
+
+
+
+class cAggressiveMonster :
+ public cMonster
+{
+ typedef cMonster super;
+
+public:
+ cAggressiveMonster(const AString & a_ConfigName, char a_ProtocolMobType, 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;
+
+protected:
+ float m_ChaseTime;
+} ;
+
+
+
+
diff --git a/source/Mobs/Bat.h b/source/Mobs/Bat.h
new file mode 100644
index 000000000..8e4cde29f
--- /dev/null
+++ b/source/Mobs/Bat.h
@@ -0,0 +1,27 @@
+
+#pragma once
+
+#include "PassiveMonster.h"
+
+
+
+
+
+class cBat :
+ public cPassiveMonster
+{
+ typedef cPassiveMonster super;
+
+public:
+ cBat(void) :
+ // TODO: The size is only a guesstimate, measure in vanilla and fix the size values here
+ super("Bat", 65, "mob.bat.hurt", "mob.bat.death", 0.7, 0.7)
+ {
+ }
+
+ CLASS_PROTODEF(cBat);
+} ;
+
+
+
+
diff --git a/source/Mobs/Blaze.cpp b/source/Mobs/Blaze.cpp
new file mode 100644
index 000000000..dbbccf417
--- /dev/null
+++ b/source/Mobs/Blaze.cpp
@@ -0,0 +1,27 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Blaze.h"
+
+
+
+
+
+cBlaze::cBlaze(void) :
+ // TODO: The size is only a guesstimate, measure in vanilla and fix the size values here
+ super("Blaze", 61, "mob.blaze.hit", "mob.blaze.death", 0.7, 1.8)
+{
+}
+
+
+
+
+
+void cBlaze::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 1, E_ITEM_BLAZE_ROD);
+}
+
+
+
+
diff --git a/source/Mobs/Blaze.h b/source/Mobs/Blaze.h
new file mode 100644
index 000000000..9df57530e
--- /dev/null
+++ b/source/Mobs/Blaze.h
@@ -0,0 +1,25 @@
+
+#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;
+} ;
+
+
+
+
diff --git a/source/Mobs/Cavespider.cpp b/source/Mobs/Cavespider.cpp
new file mode 100644
index 000000000..b547362ad
--- /dev/null
+++ b/source/Mobs/Cavespider.cpp
@@ -0,0 +1,40 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Cavespider.h"
+
+
+
+
+
+cCavespider::cCavespider(void) :
+ // TODO: The size is only a guesstimate, measure in vanilla and fix the size values here
+ super("Cavespider", 59, "mob.spider.say", "mob.spider.death", 0.9, 0.6)
+{
+}
+
+
+
+
+
+void cCavespider::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+
+ // TODO: Check vanilla if cavespiders really get passive during the day / in daylight
+ m_EMPersonality = (GetWorld()->GetTimeOfDay() < (12000 + 1000)) ? PASSIVE : AGGRESSIVE;
+}
+
+
+
+
+
+void cCavespider::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_STRING);
+ AddRandomDropItem(a_Drops, 0, 1, E_ITEM_SPIDER_EYE);
+}
+
+
+
+
diff --git a/source/Mobs/Cavespider.h b/source/Mobs/Cavespider.h
new file mode 100644
index 000000000..10ea03f7b
--- /dev/null
+++ b/source/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 GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+} ;
+
+
+
+
diff --git a/source/Mobs/Chicken.cpp b/source/Mobs/Chicken.cpp
new file mode 100644
index 000000000..3da9781d3
--- /dev/null
+++ b/source/Mobs/Chicken.cpp
@@ -0,0 +1,33 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Chicken.h"
+
+
+
+
+
+// TODO: Drop egg every 5-10 minutes
+
+
+
+
+
+cChicken::cChicken(void) :
+ super("Chicken", 93, "mob.chicken.hurt", "mob.chicken.hurt", 0.3, 0.4)
+{
+}
+
+
+
+
+
+void cChicken::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_FEATHER);
+ a_Drops.push_back(cItem(IsOnFire() ? E_ITEM_COOKED_CHICKEN : E_ITEM_RAW_CHICKEN, 1));
+}
+
+
+
+
diff --git a/source/Mobs/Chicken.h b/source/Mobs/Chicken.h
new file mode 100644
index 000000000..2f674e908
--- /dev/null
+++ b/source/Mobs/Chicken.h
@@ -0,0 +1,25 @@
+
+#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;
+} ;
+
+
+
+
diff --git a/source/Mobs/Cow.cpp b/source/Mobs/Cow.cpp
new file mode 100644
index 000000000..8e9b87d27
--- /dev/null
+++ b/source/Mobs/Cow.cpp
@@ -0,0 +1,33 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Cow.h"
+
+
+
+
+
+// TODO: Milk Cow
+
+
+
+
+
+cCow::cCow(void) :
+ super("Cow", 92, "mob.cow.hurt", "mob.cow.hurt", 0.9, 1.3)
+{
+}
+
+
+
+
+
+void cCow::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_LEATHER);
+ AddRandomDropItem(a_Drops, 1, 3, IsOnFire() ? E_ITEM_STEAK : E_ITEM_RAW_BEEF);
+}
+
+
+
+
diff --git a/source/Mobs/Cow.h b/source/Mobs/Cow.h
new file mode 100644
index 000000000..b90cb170e
--- /dev/null
+++ b/source/Mobs/Cow.h
@@ -0,0 +1,25 @@
+
+#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;
+} ;
+
+
+
+
diff --git a/source/Mobs/Creeper.cpp b/source/Mobs/Creeper.cpp
new file mode 100644
index 000000000..9b1b68b79
--- /dev/null
+++ b/source/Mobs/Creeper.cpp
@@ -0,0 +1,28 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Creeper.h"
+
+
+
+
+
+cCreeper::cCreeper(void) :
+ super("Creeper", 50, "mob.creeper.say", "mob.creeper.say", 0.6, 1.8)
+{
+}
+
+
+
+
+
+void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_GUNPOWDER);
+
+ // TODO Check if killed by a skeleton, then drop random music disk
+}
+
+
+
+
diff --git a/source/Mobs/Creeper.h b/source/Mobs/Creeper.h
new file mode 100644
index 000000000..c1d46f462
--- /dev/null
+++ b/source/Mobs/Creeper.h
@@ -0,0 +1,25 @@
+
+#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;
+} ;
+
+
+
+
diff --git a/source/Mobs/Enderman.cpp b/source/Mobs/Enderman.cpp
new file mode 100644
index 000000000..1dc47876f
--- /dev/null
+++ b/source/Mobs/Enderman.cpp
@@ -0,0 +1,27 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Enderman.h"
+
+
+
+
+
+cEnderman::cEnderman(void) :
+ // TODO: The size is only a guesstimate, measure in vanilla and fix the size values here
+ super("Enderman", 58, "mob.endermen.hit", "mob.endermen.death", 0.5, 2.5)
+{
+}
+
+
+
+
+
+void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 1, E_ITEM_ENDER_PEARL);
+}
+
+
+
+
diff --git a/source/Mobs/Enderman.h b/source/Mobs/Enderman.h
new file mode 100644
index 000000000..c4f4ee364
--- /dev/null
+++ b/source/Mobs/Enderman.h
@@ -0,0 +1,25 @@
+
+#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;
+} ;
+
+
+
+
diff --git a/source/Mobs/Ghast.cpp b/source/Mobs/Ghast.cpp
new file mode 100644
index 000000000..288d0c28a
--- /dev/null
+++ b/source/Mobs/Ghast.cpp
@@ -0,0 +1,27 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Ghast.h"
+
+
+
+
+
+cGhast::cGhast(void) :
+ super("Ghast", 56, "mob.ghast.scream", "mob.ghast.death", 4, 4)
+{
+}
+
+
+
+
+
+void cGhast::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_GUNPOWDER);
+ AddRandomDropItem(a_Drops, 0, 1, E_ITEM_GHAST_TEAR);
+}
+
+
+
+
diff --git a/source/Mobs/Ghast.h b/source/Mobs/Ghast.h
new file mode 100644
index 000000000..f9b60dfcf
--- /dev/null
+++ b/source/Mobs/Ghast.h
@@ -0,0 +1,25 @@
+
+#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;
+} ;
+
+
+
+
diff --git a/source/Mobs/Magmacube.cpp b/source/Mobs/Magmacube.cpp
new file mode 100644
index 000000000..0b9b57e3c
--- /dev/null
+++ b/source/Mobs/Magmacube.cpp
@@ -0,0 +1,27 @@
+
+#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", 62, "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)
+{
+ AddRandomDropItem(a_Drops, 0, 1, E_ITEM_MAGMA_CREAM);
+}
+
+
+
+
diff --git a/source/Mobs/Magmacube.h b/source/Mobs/Magmacube.h
new file mode 100644
index 000000000..e4df4f33d
--- /dev/null
+++ b/source/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;
+
+protected:
+
+ /// Size of the magmacube, 1 .. 3, with 1 being the smallest
+ int m_Size;
+} ;
+
+
+
+
diff --git a/source/Mobs/Monster.cpp b/source/Mobs/Monster.cpp
new file mode 100644
index 000000000..706649cb2
--- /dev/null
+++ b/source/Mobs/Monster.cpp
@@ -0,0 +1,475 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Monster.h"
+#include "../Root.h"
+#include "../Server.h"
+#include "../ClientHandle.h"
+#include "../World.h"
+#include "../Player.h"
+#include "../Defines.h"
+#include "../MonsterConfig.h"
+#include "../MersenneTwister.h"
+
+#include "../Vector3f.h"
+#include "../Vector3i.h"
+#include "../Vector3d.h"
+#include "../Tracer.h"
+
+// #include "../../iniFile/iniFile.h"
+
+
+
+
+
+cMonster::cMonster(const AString & a_ConfigName, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height)
+ : super(etMob, a_Width, a_Height)
+ , m_Target(NULL)
+ , m_bMovingToDestination(false)
+ , m_DestinationTime( 0 )
+ , m_DestroyTimer( 0 )
+ , m_Jump(0)
+ , m_MobType(a_ProtocolMobType)
+ , m_SoundHurt(a_SoundHurt)
+ , m_SoundDeath(a_SoundDeath)
+ , m_EMState(IDLE)
+ , m_SightDistance(25)
+ , m_SeePlayerInterval (0)
+ , m_EMPersonality(AGGRESSIVE)
+ , m_AttackDamage(1.0f)
+ , m_AttackRange(5.0f)
+ , m_AttackInterval(0)
+ , m_AttackRate(3)
+ , idle_interval(0)
+{
+ if (!a_ConfigName.empty())
+ {
+ GetMonsterConfig(a_ConfigName);
+ }
+}
+
+
+
+
+
+void cMonster::SpawnOn(cClientHandle & a_Client)
+{
+ a_Client.SendSpawnMob(*this);
+}
+
+
+
+
+
+void cMonster::MoveToPosition( const Vector3f & a_Position )
+{
+ m_bMovingToDestination = true;
+
+ m_Destination = a_Position;
+}
+
+
+
+
+
+bool cMonster::ReachedDestination()
+{
+ Vector3f Distance = (m_Destination) - GetPosition();
+ if( Distance.SqrLength() < 2.f )
+ 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;
+ }
+
+ HandlePhysics(a_Dt,a_Chunk);
+ BroadcastMovementUpdate();
+
+ a_Dt /= 1000;
+
+ if (m_bMovingToDestination)
+ {
+ Vector3f Pos( GetPosition() );
+ Vector3f Distance = m_Destination - Pos;
+ if( !ReachedDestination() )
+ {
+ Distance.y = 0;
+ Distance.Normalize();
+ Distance *= 3;
+ SetSpeedX( Distance.x );
+ SetSpeedZ( Distance.z );
+
+ if (m_EMState == ESCAPING)
+ { //Runs Faster when escaping :D otherwise they just walk away
+ SetSpeedX (GetSpeedX() * 2.f);
+ SetSpeedZ (GetSpeedZ() * 2.f);
+ }
+ }
+ else
+ {
+ m_bMovingToDestination = false;
+ }
+
+ if( GetSpeed().SqrLength() > 0.f )
+ {
+ if( m_bOnGround )
+ {
+ Vector3f NormSpeed = Vector3f(GetSpeed()).NormalizeCopy();
+ Vector3f NextBlock = Vector3f( GetPosition() ) + NormSpeed;
+ int NextHeight;
+ if (!m_World->TryGetHeight((int)NextBlock.x, (int)NextBlock.z, NextHeight))
+ {
+ // The chunk at NextBlock is not loaded
+ return;
+ }
+ if( NextHeight > (GetPosY() - 1.0) && (NextHeight - GetPosY()) < 2.5 )
+ {
+ m_bOnGround = false;
+ SetSpeedY(5.f); // Jump!!
+ }
+ }
+ }
+ }
+
+ Vector3d Distance = m_Destination - GetPosition();
+ if (Distance.SqrLength() > 0.1f)
+ {
+ double Rotation, Pitch;
+ Distance.Normalize();
+ VectorToEuler( Distance.x, Distance.y, Distance.z, Rotation, Pitch );
+ SetHeadYaw (Rotation);
+ SetRotation( Rotation );
+ SetPitch( -Pitch );
+ }
+
+ 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;
+ }
+ } // switch (m_EMState)
+}
+
+
+
+
+
+
+void cMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
+{
+ super::DoTakeDamage(a_TDI);
+ if((m_SoundHurt != "") && (m_Health > 0)) m_World->BroadcastSoundEffect(m_SoundHurt, (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 1.0f, 0.8f);
+ if (a_TDI.Attacker != NULL)
+ {
+ m_Target = a_TDI.Attacker;
+ AddReference(m_Target);
+ }
+}
+
+
+
+
+
+void cMonster::KilledBy(cEntity * a_Killer)
+{
+ super::KilledBy(a_Killer);
+ if (m_SoundHurt != "")
+ {
+ m_World->BroadcastSoundEffect(m_SoundDeath, (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 1.0f, 0.8f);
+ }
+ m_DestroyTimer = 0;
+}
+
+
+
+
+
+//----State Logic
+
+const char *cMonster::GetState()
+{
+ switch(m_EMState)
+ {
+ case IDLE: return "Idle";
+ case ATTACKING: return "Attacking";
+ case CHASING: return "Chasing";
+ default: return "Unknown";
+ }
+}
+
+
+
+
+
+// for debugging
+void cMonster::SetState(const AString & a_State)
+{
+ if (a_State.compare("Idle") == 0)
+ {
+ m_EMState = IDLE;
+ }
+ else if (a_State.compare("Attacking") == 0)
+ {
+ m_EMState = ATTACKING;
+ }
+ else if (a_State.compare("Chasing") == 0)
+ {
+ m_EMState = CHASING;
+ }
+ else
+ {
+ LOGD("cMonster::SetState(): Invalid state");
+ ASSERT(!"Invalid state");
+ }
+}
+
+
+
+
+
+//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 = FindClosestPlayer();
+
+ if (Closest != NULL)
+ {
+ EventSeePlayer(Closest);
+ }
+}
+
+
+
+
+
+void cMonster::CheckEventLostPlayer(void)
+{
+ Vector3f pos;
+ cTracer LineOfSight(GetWorld());
+
+ if (m_Target != NULL)
+ {
+ pos = m_Target->GetPosition();
+ if ((pos - GetPosition()).Length() > m_SightDistance || LineOfSight.Trace(GetPosition(),(pos - GetPosition()), (int)(pos - GetPosition()).Length()))
+ {
+ 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;
+ AddReference(m_Target);
+}
+
+
+
+
+
+void cMonster::EventLosePlayer(void)
+{
+ Dereference(m_Target);
+ m_Target = NULL;
+ m_EMState = IDLE;
+}
+
+
+
+
+
+// What to do if in Idle State
+void cMonster::InStateIdle(float a_Dt)
+{
+ idle_interval += a_Dt;
+ if (idle_interval > 1)
+ {
+ // at this interval the results are predictable
+ int rem = m_World->GetTickRandomNumber(6) + 1;
+ // LOGD("Moving: int: %3.3f rem: %i",idle_interval,rem);
+ idle_interval -= 1; // So nothing gets dropped when the server hangs for a few seconds
+ Vector3f Dist;
+ Dist.x = (float)(m_World->GetTickRandomNumber(10) - 5);
+ Dist.z = (float)(m_World->GetTickRandomNumber(10) - 5);
+ if ((Dist.SqrLength() > 2) && (rem >= 3))
+ {
+ m_Destination.x = (float)(GetPosX() + Dist.x);
+ m_Destination.z = (float)(GetPosZ() + Dist.z);
+ int PosY;
+ if (m_World->TryGetHeight((int)m_Destination.x, (int)m_Destination.z, PosY))
+ {
+ m_Destination.y = (float)PosY + 1.2f;
+ MoveToPosition(m_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
+ }
+}
+
+
+
+
+
+// Do attack here
+// a_Dt is passed so we can set attack rate
+void cMonster::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
+ m_AttackInterval = 0.0;
+ ((cPawn *)m_Target)->TakeDamage(*this);
+ }
+}
+
+
+
+
+
+// Checks for Players close by and if they are visible return the closest
+cPlayer * cMonster::FindClosestPlayer(void)
+{
+ return m_World->FindClosestPlayer(GetPosition(), m_SightDistance);
+}
+
+
+
+
+
+void cMonster::GetMonsterConfig(const AString & a_Name)
+{
+ cRoot::Get()->GetMonsterConfig()->AssignAttributes(this, a_Name);
+}
+
+
+
+
+
+void cMonster::SetAttackRate(int ar)
+{
+ m_AttackRate = (float)ar;
+}
+
+
+
+
+
+void cMonster::SetAttackRange(float ar)
+{
+ m_AttackRange = ar;
+}
+
+
+
+
+
+void cMonster::SetAttackDamage(float ad)
+{
+ m_AttackDamage = ad;
+}
+
+
+
+
+
+void cMonster::SetSightDistance(float sd)
+{
+ m_SightDistance = sd;
+}
+
+
+
+
+
+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));
+ }
+}
+
+
+
+
diff --git a/source/Mobs/Monster.h b/source/Mobs/Monster.h
new file mode 100644
index 000000000..ea7f935ea
--- /dev/null
+++ b/source/Mobs/Monster.h
@@ -0,0 +1,109 @@
+
+#pragma once
+
+#include "../Pawn.h"
+#include "../Defines.h"
+#include "../World.h"
+#include "../BlockID.h"
+#include "../Item.h"
+
+
+
+
+
+class Vector3f;
+class cClientHandle;
+
+
+
+
+// tolua_begin
+class cMonster :
+ public cPawn
+{
+ typedef cPawn super;
+public:
+ // tolua_end
+ float m_SightDistance;
+
+ /** Creates the mob object.
+ * If a_ConfigName is not empty, the configuration is loaded using GetMonsterConfig()
+ * a_ProtocolMobType is the ID of the mob 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, char a_ProtocolMobType, 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 void DoTakeDamage(TakeDamageInfo & a_TDI) override;
+
+ virtual void KilledBy(cEntity * a_Killer) override;
+
+ virtual void MoveToPosition(const Vector3f & a_Position);
+ virtual bool ReachedDestination(void);
+
+ char GetMobType(void) const {return m_MobType; }
+
+ const char * GetState();
+ void SetState(const AString & str);
+
+ virtual void CheckEventSeePlayer(void);
+ virtual void EventSeePlayer(cEntity * a_Player);
+ virtual cPlayer * FindClosestPlayer(); // non static is easier. also virtual so other mobs can implement their own searching algo
+
+ /// Reads the monster configuration for the specified monster name and assigns it to this object.
+ void GetMonsterConfig(const AString & a_Name);
+
+ 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);
+
+ virtual void Attack(float a_Dt);
+ int GetMobType() {return m_MobType;}
+ int GetAttackRate(){return (int)m_AttackRate;}
+ void SetAttackRate(int ar);
+ void SetAttackRange(float ar);
+ void SetAttackDamage(float ad);
+ void SetSightDistance(float sd);
+
+ enum MState{ATTACKING, IDLE, CHASING, ESCAPING} m_EMState;
+ enum MPersonality{PASSIVE,AGGRESSIVE,COWARDLY} m_EMPersonality;
+
+protected:
+
+ cEntity * m_Target;
+ float m_AttackRate;
+ float idle_interval;
+
+ Vector3f m_Destination;
+ bool m_bMovingToDestination;
+ bool m_bPassiveAggressive;
+
+ float m_DestinationTime;
+
+ float m_DestroyTimer;
+ float m_Jump;
+
+ char m_MobType;
+
+ AString m_SoundHurt;
+ AString m_SoundDeath;
+
+ float m_SeePlayerInterval;
+ float m_AttackDamage;
+ float m_AttackRange;
+ float m_AttackInterval;
+
+ void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0);
+} ; // tolua_export
+
+
+
+
diff --git a/source/Mobs/Mooshroom.cpp b/source/Mobs/Mooshroom.cpp
new file mode 100644
index 000000000..5d2c901ba
--- /dev/null
+++ b/source/Mobs/Mooshroom.cpp
@@ -0,0 +1,33 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Mooshroom.h"
+
+
+
+
+
+// TODO: Milk Cow
+
+
+
+
+
+cMooshroom::cMooshroom(void) :
+ super("Mooshroom", 96, "mob.cow.hurt", "mob.cow.hurt", 0.9, 1.3)
+{
+}
+
+
+
+
+
+void cMooshroom::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_LEATHER);
+ AddRandomDropItem(a_Drops, 1, 3, IsOnFire() ? E_ITEM_STEAK : E_ITEM_RAW_BEEF);
+}
+
+
+
+
diff --git a/source/Mobs/Mooshroom.h b/source/Mobs/Mooshroom.h
new file mode 100644
index 000000000..73f6348b6
--- /dev/null
+++ b/source/Mobs/Mooshroom.h
@@ -0,0 +1,25 @@
+
+#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;
+} ;
+
+
+
+
diff --git a/source/Mobs/Ocelot.h b/source/Mobs/Ocelot.h
new file mode 100644
index 000000000..98ea224e2
--- /dev/null
+++ b/source/Mobs/Ocelot.h
@@ -0,0 +1,27 @@
+
+#pragma once
+
+#include "PassiveMonster.h"
+
+
+
+
+
+class cOcelot :
+ public cPassiveMonster
+{
+ typedef cPassiveMonster super;
+
+public:
+ cOcelot(void) :
+ // TODO: The size is only a guesstimate, measure in vanilla and fix the size values here
+ super("Ocelot", 98, "mob.cat.hitt", "mob.cat.hitt", 0.9, 0.5)
+ {
+ }
+
+ CLASS_PROTODEF(cOcelot);
+} ;
+
+
+
+
diff --git a/source/Mobs/PassiveAggressiveMonster.cpp b/source/Mobs/PassiveAggressiveMonster.cpp
new file mode 100644
index 000000000..f1e231a09
--- /dev/null
+++ b/source/Mobs/PassiveAggressiveMonster.cpp
@@ -0,0 +1,38 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "PassiveAggressiveMonster.h"
+
+#include "../Player.h"
+
+
+
+
+
+cPassiveAggressiveMonster::cPassiveAggressiveMonster(const AString & a_ConfigName, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) :
+ super(a_ConfigName, a_ProtocolMobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height)
+{
+ m_EMPersonality = PASSIVE;
+}
+
+
+
+
+
+void cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
+{
+ super::DoTakeDamage(a_TDI);
+
+ if ((m_Target != NULL) && (m_Target->IsPlayer()))
+ {
+ cPlayer * Player = (cPlayer *) m_Target;
+ if (Player->GetGameMode() != 1)
+ {
+ m_EMState = CHASING;
+ }
+ }
+}
+
+
+
+
diff --git a/source/Mobs/PassiveAggressiveMonster.h b/source/Mobs/PassiveAggressiveMonster.h
new file mode 100644
index 000000000..243dfff38
--- /dev/null
+++ b/source/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, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height);
+
+ virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
+} ;
+
+
+
+
diff --git a/source/Mobs/PassiveMonster.cpp b/source/Mobs/PassiveMonster.cpp
new file mode 100644
index 000000000..96cc1ba8f
--- /dev/null
+++ b/source/Mobs/PassiveMonster.cpp
@@ -0,0 +1,57 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "PassiveMonster.h"
+#include "../MersenneTwister.h"
+
+
+
+
+
+cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) :
+ super(a_ConfigName, a_ProtocolMobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height)
+{
+ m_EMPersonality = PASSIVE;
+}
+
+
+
+
+
+void cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
+{
+ super::DoTakeDamage(a_TDI);
+ if ((a_TDI.Attacker != this) && (a_TDI.Attacker != NULL))
+ {
+ m_EMState = ESCAPING;
+ }
+}
+
+
+
+
+
+void cPassiveMonster::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+
+ m_SeePlayerInterval += a_Dt;
+
+ if (m_SeePlayerInterval > 1) // Check every second
+ {
+ int rem = m_World->GetTickRandomNumber(3) + 1; // Check most of the time but miss occasionally
+
+ m_SeePlayerInterval = 0.0;
+ if (rem >= 2)
+ {
+ if (m_EMState == ESCAPING)
+ {
+ CheckEventLostPlayer();
+ }
+ }
+ }
+}
+
+
+
+
diff --git a/source/Mobs/PassiveMonster.h b/source/Mobs/PassiveMonster.h
new file mode 100644
index 000000000..ae0bea3fb
--- /dev/null
+++ b/source/Mobs/PassiveMonster.h
@@ -0,0 +1,26 @@
+
+#pragma once
+
+#include "Monster.h"
+
+
+
+
+
+class cPassiveMonster :
+ public cMonster
+{
+ typedef cMonster super;
+
+public:
+ cPassiveMonster(const AString & a_ConfigName, char a_ProtocolMobType, 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 void DoTakeDamage(TakeDamageInfo & a_TDI) override;
+} ;
+
+
+
+
diff --git a/source/Mobs/Pig.cpp b/source/Mobs/Pig.cpp
new file mode 100644
index 000000000..9df2c2571
--- /dev/null
+++ b/source/Mobs/Pig.cpp
@@ -0,0 +1,26 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Pig.h"
+
+
+
+
+
+cPig::cPig(void) :
+ super("Pig", 90, "mob.pig.say", "mob.pig.death", 0.9, 0.9)
+{
+}
+
+
+
+
+
+void cPig::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 1, 3, IsOnFire() ? E_ITEM_COOKED_PORKCHOP : E_ITEM_RAW_PORKCHOP);
+}
+
+
+
+
diff --git a/source/Mobs/Pig.h b/source/Mobs/Pig.h
new file mode 100644
index 000000000..ae790ac2f
--- /dev/null
+++ b/source/Mobs/Pig.h
@@ -0,0 +1,25 @@
+
+#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;
+} ;
+
+
+
+
diff --git a/source/Mobs/Sheep.cpp b/source/Mobs/Sheep.cpp
new file mode 100644
index 000000000..2f371f384
--- /dev/null
+++ b/source/Mobs/Sheep.cpp
@@ -0,0 +1,32 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Sheep.h"
+#include "../BlockID.h"
+
+
+
+
+
+cSheep::cSheep(void) :
+ super("Sheep", 91, "mob.sheep.say", "mob.sheep.say", 0.6, 1.3),
+ m_IsSheared(false),
+ m_WoolColor(E_META_WOOL_WHITE)
+{
+}
+
+
+
+
+
+void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ if (!m_IsSheared)
+ {
+ a_Drops.push_back(cItem(E_BLOCK_WOOL, 1, m_WoolColor));
+ }
+}
+
+
+
+
diff --git a/source/Mobs/Sheep.h b/source/Mobs/Sheep.h
new file mode 100644
index 000000000..369fc78c5
--- /dev/null
+++ b/source/Mobs/Sheep.h
@@ -0,0 +1,28 @@
+
+#pragma once
+
+#include "PassiveMonster.h"
+
+
+
+
+
+class cSheep :
+ public cPassiveMonster
+{
+ typedef cPassiveMonster super;
+
+public:
+ cSheep(void);
+
+ bool m_IsSheared;
+ NIBBLETYPE m_WoolColor; // Uses E_META_WOOL_ constants for colors
+
+ CLASS_PROTODEF(cSheep);
+
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+} ;
+
+
+
+
diff --git a/source/Mobs/Silverfish.h b/source/Mobs/Silverfish.h
new file mode 100644
index 000000000..7d675a9c0
--- /dev/null
+++ b/source/Mobs/Silverfish.h
@@ -0,0 +1,27 @@
+
+#pragma once
+
+#include "AggressiveMonster.h"
+
+
+
+
+
+class cSilverfish :
+ public cAggressiveMonster
+{
+ typedef cAggressiveMonster super;
+
+public:
+ cSilverfish(void) :
+ // TODO: The size is only a guesstimate, measure in vanilla and fix the size values here
+ super("Silverfish", 60, "mob.silverfish.hit", "mob.silverfish.kill", 0.9, 0.3)
+ {
+ }
+
+ CLASS_PROTODEF(cSilverfish);
+} ;
+
+
+
+
diff --git a/source/Mobs/Skeleton.cpp b/source/Mobs/Skeleton.cpp
new file mode 100644
index 000000000..8dacbece8
--- /dev/null
+++ b/source/Mobs/Skeleton.cpp
@@ -0,0 +1,44 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Skeleton.h"
+
+
+
+
+
+cSkeleton::cSkeleton(void) :
+ super("Skeleton", 51, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8)
+{
+}
+
+
+
+
+
+void cSkeleton::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ cMonster::Tick(a_Dt, a_Chunk);
+
+ // TODO Outsource
+ // TODO should do SkyLight check, mobs in the dark donīt burn
+ if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && !IsOnFire())
+ {
+ // Burn for 10 ticks, then decide again
+ StartBurning(10);
+ }
+}
+
+
+
+
+
+void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_ARROW);
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_BONE);
+}
+
+
+
+
diff --git a/source/Mobs/Skeleton.h b/source/Mobs/Skeleton.h
new file mode 100644
index 000000000..bc541bac2
--- /dev/null
+++ b/source/Mobs/Skeleton.h
@@ -0,0 +1,26 @@
+
+#pragma once
+
+#include "AggressiveMonster.h"
+
+
+
+
+
+class cSkeleton :
+ public cAggressiveMonster
+{
+ typedef cAggressiveMonster super;
+
+public:
+ cSkeleton();
+
+ CLASS_PROTODEF(cSkeleton);
+
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+} ;
+
+
+
+
diff --git a/source/Mobs/Slime.cpp b/source/Mobs/Slime.cpp
new file mode 100644
index 000000000..b209ac869
--- /dev/null
+++ b/source/Mobs/Slime.cpp
@@ -0,0 +1,31 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Slime.h"
+
+// TODO: Implement sized slimes
+
+
+
+
+
+/// Creates a slime of the specified size; size is 1 .. 3, with 1 being the smallest
+cSlime::cSlime(int a_Size) :
+ super("Slime", 55, "mob.slime.attack", "mob.slime.attack", 0.6 * a_Size, 0.6 * a_Size),
+ m_Size(a_Size)
+{
+}
+
+
+
+
+
+void cSlime::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ // TODO: only when tiny
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_SLIMEBALL);
+}
+
+
+
+
diff --git a/source/Mobs/Slime.h b/source/Mobs/Slime.h
new file mode 100644
index 000000000..88136ff32
--- /dev/null
+++ b/source/Mobs/Slime.h
@@ -0,0 +1,31 @@
+
+#pragma once
+
+#include "AggressiveMonster.h"
+
+
+
+
+
+class cSlime :
+ public cAggressiveMonster
+{
+ typedef cAggressiveMonster super;
+
+public:
+ /// Creates a slime of the specified size; size is 1 .. 3, with 1 being the smallest
+ cSlime(int a_Size);
+
+ CLASS_PROTODEF(cSlime);
+
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+
+protected:
+
+ /// Size of the slime, 1 .. 3, with 1 being the smallest
+ int m_Size;
+} ;
+
+
+
+
diff --git a/source/Mobs/Spider.cpp b/source/Mobs/Spider.cpp
new file mode 100644
index 000000000..2f244cdbc
--- /dev/null
+++ b/source/Mobs/Spider.cpp
@@ -0,0 +1,27 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Spider.h"
+
+
+
+
+
+cSpider::cSpider(void) :
+ super("Spider", 52, "mob.spider.say", "mob.spider.death", 1.4, 0.9)
+{
+}
+
+
+
+
+
+void cSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_STRING);
+ AddRandomDropItem(a_Drops, 0, 1, E_ITEM_SPIDER_EYE);
+}
+
+
+
+
diff --git a/source/Mobs/Spider.h b/source/Mobs/Spider.h
new file mode 100644
index 000000000..51e65d028
--- /dev/null
+++ b/source/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/source/Mobs/Squid.cpp b/source/Mobs/Squid.cpp
new file mode 100644
index 000000000..cb796f5ec
--- /dev/null
+++ b/source/Mobs/Squid.cpp
@@ -0,0 +1,57 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Squid.h"
+#include "../Vector3d.h"
+#include "../Chunk.h"
+
+
+
+
+
+cSquid::cSquid(void) :
+ super("Squid", 94, "", "", 0.95, 0.95)
+{
+}
+
+
+
+
+
+void cSquid::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ // Drops 0-3 Ink Sacs
+ AddRandomDropItem(a_Drops, 0, 3, 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;
+ if (!IsBlockWater(a_Chunk.GetBlock(RelX, RelY, RelZ)) && !IsOnFire())
+ {
+ // Burn for 10 ticks, then decide again
+ StartBurning(10);
+ }
+
+ super::Tick(a_Dt, a_Chunk);
+}
+
+
+
+
diff --git a/source/Mobs/Squid.h b/source/Mobs/Squid.h
new file mode 100644
index 000000000..35d7295b3
--- /dev/null
+++ b/source/Mobs/Squid.h
@@ -0,0 +1,27 @@
+
+#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;
+} ;
+
+
+
+
diff --git a/source/Mobs/Villager.cpp b/source/Mobs/Villager.cpp
new file mode 100644
index 000000000..98e5276e1
--- /dev/null
+++ b/source/Mobs/Villager.cpp
@@ -0,0 +1,17 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Villager.h"
+
+
+
+
+
+cVillager::cVillager(void) :
+ super("Villager", 120, "", "", 0.6, 1.8)
+{
+}
+
+
+
+
diff --git a/source/Mobs/Villager.h b/source/Mobs/Villager.h
new file mode 100644
index 000000000..92267a979
--- /dev/null
+++ b/source/Mobs/Villager.h
@@ -0,0 +1,23 @@
+
+#pragma once
+
+#include "PassiveMonster.h"
+
+
+
+
+
+class cVillager :
+ public cPassiveMonster
+{
+ typedef cPassiveMonster super;
+
+public:
+ cVillager();
+
+ CLASS_PROTODEF(cVillager);
+} ;
+
+
+
+
diff --git a/source/Mobs/Witch.cpp b/source/Mobs/Witch.cpp
new file mode 100644
index 000000000..b29783853
--- /dev/null
+++ b/source/Mobs/Witch.cpp
@@ -0,0 +1,32 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Witch.h"
+
+
+
+
+
+cWitch::cWitch(void) :
+ super("Witch", 66, "", "", 0.6, 1.8)
+{
+}
+
+
+
+
+
+void cWitch::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 6, E_ITEM_GLASS_BOTTLE);
+ AddRandomDropItem(a_Drops, 0, 6, E_ITEM_GLOWSTONE_DUST);
+ AddRandomDropItem(a_Drops, 0, 6, E_ITEM_GUNPOWDER);
+ AddRandomDropItem(a_Drops, 0, 6, E_ITEM_REDSTONE_DUST);
+ AddRandomDropItem(a_Drops, 0, 6, E_ITEM_SPIDER_EYE);
+ AddRandomDropItem(a_Drops, 0, 6, E_ITEM_STICK);
+ AddRandomDropItem(a_Drops, 0, 6, E_ITEM_SUGAR);
+}
+
+
+
+
diff --git a/source/Mobs/Witch.h b/source/Mobs/Witch.h
new file mode 100644
index 000000000..ce0b49deb
--- /dev/null
+++ b/source/Mobs/Witch.h
@@ -0,0 +1,25 @@
+
+#pragma once
+
+#include "AggressiveMonster.h"
+
+
+
+
+
+class cWitch :
+ public cAggressiveMonster
+{
+ typedef cAggressiveMonster super;
+
+public:
+ cWitch();
+
+ CLASS_PROTODEF(cWitch);
+
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+} ;
+
+
+
+
diff --git a/source/Mobs/Wolf.h b/source/Mobs/Wolf.h
new file mode 100644
index 000000000..405df80a6
--- /dev/null
+++ b/source/Mobs/Wolf.h
@@ -0,0 +1,27 @@
+
+#pragma once
+
+#include "PassiveAggressiveMonster.h"
+
+
+
+
+
+class cWolf :
+ public cPassiveAggressiveMonster
+{
+ typedef cPassiveAggressiveMonster super;
+
+public:
+ cWolf(void) :
+ // TODO: The size is only a guesstimate, measure in vanilla and fix the size values here (wiki.vg values are suspicious)
+ super("Wolf", 95, "mob.wolf.hurt", "mob.wolf.death", 0.9, 0.9)
+ {
+ }
+
+ CLASS_PROTODEF(cWolf);
+} ;
+
+
+
+
diff --git a/source/Mobs/Zombie.cpp b/source/Mobs/Zombie.cpp
new file mode 100644
index 000000000..d0a929519
--- /dev/null
+++ b/source/Mobs/Zombie.cpp
@@ -0,0 +1,44 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Zombie.h"
+
+
+
+
+
+cZombie::cZombie(void) :
+ super("Zombie", 54, "mob.zombie.hurt", "mob.zombie.death", 0.6, 1.8)
+{
+}
+
+
+
+
+
+void cZombie::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+
+ // TODO Same as in cSkeleton :D
+ if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && !IsOnFire())
+ {
+ // Burn for 10 ticks, then decide again
+ StartBurning(10);
+ }
+}
+
+
+
+
+
+void cZombie::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 2, E_ITEM_ROTTEN_FLESH);
+
+ // TODO: Rare drops
+}
+
+
+
+
diff --git a/source/Mobs/Zombie.h b/source/Mobs/Zombie.h
new file mode 100644
index 000000000..61f8e3bb8
--- /dev/null
+++ b/source/Mobs/Zombie.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "AggressiveMonster.h"
+
+
+
+
+
+class cZombie :
+ public cAggressiveMonster
+{
+ typedef cAggressiveMonster super;
+
+public:
+ cZombie();
+
+ CLASS_PROTODEF(cZombie);
+
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+} ;
+
+
+
+
diff --git a/source/Mobs/Zombiepigman.cpp b/source/Mobs/Zombiepigman.cpp
new file mode 100644
index 000000000..6483e58c5
--- /dev/null
+++ b/source/Mobs/Zombiepigman.cpp
@@ -0,0 +1,60 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Zombiepigman.h"
+
+
+
+
+
+cZombiepigman::cZombiepigman(void) :
+ super("Zombiepigman", 57, "mob.zombiepig.zpighurt", "mob.zombiepig.zpigdeath", 0.6, 1.8)
+{
+}
+
+
+
+
+
+void cZombiepigman::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+
+ // TODO Same as noticed in cSkeleton AND Do they really burn by sun?? :D In the neather is no sun :D
+ if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && !IsOnFire())
+ {
+ // Burn for 10 ticks, then decide again
+ StartBurning(10);
+ }
+}
+
+
+
+
+
+void cZombiepigman::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ AddRandomDropItem(a_Drops, 0, 1, E_ITEM_ROTTEN_FLESH);
+ AddRandomDropItem(a_Drops, 0, 1, E_ITEM_GOLD_NUGGET);
+
+ // TODO: Rare drops
+}
+
+
+
+
+
+void cZombiepigman::KilledBy(cEntity * a_Killer)
+{
+ super::KilledBy(a_Killer);
+
+ if ((a_Killer != NULL) && (a_Killer->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/source/Mobs/Zombiepigman.h b/source/Mobs/Zombiepigman.h
new file mode 100644
index 000000000..fe8c6d047
--- /dev/null
+++ b/source/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 Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+ virtual void KilledBy(cEntity * a_Killer) override;
+} ;
+
+
+
+