summaryrefslogtreecommitdiffstats
path: root/src/Mobs
diff options
context:
space:
mode:
authorMattes D <github@xoft.cz>2014-12-07 18:15:23 +0100
committerMattes D <github@xoft.cz>2014-12-07 18:15:23 +0100
commit8ad1afcc1b98c03bd77b0d85236643ba04795d38 (patch)
treee340889a2d505f10fd45a80f7b951f3165d6294a /src/Mobs
parentcEvent: Changed chrono duration resolution. (diff)
parentFixed format warning. (diff)
downloadcuberite-8ad1afcc1b98c03bd77b0d85236643ba04795d38.tar
cuberite-8ad1afcc1b98c03bd77b0d85236643ba04795d38.tar.gz
cuberite-8ad1afcc1b98c03bd77b0d85236643ba04795d38.tar.bz2
cuberite-8ad1afcc1b98c03bd77b0d85236643ba04795d38.tar.lz
cuberite-8ad1afcc1b98c03bd77b0d85236643ba04795d38.tar.xz
cuberite-8ad1afcc1b98c03bd77b0d85236643ba04795d38.tar.zst
cuberite-8ad1afcc1b98c03bd77b0d85236643ba04795d38.zip
Diffstat (limited to 'src/Mobs')
-rw-r--r--src/Mobs/AggressiveMonster.cpp2
-rw-r--r--src/Mobs/Blaze.cpp2
-rw-r--r--src/Mobs/Ghast.cpp2
-rw-r--r--src/Mobs/Monster.cpp156
-rw-r--r--src/Mobs/Monster.h21
-rw-r--r--src/Mobs/MonsterTypes.h10
-rw-r--r--src/Mobs/Pig.cpp26
-rw-r--r--src/Mobs/Pig.h3
-rw-r--r--src/Mobs/Skeleton.cpp2
-rw-r--r--src/Mobs/SnowGolem.cpp2
-rw-r--r--src/Mobs/Villager.cpp7
-rw-r--r--src/Mobs/Witch.cpp1
-rw-r--r--src/Mobs/Witch.h1
13 files changed, 140 insertions, 95 deletions
diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp
index 41ef26e2a..7ca7a9d66 100644
--- a/src/Mobs/AggressiveMonster.cpp
+++ b/src/Mobs/AggressiveMonster.cpp
@@ -75,7 +75,9 @@ void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk)
}
if (m_Target == nullptr)
+ {
return;
+ }
cTracer LineOfSight(GetWorld());
Vector3d AttackDirection(m_Target->GetPosition() - GetPosition());
diff --git a/src/Mobs/Blaze.cpp b/src/Mobs/Blaze.cpp
index 16869c79d..1fa9d2c37 100644
--- a/src/Mobs/Blaze.cpp
+++ b/src/Mobs/Blaze.cpp
@@ -34,7 +34,7 @@ void cBlaze::Attack(float a_Dt)
{
m_AttackInterval += a_Dt * m_AttackRate;
- if (m_Target != nullptr && m_AttackInterval > 3.0)
+ if ((m_Target != nullptr) && (m_AttackInterval > 3.0))
{
// Setting this higher gives us more wiggle room for attackrate
Vector3d Speed = GetLookVector() * 20;
diff --git a/src/Mobs/Ghast.cpp b/src/Mobs/Ghast.cpp
index c65c0d29a..fc8de8362 100644
--- a/src/Mobs/Ghast.cpp
+++ b/src/Mobs/Ghast.cpp
@@ -36,7 +36,7 @@ void cGhast::Attack(float a_Dt)
{
m_AttackInterval += a_Dt * m_AttackRate;
- if (m_Target != nullptr && m_AttackInterval > 3.0)
+ if ((m_Target != nullptr) && (m_AttackInterval > 3.0))
{
// Setting this higher gives us more wiggle room for attackrate
Vector3d Speed = GetLookVector() * 20;
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 23b4d9f45..7b8f763af 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -9,7 +9,6 @@
#include "../Entities/Player.h"
#include "../Entities/ExpOrb.h"
#include "../MonsterConfig.h"
-#include "../MersenneTwister.h"
#include "../Chunk.h"
#include "../FastRandom.h"
@@ -21,57 +20,49 @@
/** Map for eType <-> string
Needs to be alpha-sorted by the strings, because binary search is used in StringToMobType()
The strings need to be lowercase (for more efficient comparisons in StringToMobType())
+m_VanillaName is the name that vanilla use for this mob.
*/
static const struct
{
eMonsterType m_Type;
const char * m_lcName;
+ const char * m_VanillaName;
} g_MobTypeNames[] =
{
- {mtBat, "bat"},
- {mtBlaze, "blaze"},
- {mtCaveSpider, "cavespider"},
- {mtChicken, "chicken"},
- {mtCow, "cow"},
- {mtCreeper, "creeper"},
- {mtEnderman, "enderman"},
- {mtEnderDragon, "enderdragon"},
- {mtGhast, "ghast"},
- {mtHorse, "horse"},
- {mtIronGolem, "irongolem"},
- {mtMagmaCube, "magmacube"},
- {mtMooshroom, "mooshroom"},
- {mtOcelot, "ocelot"},
- {mtPig, "pig"},
- {mtSheep, "sheep"},
- {mtSilverfish, "silverfish"},
- {mtSkeleton, "skeleton"},
- {mtSlime, "slime"},
- {mtSnowGolem, "snowgolem"},
- {mtSpider, "spider"},
- {mtSquid, "squid"},
- {mtVillager, "villager"},
- {mtWitch, "witch"},
- {mtWither, "wither"},
- {mtWolf, "wolf"},
- {mtZombie, "zombie"},
- {mtZombiePigman, "zombiepigman"},
+ {mtBat, "bat", "Bat"},
+ {mtBlaze, "blaze", "Blaze"},
+ {mtCaveSpider, "cavespider", "CaveSpider"},
+ {mtChicken, "chicken", "Chicken"},
+ {mtCow, "cow", "Cow"},
+ {mtCreeper, "creeper", "Creeper"},
+ {mtEnderman, "enderman", "Enderman"},
+ {mtEnderDragon, "enderdragon", "EnderDragon"},
+ {mtGhast, "ghast", "Ghast"},
+ {mtHorse, "horse", "EntityHorse"},
+ {mtIronGolem, "irongolem", "VillagerGolem"},
+ {mtMagmaCube, "magmacube", "LavaSlime"},
+ {mtMooshroom, "mooshroom", "MushroomCow"},
+ {mtOcelot, "ocelot", "Ozelot"},
+ {mtPig, "pig", "Pig"},
+ {mtSheep, "sheep", "Sheep"},
+ {mtSilverfish, "silverfish", "Silverfish"},
+ {mtSkeleton, "skeleton", "Skeleton"},
+ {mtSlime, "slime", "Slime"},
+ {mtSnowGolem, "snowgolem", "SnowMan"},
+ {mtSpider, "spider", "Spider"},
+ {mtSquid, "squid", "Squid"},
+ {mtVillager, "villager", "Villager"},
+ {mtWitch, "witch", "Witch"},
+ {mtWither, "wither", "WitherBoss"},
+ {mtWolf, "wolf", "Wolf"},
+ {mtZombie, "zombie", "Zombie"},
+ {mtZombiePigman, "zombiepigman", "PigZombie"},
} ;
-eMonsterType StringToMobType(const AString & a_MobString)
-{
- LOGWARNING("%s: Function is obsolete, use cMonster::StringToMobType() instead", __FUNCTION__);
- return cMonster::StringToMobType(a_MobString);
-}
-
-
-
-
-
////////////////////////////////////////////////////////////////////////////////
// cMonster:
@@ -160,7 +151,7 @@ void cMonster::TickPathFinding()
BLOCKTYPE BlockAtYP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 1, gCrossCoords[i].z + PosZ);
BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ);
int LowestY = FindFirstNonAirBlockPosition(gCrossCoords[i].x + PosX, gCrossCoords[i].z + PosZ);
- BLOCKTYPE BlockAtLowestY = m_World->GetBlock(gCrossCoords[i].x + PosX, LowestY, gCrossCoords[i].z + PosZ);
+ BLOCKTYPE BlockAtLowestY = (LowestY >= cChunkDef::Height) ? E_BLOCK_AIR : m_World->GetBlock(gCrossCoords[i].x + PosX, LowestY, gCrossCoords[i].z + PosZ);
if (
(!cBlockInfo::IsSolid(BlockAtY)) &&
@@ -275,7 +266,9 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
}
if ((m_Target != nullptr) && m_Target->IsDestroyed())
+ {
m_Target = nullptr;
+ }
// Burning in daylight
HandleDaylightBurning(a_Chunk);
@@ -453,7 +446,7 @@ int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ)
}
else
{
- while (cBlockInfo::IsSolid(m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))) && (PosY < cChunkDef::Height))
+ while ((PosY < cChunkDef::Height) && cBlockInfo::IsSolid(m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))))
{
PosY++;
}
@@ -784,39 +777,47 @@ AString cMonster::MobTypeToString(eMonsterType a_MobType)
-eMonsterType cMonster::StringToMobType(const AString & a_Name)
+AString cMonster::MobTypeToVanillaName(eMonsterType a_MobType)
{
- AString lcName = StrToLower(a_Name);
-
- // Binary-search for the lowercase name:
- int lo = 0, hi = ARRAYCOUNT(g_MobTypeNames) - 1;
- while (hi - lo > 1)
+ // Mob types aren't sorted, so we need to search linearly:
+ for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++)
{
- int mid = (lo + hi) / 2;
- int res = strcmp(g_MobTypeNames[mid].m_lcName, lcName.c_str());
- if (res == 0)
- {
- return g_MobTypeNames[mid].m_Type;
- }
- if (res < 0)
- {
- lo = mid;
- }
- else
+ if (g_MobTypeNames[i].m_Type == a_MobType)
{
- hi = mid;
+ return g_MobTypeNames[i].m_VanillaName;
}
}
- // Range has collapsed to at most two elements, compare each:
- if (strcmp(g_MobTypeNames[lo].m_lcName, lcName.c_str()) == 0)
+
+ // Not found:
+ return "";
+}
+
+
+
+
+
+eMonsterType cMonster::StringToMobType(const AString & a_Name)
+{
+ AString lcName = StrToLower(a_Name);
+
+ // Search MCServer name:
+ for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++)
{
- return g_MobTypeNames[lo].m_Type;
+ if (strcmp(g_MobTypeNames[i].m_lcName, lcName.c_str()) == 0)
+ {
+ return g_MobTypeNames[i].m_Type;
+ }
}
- if ((lo != hi) && (strcmp(g_MobTypeNames[hi].m_lcName, lcName.c_str()) == 0))
+
+ // Not found. Search Vanilla name:
+ for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++)
{
- return g_MobTypeNames[hi].m_Type;
+ if (strcmp(StrToLower(g_MobTypeNames[i].m_VanillaName).c_str(), lcName.c_str()) == 0)
+ {
+ return g_MobTypeNames[i].m_Type;
+ }
}
-
+
// Not found:
return mtInvalidType;
}
@@ -1028,22 +1029,34 @@ void cMonster::AddRandomArmorDropItem(cItems & a_Drops, short a_LootingLevel)
MTRand r1;
if (r1.randInt() % 200 < ((m_DropChanceHelmet * 200) + (a_LootingLevel * 2)))
{
- if (!GetEquippedHelmet().IsEmpty()) a_Drops.push_back(GetEquippedHelmet());
+ if (!GetEquippedHelmet().IsEmpty())
+ {
+ a_Drops.push_back(GetEquippedHelmet());
+ }
}
if (r1.randInt() % 200 < ((m_DropChanceChestplate * 200) + (a_LootingLevel * 2)))
{
- if (!GetEquippedChestplate().IsEmpty()) a_Drops.push_back(GetEquippedChestplate());
+ if (!GetEquippedChestplate().IsEmpty())
+ {
+ a_Drops.push_back(GetEquippedChestplate());
+ }
}
if (r1.randInt() % 200 < ((m_DropChanceLeggings * 200) + (a_LootingLevel * 2)))
{
- if (!GetEquippedLeggings().IsEmpty()) a_Drops.push_back(GetEquippedLeggings());
+ if (!GetEquippedLeggings().IsEmpty())
+ {
+ a_Drops.push_back(GetEquippedLeggings());
+ }
}
if (r1.randInt() % 200 < ((m_DropChanceBoots * 200) + (a_LootingLevel * 2)))
{
- if (!GetEquippedBoots().IsEmpty()) a_Drops.push_back(GetEquippedBoots());
+ if (!GetEquippedBoots().IsEmpty())
+ {
+ a_Drops.push_back(GetEquippedBoots());
+ }
}
}
@@ -1056,7 +1069,10 @@ void cMonster::AddRandomWeaponDropItem(cItems & a_Drops, short a_LootingLevel)
MTRand r1;
if (r1.randInt() % 200 < ((m_DropChanceWeapon * 200) + (a_LootingLevel * 2)))
{
- if (!GetEquippedWeapon().IsEmpty()) a_Drops.push_back(GetEquippedWeapon());
+ if (!GetEquippedWeapon().IsEmpty())
+ {
+ a_Drops.push_back(GetEquippedWeapon());
+ }
}
}
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index f5ae2cb4d..f04e45ac6 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -64,7 +64,7 @@ public:
virtual bool ReachedDestination(void);
// tolua_begin
- eMonsterType GetMobType(void) const {return m_MobType; }
+ eMonsterType GetMobType(void) const { return m_MobType; }
eFamily GetMobFamily(void) const;
// tolua_end
@@ -133,16 +133,19 @@ public:
If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name. */
void SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible);
- /// Translates MobType enum to a string, empty string if unknown
+ /** Translates MobType enum to a string, empty string if unknown */
static AString MobTypeToString(eMonsterType a_MobType);
- /// Translates MobType string to the enum, mtInvalidType if not recognized
+ /** Translates MobType enum to the vanilla name of the mob, empty string if unknown. */
+ static AString MobTypeToVanillaName(eMonsterType a_MobType);
+
+ /** Translates MobType string to the enum, mtInvalidType if not recognized */
static eMonsterType StringToMobType(const AString & a_MobTypeName);
- /// Returns the mob family based on the type
+ /** Returns the mob family based on the type */
static eFamily FamilyFromType(eMonsterType a_MobType);
- /// Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family
+ /** Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family */
static int GetSpawnDelay(cMonster::eFamily a_MobFamily);
// tolua_end
@@ -169,10 +172,12 @@ protected:
/** Stores if mobile is currently moving towards the ultimate, final destination */
bool m_bMovingToDestination;
- /** Finds the first non-air block position (not the highest, as cWorld::GetHeight does)
- If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1
- If current Y is solid, goes up to find first nonsolid block, and returns that */
+ /** Finds the lowest non-air block position (not the highest, as cWorld::GetHeight does)
+ If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1
+ If current Y is solid, goes up to find first nonsolid block, and returns that.
+ If no suitable position is found, returns cChunkDef::Height. */
int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ);
+
/** Returns if a monster can actually reach a given height by jumping or walking */
inline bool IsNextYPosReachable(int a_PosY)
{
diff --git a/src/Mobs/MonsterTypes.h b/src/Mobs/MonsterTypes.h
index 852eb3446..dc6dd3992 100644
--- a/src/Mobs/MonsterTypes.h
+++ b/src/Mobs/MonsterTypes.h
@@ -2,6 +2,7 @@
#pragma once
/// This identifies individual monster type, as well as their network type-ID
+
// tolua_begin
enum eMonsterType
{
@@ -38,15 +39,6 @@ enum eMonsterType
mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN,
} ;
-
-
-
-
-/** Translates a mob string ("ocelot") to mobtype (mtOcelot).
-OBSOLETE, use cMonster::StringToMobType() instead.
-Implemented in Monster.cpp. */
-extern eMonsterType StringToMobType(const AString & a_MobString);
-
// tolua_end
diff --git a/src/Mobs/Pig.cpp b/src/Mobs/Pig.cpp
index 55a4412ca..1e4c35acd 100644
--- a/src/Mobs/Pig.cpp
+++ b/src/Mobs/Pig.cpp
@@ -49,17 +49,17 @@ void cPig::OnRightClicked(cPlayer & a_Player)
a_Player.Detach();
return;
}
-
+
if (m_Attachee->IsPlayer())
{
// Another player is already sitting in here, cannot attach
return;
}
-
+
// Detach whatever is sitting in this pig now:
m_Attachee->Detach();
}
-
+
// Attach the player to this pig
a_Player.AttachTo(this);
}
@@ -98,3 +98,23 @@ void cPig::Tick(float a_Dt, cChunk & a_Chunk)
+
+bool cPig::DoTakeDamage(TakeDamageInfo & a_TDI)
+{
+ if (!super::DoTakeDamage(a_TDI))
+ {
+ return false;
+ }
+
+ if (a_TDI.DamageType == dtLightning)
+ {
+ Destroy();
+ m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtZombiePigman);
+ return true;
+ }
+ return true;
+}
+
+
+
+
diff --git a/src/Mobs/Pig.h b/src/Mobs/Pig.h
index 953850b3a..0e026933a 100644
--- a/src/Mobs/Pig.h
+++ b/src/Mobs/Pig.h
@@ -17,6 +17,9 @@ public:
CLASS_PROTODEF(cPig)
+ // cEntity overrides
+ virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
+
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp
index f17bc307c..da5ddc670 100644
--- a/src/Mobs/Skeleton.cpp
+++ b/src/Mobs/Skeleton.cpp
@@ -71,7 +71,7 @@ void cSkeleton::Attack(float a_Dt)
{
m_AttackInterval += a_Dt * m_AttackRate;
- if (m_Target != nullptr && m_AttackInterval > 3.0)
+ if ((m_Target != nullptr) && (m_AttackInterval > 3.0))
{
// Setting this higher gives us more wiggle room for attackrate
Vector3d Speed = GetLookVector() * 20;
diff --git a/src/Mobs/SnowGolem.cpp b/src/Mobs/SnowGolem.cpp
index 76334d970..8c4178beb 100644
--- a/src/Mobs/SnowGolem.cpp
+++ b/src/Mobs/SnowGolem.cpp
@@ -38,7 +38,7 @@ void cSnowGolem::Tick(float a_Dt, cChunk & a_Chunk)
{
BLOCKTYPE BlockBelow = m_World->GetBlock((int) floor(GetPosX()), (int) floor(GetPosY()) - 1, (int) floor(GetPosZ()));
BLOCKTYPE Block = m_World->GetBlock((int) floor(GetPosX()), (int) floor(GetPosY()), (int) floor(GetPosZ()));
- if (Block == E_BLOCK_AIR && cBlockInfo::IsSolid(BlockBelow))
+ if ((Block == E_BLOCK_AIR) && cBlockInfo::IsSolid(BlockBelow))
{
m_World->SetBlock((int) floor(GetPosX()), (int) floor(GetPosY()), (int) floor(GetPosZ()), E_BLOCK_SNOW, 0);
}
diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp
index 5c9999a59..963595347 100644
--- a/src/Mobs/Villager.cpp
+++ b/src/Mobs/Villager.cpp
@@ -37,6 +37,13 @@ bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
m_World->BroadcastEntityStatus(*this, esVillagerAngry);
}
}
+
+ if (a_TDI.DamageType == dtLightning)
+ {
+ Destroy();
+ m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtWitch);
+ return true;
+ }
return true;
}
diff --git a/src/Mobs/Witch.cpp b/src/Mobs/Witch.cpp
index 747a11f97..a3cadbaa0 100644
--- a/src/Mobs/Witch.cpp
+++ b/src/Mobs/Witch.cpp
@@ -2,6 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Witch.h"
+#include "FastRandom.h"
diff --git a/src/Mobs/Witch.h b/src/Mobs/Witch.h
index 03691fef1..8230e1f98 100644
--- a/src/Mobs/Witch.h
+++ b/src/Mobs/Witch.h
@@ -2,7 +2,6 @@
#pragma once
#include "AggressiveMonster.h"
-#include "../MersenneTwister.h"