diff options
Diffstat (limited to 'source/Mobs')
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; +} ; + + + + |