summaryrefslogtreecommitdiffstats
path: root/src/Mobs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Mobs')
-rw-r--r--src/Mobs/AggressiveMonster.cpp16
-rw-r--r--src/Mobs/AggressiveMonster.h4
-rw-r--r--src/Mobs/Bat.cpp3
-rw-r--r--src/Mobs/Blaze.cpp6
-rw-r--r--src/Mobs/CMakeLists.txt1
-rw-r--r--src/Mobs/CaveSpider.cpp (renamed from src/Mobs/Cavespider.cpp)12
-rw-r--r--src/Mobs/CaveSpider.h (renamed from src/Mobs/Cavespider.h)5
-rw-r--r--src/Mobs/Creeper.cpp18
-rw-r--r--src/Mobs/Creeper.h2
-rw-r--r--src/Mobs/Ghast.cpp3
-rw-r--r--src/Mobs/IncludeAllMonsters.h6
-rw-r--r--src/Mobs/MagmaCube.cpp (renamed from src/Mobs/Magmacube.cpp)3
-rw-r--r--src/Mobs/MagmaCube.h (renamed from src/Mobs/Magmacube.h)1
-rw-r--r--src/Mobs/Monster.cpp103
-rw-r--r--src/Mobs/Monster.h9
-rw-r--r--src/Mobs/PassiveAggressiveMonster.cpp8
-rw-r--r--src/Mobs/PassiveAggressiveMonster.h2
-rw-r--r--src/Mobs/PassiveMonster.cpp8
-rw-r--r--src/Mobs/PassiveMonster.h2
-rw-r--r--src/Mobs/Sheep.cpp9
-rw-r--r--src/Mobs/Skeleton.cpp3
-rw-r--r--src/Mobs/Villager.cpp11
-rw-r--r--src/Mobs/Villager.h2
-rw-r--r--src/Mobs/Wither.cpp56
-rw-r--r--src/Mobs/Wither.h11
-rw-r--r--src/Mobs/Wolf.cpp13
-rw-r--r--src/Mobs/Wolf.h4
-rw-r--r--src/Mobs/ZombiePigman.cpp (renamed from src/Mobs/Zombiepigman.cpp)3
-rw-r--r--src/Mobs/ZombiePigman.h (renamed from src/Mobs/Zombiepigman.h)1
29 files changed, 224 insertions, 101 deletions
diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp
index 0901f85a9..85b122034 100644
--- a/src/Mobs/AggressiveMonster.cpp
+++ b/src/Mobs/AggressiveMonster.cpp
@@ -37,7 +37,7 @@ void cAggressiveMonster::InStateChasing(float a_Dt)
}
}
- if (((float)m_FinalDestination.x != (float)m_Target->GetPosX()) || ((float)m_FinalDestination.z != (float)m_Target->GetPosZ()))
+ if (!IsMovingToTargetPosition())
{
MoveToPosition(m_Target->GetPosition());
}
@@ -106,3 +106,17 @@ void cAggressiveMonster::Attack(float a_Dt)
+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<float>::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<float>::epsilon())
+ {
+ return false;
+ }
+ return true;
+}
diff --git a/src/Mobs/AggressiveMonster.h b/src/Mobs/AggressiveMonster.h
index 152260f95..d70ff04a3 100644
--- a/src/Mobs/AggressiveMonster.h
+++ b/src/Mobs/AggressiveMonster.h
@@ -22,6 +22,10 @@ public:
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
index 1417ddd9e..c072d4f48 100644
--- a/src/Mobs/Bat.cpp
+++ b/src/Mobs/Bat.cpp
@@ -7,8 +7,7 @@
cBat::cBat(void) :
- // TODO: The size is only a guesstimate, measure in vanilla and fix the size values here
- super("Bat", mtBat, "mob.bat.hurt", "mob.bat.death", 0.7, 0.7)
+ super("Bat", mtBat, "mob.bat.hurt", "mob.bat.death", 0.5, 0.9)
{
}
diff --git a/src/Mobs/Blaze.cpp b/src/Mobs/Blaze.cpp
index 84ff8929b..19bdf8737 100644
--- a/src/Mobs/Blaze.cpp
+++ b/src/Mobs/Blaze.cpp
@@ -3,13 +3,13 @@
#include "Blaze.h"
#include "../World.h"
+#include "../Entities/FireChargeEntity.h"
cBlaze::cBlaze(void) :
- // TODO: The size is only a guesstimate, measure in vanilla and fix the size values here
- super("Blaze", mtBlaze, "mob.blaze.hit", "mob.blaze.death", 0.7, 1.8)
+ super("Blaze", mtBlaze, "mob.blaze.hit", "mob.blaze.death", 0.6, 1.8)
{
}
@@ -44,7 +44,7 @@ void cBlaze::Attack(float a_Dt)
{
return;
}
- if (!FireCharge->Initialize(m_World))
+ if (!FireCharge->Initialize(*m_World))
{
delete FireCharge;
return;
diff --git a/src/Mobs/CMakeLists.txt b/src/Mobs/CMakeLists.txt
index 87fbfd2fc..53c265803 100644
--- a/src/Mobs/CMakeLists.txt
+++ b/src/Mobs/CMakeLists.txt
@@ -6,6 +6,7 @@ include_directories ("${PROJECT_SOURCE_DIR}/../")
file(GLOB SOURCE
"*.cpp"
+ "*.h"
)
add_library(Mobs ${SOURCE})
diff --git a/src/Mobs/Cavespider.cpp b/src/Mobs/CaveSpider.cpp
index 94e93283d..1157b81f9 100644
--- a/src/Mobs/Cavespider.cpp
+++ b/src/Mobs/CaveSpider.cpp
@@ -1,15 +1,14 @@
-
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-#include "Cavespider.h"
+#include "CaveSpider.h"
#include "../World.h"
-cCavespider::cCavespider(void) :
- super("Cavespider", mtCaveSpider, "mob.spider.say", "mob.spider.death", 0.7, 0.5)
+cCaveSpider::cCaveSpider(void) :
+ super("CaveSpider", mtCaveSpider, "mob.spider.say", "mob.spider.death", 0.7, 0.5)
{
}
@@ -17,11 +16,10 @@ cCavespider::cCavespider(void) :
-void cCavespider::Tick(float a_Dt, cChunk & a_Chunk)
+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;
}
@@ -29,7 +27,7 @@ void cCavespider::Tick(float a_Dt, cChunk & a_Chunk)
-void cCavespider::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+void cCaveSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{
int LootingLevel = 0;
if (a_Killer != NULL)
diff --git a/src/Mobs/Cavespider.h b/src/Mobs/CaveSpider.h
index 10ea03f7b..be9f174f9 100644
--- a/src/Mobs/Cavespider.h
+++ b/src/Mobs/CaveSpider.h
@@ -1,4 +1,3 @@
-
#pragma once
#include "AggressiveMonster.h"
@@ -7,13 +6,13 @@
-class cCavespider :
+class cCaveSpider :
public cAggressiveMonster
{
typedef cAggressiveMonster super;
public:
- cCavespider(void);
+ cCaveSpider(void);
CLASS_PROTODEF(cCaveSpider);
diff --git a/src/Mobs/Creeper.cpp b/src/Mobs/Creeper.cpp
index 3471b4cf1..a7b97f604 100644
--- a/src/Mobs/Creeper.cpp
+++ b/src/Mobs/Creeper.cpp
@@ -43,7 +43,7 @@ void cCreeper::Tick(float a_Dt, cChunk & a_Chunk)
if (m_ExplodingTimer == 30)
{
m_World->DoExplosionAt((m_bIsCharged ? 5 : 3), GetPosX(), GetPosY(), GetPosZ(), false, esMonster, this);
- Destroy();
+ Destroy(); // Just in case we aren't killed by the explosion
}
}
}
@@ -54,6 +54,12 @@ void cCreeper::Tick(float a_Dt, cChunk & a_Chunk)
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)
{
@@ -65,7 +71,7 @@ void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{
if (((cMonster *)((cProjectileEntity *)a_Killer)->GetCreator())->GetMobType() == mtSkeleton)
{
- // 12 music discs. TickRand starts from 0, so range = 11. Disk IDs start at 2256, so add that. There.
+ // 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);
}
}
@@ -75,9 +81,12 @@ void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer)
-void cCreeper::DoTakeDamage(TakeDamageInfo & a_TDI)
+bool cCreeper::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- super::DoTakeDamage(a_TDI);
+ if (!super::DoTakeDamage(a_TDI))
+ {
+ return false;
+ }
if (a_TDI.DamageType == dtLightning)
{
@@ -85,6 +94,7 @@ void cCreeper::DoTakeDamage(TakeDamageInfo & a_TDI)
}
m_World->BroadcastEntityMetadata(*this);
+ return true;
}
diff --git a/src/Mobs/Creeper.h b/src/Mobs/Creeper.h
index 9abca369b..fc7db6716 100644
--- a/src/Mobs/Creeper.h
+++ b/src/Mobs/Creeper.h
@@ -18,7 +18,7 @@ public:
CLASS_PROTODEF(cCreeper);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
- virtual void DoTakeDamage(TakeDamageInfo & a_TDI) 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;
diff --git a/src/Mobs/Ghast.cpp b/src/Mobs/Ghast.cpp
index fe18f5e76..4df8e165c 100644
--- a/src/Mobs/Ghast.cpp
+++ b/src/Mobs/Ghast.cpp
@@ -3,6 +3,7 @@
#include "Ghast.h"
#include "../World.h"
+#include "../Entities/GhastFireballEntity.h"
@@ -45,7 +46,7 @@ void cGhast::Attack(float a_Dt)
{
return;
}
- if (!GhastBall->Initialize(m_World))
+ if (!GhastBall->Initialize(*m_World))
{
delete GhastBall;
return;
diff --git a/src/Mobs/IncludeAllMonsters.h b/src/Mobs/IncludeAllMonsters.h
index 1b436a11f..3460db993 100644
--- a/src/Mobs/IncludeAllMonsters.h
+++ b/src/Mobs/IncludeAllMonsters.h
@@ -1,6 +1,6 @@
#include "Bat.h"
#include "Blaze.h"
-#include "Cavespider.h"
+#include "CaveSpider.h"
#include "Chicken.h"
#include "Cow.h"
#include "Creeper.h"
@@ -10,7 +10,7 @@
#include "Giant.h"
#include "Horse.h"
#include "IronGolem.h"
-#include "Magmacube.h"
+#include "MagmaCube.h"
#include "Mooshroom.h"
#include "Ocelot.h"
#include "Pig.h"
@@ -26,4 +26,4 @@
#include "Wither.h"
#include "Wolf.h"
#include "Zombie.h"
-#include "Zombiepigman.h"
+#include "ZombiePigman.h"
diff --git a/src/Mobs/Magmacube.cpp b/src/Mobs/MagmaCube.cpp
index 05405f082..3e9abc108 100644
--- a/src/Mobs/Magmacube.cpp
+++ b/src/Mobs/MagmaCube.cpp
@@ -1,7 +1,6 @@
-
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-#include "Magmacube.h"
+#include "MagmaCube.h"
diff --git a/src/Mobs/Magmacube.h b/src/Mobs/MagmaCube.h
index 130952970..43065cae5 100644
--- a/src/Mobs/Magmacube.h
+++ b/src/Mobs/MagmaCube.h
@@ -1,4 +1,3 @@
-
#pragma once
#include "AggressiveMonster.h"
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 171097aba..5843ca5a6 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -111,9 +111,9 @@ void cMonster::SpawnOn(cClientHandle & a_Client)
void cMonster::TickPathFinding()
{
- const int PosX = (int)floor(GetPosX());
- const int PosY = (int)floor(GetPosY());
- const int PosZ = (int)floor(GetPosZ());
+ const int PosX = POSX_TOINT;
+ const int PosY = POSY_TOINT;
+ const int PosZ = POSZ_TOINT;
m_FinalDestination.y = (double)FindFirstNonAirBlockPosition(m_FinalDestination.x, m_FinalDestination.z);
@@ -148,13 +148,27 @@ void cMonster::TickPathFinding()
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);
- BLOCKTYPE BlockAtYM = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY - 1, gCrossCoords[i].z + PosZ);
-
- if ((!cBlockInfo::IsSolid(BlockAtY)) && (!cBlockInfo::IsSolid(BlockAtYP)) && (!IsBlockLava(BlockAtYM)) && (BlockAtY != E_BLOCK_FENCE) && (BlockAtY != E_BLOCK_FENCE_GATE))
+ 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)) && (!cBlockInfo::IsSolid(BlockAtYP)) && (!cBlockInfo::IsSolid(BlockAtYPP)) && (!IsBlockLava(BlockAtYM)) && (BlockAtY != E_BLOCK_FENCE) && (BlockAtY != E_BLOCK_FENCE_GATE))
+ 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));
}
@@ -287,7 +301,7 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
if (DoesPosYRequireJump((int)floor(m_Destination.y)))
{
m_bOnGround = false;
- AddPosY(1.5); // Jump!!
+ AddSpeedY(5.2); // Jump!!
}
}
@@ -296,9 +310,19 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
{
Distance.y = 0;
Distance.Normalize();
- Distance *= 5;
- SetSpeedX(Distance.x);
- SetSpeedZ(Distance.z);
+
+ if (m_bOnGround)
+ {
+ Distance *= 2.5;
+ }
+ else
+ {
+ // Don't let the mob move too much if he's falling.
+ Distance *= 0.25;
+ }
+
+ AddSpeedX(Distance.x);
+ AddSpeedZ(Distance.z);
if (m_EMState == ESCAPING)
{ //Runs Faster when escaping :D otherwise they just walk away
@@ -341,6 +365,8 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
InStateEscaping(a_Dt);
break;
}
+
+ case ATTACKING: break;
} // switch (m_EMState)
BroadcastMovementUpdate();
@@ -402,7 +428,7 @@ void cMonster::HandleFalling()
GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, POSY_TOINT - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */);
}
- m_LastGroundHeight = (int)floor(GetPosY());
+ m_LastGroundHeight = POSY_TOINT;
}
}
@@ -411,7 +437,7 @@ void cMonster::HandleFalling()
int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ)
{
- int PosY = (int)floor(GetPosY());
+ int PosY = POSY_TOINT;
if (PosY < 0)
PosY = 0;
@@ -443,17 +469,23 @@ int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ)
-void cMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
+bool cMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- super::DoTakeDamage(a_TDI);
+ if (!super::DoTakeDamage(a_TDI))
+ {
+ return false;
+ }
- if((m_SoundHurt != "") && (m_Health > 0))
+ if (!m_SoundHurt.empty() && (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;
}
+ return true;
}
@@ -526,7 +558,7 @@ void cMonster::KilledBy(cEntity * a_Killer)
break;
}
}
- if (a_Killer != NULL)
+ if ((a_Killer != NULL) && (!IsBaby()))
{
m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), Reward);
}
@@ -747,8 +779,10 @@ cMonster::eFamily cMonster::FamilyFromType(eType a_Type)
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;
@@ -759,17 +793,20 @@ cMonster::eFamily cMonster::FamilyFromType(eType a_Type)
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 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 mfMaxplusone;
+ return mfUnhandled;
}
@@ -780,10 +817,12 @@ 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 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;
@@ -802,6 +841,10 @@ cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType)
switch (a_MobType)
{
case mtMagmaCube:
+ {
+ toReturn = new cMagmaCube(Random.NextInt(2) + 1);
+ break;
+ }
case mtSlime:
{
toReturn = new cSlime(Random.NextInt(2) + 1);
@@ -845,13 +888,14 @@ cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType)
case mtBat: toReturn = new cBat(); break;
case mtBlaze: toReturn = new cBlaze(); break;
- case mtCaveSpider: toReturn = new cCavespider(); 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;
@@ -969,15 +1013,15 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk)
return;
}
- int RelY = (int)floor(GetPosY());
+ int RelY = POSY_TOINT;
if ((RelY < 0) || (RelY >= cChunkDef::Height))
{
// Outside the world
return;
}
- int RelX = (int)floor(GetPosX()) - GetChunkX() * cChunkDef::Width;
- int RelZ = (int)floor(GetPosZ()) - GetChunkZ() * cChunkDef::Width;
+ int RelX = POSX_TOINT - GetChunkX() * cChunkDef::Width;
+ int RelZ = POSZ_TOINT - GetChunkZ() * cChunkDef::Width;
if (!a_Chunk.IsLightValid())
{
@@ -989,7 +1033,8 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk)
(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
+ !IsOnFire() && // Not already burning
+ (GetWorld()->GetWeather() != eWeather_Rain) // Not raining
)
{
// Burn for 100 ticks, then decide again
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index 776426a0d..7d7e90eb2 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -66,7 +66,8 @@ public:
mfAmbient = 2, // Bats
mfWater = 3, // Squid
- mfMaxplusone, // Nothing. Be sure this is the last and the others are in order
+ mfNoSpawn,
+ mfUnhandled, // Nothing. Be sure this is the last and the others are in order
} ;
// tolua_end
@@ -87,7 +88,7 @@ public:
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
- virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
+ virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void KilledBy(cEntity * a_Killer) override;
@@ -185,14 +186,14 @@ protected:
inline bool IsNextYPosReachable(int a_PosY)
{
return (
- (a_PosY <= (int)floor(GetPosY())) ||
+ (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 > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1));
+ 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 */
diff --git a/src/Mobs/PassiveAggressiveMonster.cpp b/src/Mobs/PassiveAggressiveMonster.cpp
index 4b45f9a2a..24501b1ba 100644
--- a/src/Mobs/PassiveAggressiveMonster.cpp
+++ b/src/Mobs/PassiveAggressiveMonster.cpp
@@ -19,9 +19,12 @@ cPassiveAggressiveMonster::cPassiveAggressiveMonster(const AString & a_ConfigNam
-void cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
+bool cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- super::DoTakeDamage(a_TDI);
+ if (!super::DoTakeDamage(a_TDI))
+ {
+ return false;
+ }
if ((m_Target != NULL) && (m_Target->IsPlayer()))
{
@@ -30,6 +33,7 @@ void cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
m_EMState = CHASING;
}
}
+ return true;
}
diff --git a/src/Mobs/PassiveAggressiveMonster.h b/src/Mobs/PassiveAggressiveMonster.h
index 2c5ef30b1..a0da50e8e 100644
--- a/src/Mobs/PassiveAggressiveMonster.h
+++ b/src/Mobs/PassiveAggressiveMonster.h
@@ -15,7 +15,7 @@ class cPassiveAggressiveMonster :
public:
cPassiveAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height);
- virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
+ virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
} ;
diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp
index 904cd63cc..2861d7314 100644
--- a/src/Mobs/PassiveMonster.cpp
+++ b/src/Mobs/PassiveMonster.cpp
@@ -18,13 +18,17 @@ cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eType a_MobType,
-void cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
+bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- super::DoTakeDamage(a_TDI);
+ if (!super::DoTakeDamage(a_TDI))
+ {
+ return false;
+ }
if ((a_TDI.Attacker != this) && (a_TDI.Attacker != NULL))
{
m_EMState = ESCAPING;
}
+ return true;
}
diff --git a/src/Mobs/PassiveMonster.h b/src/Mobs/PassiveMonster.h
index 0b3c155da..70574585a 100644
--- a/src/Mobs/PassiveMonster.h
+++ b/src/Mobs/PassiveMonster.h
@@ -18,7 +18,7 @@ public:
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
/// When hit by someone, run away
- virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
+ 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/Sheep.cpp b/src/Mobs/Sheep.cpp
index c64360153..5a6b760af 100644
--- a/src/Mobs/Sheep.cpp
+++ b/src/Mobs/Sheep.cpp
@@ -36,7 +36,8 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cSheep::OnRightClicked(cPlayer & a_Player)
{
- if ((a_Player.GetEquippedItem().m_ItemType == E_ITEM_SHEARS) && (!m_IsSheared))
+ const cItem & EquippedItem = a_Player.GetEquippedItem();
+ if ((EquippedItem.m_ItemType == E_ITEM_SHEARS) && (!m_IsSheared))
{
m_IsSheared = true;
m_World->BroadcastEntityMetadata(*this);
@@ -51,9 +52,9 @@ void cSheep::OnRightClicked(cPlayer & a_Player)
Drops.push_back(cItem(E_BLOCK_WOOL, NumDrops, m_WoolColor));
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10);
}
- if ((a_Player.GetEquippedItem().m_ItemType == E_ITEM_DYE) && (m_WoolColor != 15 - a_Player.GetEquippedItem().m_ItemDamage))
+ else if ((EquippedItem.m_ItemType == E_ITEM_DYE) && (m_WoolColor != 15 - EquippedItem.m_ItemDamage))
{
- m_WoolColor = 15 - a_Player.GetEquippedItem().m_ItemDamage;
+ m_WoolColor = 15 - EquippedItem.m_ItemDamage;
if (!a_Player.IsGameModeCreative())
{
a_Player.GetInventory().RemoveOneEquippedItem();
@@ -101,7 +102,7 @@ void cSheep::Tick(float a_Dt, cChunk & a_Chunk)
{
if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS)
{
- m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_SHEEP_EATING);
+ m_World->BroadcastEntityStatus(*this, esSheepEating);
m_TimeToStopEating = 40;
}
}
diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp
index 1685f40c5..e7f3971cc 100644
--- a/src/Mobs/Skeleton.cpp
+++ b/src/Mobs/Skeleton.cpp
@@ -3,6 +3,7 @@
#include "Skeleton.h"
#include "../World.h"
+#include "../Entities/ArrowEntity.h"
@@ -80,7 +81,7 @@ void cSkeleton::Attack(float a_Dt)
{
return;
}
- if (!Arrow->Initialize(m_World))
+ if (!Arrow->Initialize(*m_World))
{
delete Arrow;
return;
diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp
index bbd8d6aaa..41283acf4 100644
--- a/src/Mobs/Villager.cpp
+++ b/src/Mobs/Villager.cpp
@@ -23,16 +23,21 @@ cVillager::cVillager(eVillagerType VillagerType) :
-void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
+bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- super::DoTakeDamage(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, ENTITY_STATUS_VILLAGER_ANGRY);
+ m_World->BroadcastEntityStatus(*this, esVillagerAngry);
}
}
+ return true;
}
diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h
index 5bba4d4ba..abde48407 100644
--- a/src/Mobs/Villager.h
+++ b/src/Mobs/Villager.h
@@ -30,7 +30,7 @@ public:
CLASS_PROTODEF(cVillager);
// cEntity overrides
- virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
+ virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void Tick (float a_Dt, cChunk & a_Chunk) override;
// cVillager functions
diff --git a/src/Mobs/Wither.cpp b/src/Mobs/Wither.cpp
index 8f5d28b68..da4cc7765 100644
--- a/src/Mobs/Wither.cpp
+++ b/src/Mobs/Wither.cpp
@@ -2,7 +2,9 @@
#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"
@@ -10,7 +12,7 @@
cWither::cWither(void) :
super("Wither", mtWither, "mob.wither.hurt", "mob.wither.death", 0.9, 4.0),
- m_InvulnerableTicks(220)
+ m_WitherInvulnerableTicks(220)
{
SetMaxHealth(300);
}
@@ -28,7 +30,7 @@ bool cWither::IsArmored(void) const
-bool cWither::Initialize(cWorld * a_World)
+bool cWither::Initialize(cWorld & a_World)
{
// Set health before BroadcastSpawnEntity()
SetHealth(GetMaxHealth() / 3);
@@ -40,24 +42,24 @@ bool cWither::Initialize(cWorld * a_World)
-void cWither::DoTakeDamage(TakeDamageInfo & a_TDI)
+bool cWither::DoTakeDamage(TakeDamageInfo & a_TDI)
{
if (a_TDI.DamageType == dtDrowning)
{
- return;
+ return false;
}
- if (m_InvulnerableTicks > 0)
+ if (m_WitherInvulnerableTicks > 0)
{
- return;
+ return false;
}
if (IsArmored() && (a_TDI.DamageType == dtRangedAttack))
{
- return;
+ return false;
}
- super::DoTakeDamage(a_TDI);
+ return super::DoTakeDamage(a_TDI);
}
@@ -68,16 +70,16 @@ void cWither::Tick(float a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
- if (m_InvulnerableTicks > 0)
+ if (m_WitherInvulnerableTicks > 0)
{
- unsigned int NewTicks = m_InvulnerableTicks - 1;
+ unsigned int NewTicks = m_WitherInvulnerableTicks - 1;
if (NewTicks == 0)
{
m_World->DoExplosionAt(7.0, GetPosX(), GetPosY(), GetPosZ(), false, esWitherBirth, this);
}
- m_InvulnerableTicks = NewTicks;
+ m_WitherInvulnerableTicks = NewTicks;
if ((NewTicks % 10) == 0)
{
@@ -100,3 +102,35 @@ void cWither::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+
+void cWither::KilledBy(cEntity * a_Killer)
+{
+ super::KilledBy(a_Killer);
+
+ 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
index bc78bfaad..03a320788 100644
--- a/src/Mobs/Wither.h
+++ b/src/Mobs/Wither.h
@@ -17,23 +17,24 @@ public:
CLASS_PROTODEF(cWither);
- unsigned int GetNumInvulnerableTicks(void) const { return m_InvulnerableTicks; }
+ unsigned int GetWitherInvulnerableTicks(void) const { return m_WitherInvulnerableTicks; }
- void SetNumInvulnerableTicks(unsigned int a_Ticks) { m_InvulnerableTicks = a_Ticks; }
+ 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 bool Initialize(cWorld & a_World) override;
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
- virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
+ virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void KilledBy(cEntity * a_Killer) override;
private:
/** The number of ticks of invulnerability left after being initially created. Zero once invulnerability has expired. */
- unsigned int m_InvulnerableTicks;
+ unsigned int m_WitherInvulnerableTicks;
} ;
diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp
index 0d3619166..e6268abc7 100644
--- a/src/Mobs/Wolf.cpp
+++ b/src/Mobs/Wolf.cpp
@@ -25,14 +25,19 @@ cWolf::cWolf(void) :
-void cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
+bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- super::DoTakeDamage(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;
}
@@ -75,12 +80,12 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
SetMaxHealth(20);
SetIsTame(true);
SetOwner(a_Player.GetName());
- m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMED);
+ m_World->BroadcastEntityStatus(*this, esWolfTamed);
m_World->BroadcastParticleEffect("heart", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5);
}
else
{
- m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMING);
+ m_World->BroadcastEntityStatus(*this, esWolfTaming);
m_World->BroadcastParticleEffect("smoke", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5);
}
}
diff --git a/src/Mobs/Wolf.h b/src/Mobs/Wolf.h
index 9e5ad03c7..fb8a7c995 100644
--- a/src/Mobs/Wolf.h
+++ b/src/Mobs/Wolf.h
@@ -18,7 +18,7 @@ public:
CLASS_PROTODEF(cWolf);
- virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
+ 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();
@@ -37,7 +37,7 @@ public:
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 SetOwner (AString a_NewOwner) { m_OwnerName = a_NewOwner; }
+ void SetOwner (const AString & a_NewOwner) { m_OwnerName = a_NewOwner; }
void SetCollarColor(int a_CollarColor) { m_CollarColor = a_CollarColor; }
protected:
diff --git a/src/Mobs/Zombiepigman.cpp b/src/Mobs/ZombiePigman.cpp
index a0142b566..c9d94face 100644
--- a/src/Mobs/Zombiepigman.cpp
+++ b/src/Mobs/ZombiePigman.cpp
@@ -1,7 +1,6 @@
-
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-#include "Zombiepigman.h"
+#include "ZombiePigman.h"
#include "../World.h"
diff --git a/src/Mobs/Zombiepigman.h b/src/Mobs/ZombiePigman.h
index 67991d56a..ab3cebf6d 100644
--- a/src/Mobs/Zombiepigman.h
+++ b/src/Mobs/ZombiePigman.h
@@ -1,4 +1,3 @@
-
#pragma once
#include "PassiveAggressiveMonster.h"