summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Barney <samjbarney@gmail.com>2014-08-21 18:23:35 +0200
committerSamuel Barney <samjbarney@gmail.com>2014-08-21 18:23:35 +0200
commitbadced2acd355680685efdfc3ca728338201920f (patch)
tree9fb560de7c6b60bc11f4514c6b44511791622932
parentRemoved the rest of the references to cNewMonster (diff)
downloadcuberite-badced2acd355680685efdfc3ca728338201920f.tar
cuberite-badced2acd355680685efdfc3ca728338201920f.tar.gz
cuberite-badced2acd355680685efdfc3ca728338201920f.tar.bz2
cuberite-badced2acd355680685efdfc3ca728338201920f.tar.lz
cuberite-badced2acd355680685efdfc3ca728338201920f.tar.xz
cuberite-badced2acd355680685efdfc3ca728338201920f.tar.zst
cuberite-badced2acd355680685efdfc3ca728338201920f.zip
-rw-r--r--src/Mobs/Monster.cpp266
-rw-r--r--src/Mobs/Monster.h65
-rw-r--r--src/Mobs/Wither.cpp3
-rw-r--r--src/Mobs/Wither.h8
4 files changed, 340 insertions, 2 deletions
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 4ea495279..c272dc93a 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -1,7 +1,57 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Monster.h"
+#include "IncludeAllMonsters.h"
#include "../ClientHandle.h"
#include "../MersenneTwister.h"
+#include "../FastRandom.h"
+
+
+
+
+
+/** Map for eType <-> string
+Needs to be alpha-sorted by the strings, because binary search is used in StringToMobType()
+The strings need to be lowercase (for more efficient comparisons in StringToMobType())
+*/
+static const struct
+{
+ cMonster::eType m_Type;
+ const char * m_lcName;
+} g_MobTypeNames[] =
+{
+ {cMonster::mtBat, "bat"},
+ {cMonster::mtBlaze, "blaze"},
+ {cMonster::mtCaveSpider, "cavespider"},
+ {cMonster::mtChicken, "chicken"},
+ {cMonster::mtCow, "cow"},
+ {cMonster::mtCreeper, "creeper"},
+ {cMonster::mtEnderman, "enderman"},
+ {cMonster::mtEnderDragon, "enderdragon"},
+ {cMonster::mtGhast, "ghast"},
+ {cMonster::mtHorse, "horse"},
+ {cMonster::mtIronGolem, "irongolem"},
+ {cMonster::mtMagmaCube, "magmacube"},
+ {cMonster::mtMooshroom, "mooshroom"},
+ {cMonster::mtOcelot, "ocelot"},
+ {cMonster::mtPig, "pig"},
+ {cMonster::mtSheep, "sheep"},
+ {cMonster::mtSilverfish, "silverfish"},
+ {cMonster::mtSkeleton, "skeleton"},
+ {cMonster::mtSlime, "slime"},
+ {cMonster::mtSnowGolem, "snowgolem"},
+ {cMonster::mtSpider, "spider"},
+ {cMonster::mtSquid, "squid"},
+ {cMonster::mtVillager, "villager"},
+ {cMonster::mtWitch, "witch"},
+ {cMonster::mtWither, "wither"},
+ {cMonster::mtWolf, "wolf"},
+ {cMonster::mtZombie, "zombie"},
+ {cMonster::mtZombiePigman, "zombiepigman"},
+} ;
+
+
+
+
cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height)
: super(etMonster, a_Width, a_Height)
@@ -114,3 +164,219 @@ void cMonster::AddRandomWeaponDropItem(cItems & a_Drops, short a_LootingLevel)
if (!GetEquippedWeapon().IsEmpty()) a_Drops.push_back(GetEquippedWeapon());
}
}
+
+
+
+
+
+cMonster::eFamily cMonster::FamilyFromType(eType a_Type)
+{
+ // Passive-agressive mobs are counted in mob spawning code as passive
+
+ switch (a_Type)
+ {
+ case mtBat: return mfAmbient;
+ case mtBlaze: return mfHostile;
+ case mtCaveSpider: return mfHostile;
+ case mtChicken: return mfPassive;
+ case mtCow: return mfPassive;
+ case mtCreeper: return mfHostile;
+ case mtEnderDragon: return mfNoSpawn;
+ case mtEnderman: return mfHostile;
+ case mtGhast: return mfHostile;
+ case mtGiant: return mfNoSpawn;
+ case mtHorse: return mfPassive;
+ case mtIronGolem: return mfPassive;
+ case mtMagmaCube: return mfHostile;
+ case mtMooshroom: return mfHostile;
+ case mtOcelot: return mfPassive;
+ case mtPig: return mfPassive;
+ case mtSheep: return mfPassive;
+ case mtSilverfish: return mfHostile;
+ case mtSkeleton: return mfHostile;
+ case mtSlime: return mfHostile;
+ case mtSnowGolem: return mfNoSpawn;
+ case mtSpider: return mfHostile;
+ case mtSquid: return mfWater;
+ case mtVillager: return mfPassive;
+ case mtWitch: return mfHostile;
+ case mtWither: return mfNoSpawn;
+ case mtWolf: return mfHostile;
+ case mtZombie: return mfHostile;
+ case mtZombiePigman: return mfHostile;
+
+ case mtInvalidType: break;
+ }
+ ASSERT(!"Unhandled mob type");
+ return mfUnhandled;
+}
+
+
+
+
+
+cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType)
+{
+ cFastRandom Random;
+ cMonster * toReturn = NULL;
+
+ // Create the mob entity
+ switch (a_MobType)
+ {
+ case mtMagmaCube:
+ {
+ toReturn = new cMagmaCube(Random.NextInt(2) + 1);
+ break;
+ }
+ case mtSlime:
+ {
+ toReturn = new cSlime(1 << Random.NextInt(3)); // Size 1, 2 or 4
+ break;
+ }
+ case mtSkeleton:
+ {
+ // TODO: Actual detection of spawning in Nether
+ toReturn = new cSkeleton((Random.NextInt(1) == 0) ? false : true);
+ break;
+ }
+ case mtVillager:
+ {
+ int VillagerType = Random.NextInt(6);
+ if (VillagerType == 6)
+ {
+ // Give farmers a better chance of spawning
+ VillagerType = 0;
+ }
+
+ toReturn = new cVillager((cVillager::eVillagerType)VillagerType);
+ break;
+ }
+ case mtHorse:
+ {
+ // Horses take a type (species), a colour, and a style (dots, stripes, etc.)
+ int HorseType = Random.NextInt(7);
+ int HorseColor = Random.NextInt(6);
+ int HorseStyle = Random.NextInt(6);
+ int HorseTameTimes = Random.NextInt(6) + 1;
+
+ if ((HorseType == 5) || (HorseType == 6) || (HorseType == 7))
+ {
+ // Increase chances of normal horse (zero)
+ HorseType = 0;
+ }
+
+ toReturn = new cHorse(HorseType, HorseColor, HorseStyle, HorseTameTimes);
+ break;
+ }
+
+ case mtBat: toReturn = new cBat(); break;
+ case mtBlaze: toReturn = new cBlaze(); break;
+ case mtCaveSpider: toReturn = new cCaveSpider(); break;
+ case mtChicken: toReturn = new cChicken(); break;
+ case mtCow: toReturn = new cCow(); break;
+ case mtCreeper: toReturn = new cCreeper(); break;
+ case mtEnderDragon: toReturn = new cEnderDragon(); break;
+ case mtEnderman: toReturn = new cEnderman(); break;
+ case mtGhast: toReturn = new cGhast(); break;
+ case mtGiant: toReturn = new cGiant(); break;
+ case mtIronGolem: toReturn = new cIronGolem(); break;
+ case mtMooshroom: toReturn = new cMooshroom(); break;
+ case mtOcelot: toReturn = new cOcelot(); break;
+ case mtPig: toReturn = new cPig(); break;
+ case mtSheep: toReturn = new cSheep(); break;
+ case mtSilverfish: toReturn = new cSilverfish(); break;
+ case mtSnowGolem: toReturn = new cSnowGolem(); break;
+ case mtSpider: toReturn = new cSpider(); break;
+ case mtSquid: toReturn = new cSquid(); break;
+ case mtWitch: toReturn = new cWitch(); break;
+ case mtWither: toReturn = new cWither(); break;
+ case mtWolf: toReturn = new cWolf(); break;
+ case mtZombie: toReturn = new cZombie(false); break; // TODO: Infected zombie parameter
+ case mtZombiePigman: toReturn = new cZombiePigman(); break;
+ default:
+ {
+ ASSERT(!"Unhandled mob type whilst trying to spawn mob!");
+ }
+ }
+ return toReturn;
+}
+
+
+
+
+
+int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily)
+{
+ switch (a_MobFamily)
+ {
+ case mfHostile: return 40;
+ case mfPassive: return 40;
+ case mfAmbient: return 40;
+ case mfWater: return 400;
+ case mfNoSpawn: return -1;
+ case mfUnhandled: break;
+ }
+ ASSERT(!"Unhandled mob family");
+ return -1;
+}
+
+
+
+
+
+AString cMonster::MobTypeToString(cMonster::eType a_MobType)
+{
+ // Mob types aren't sorted, so we need to search linearly:
+ for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++)
+ {
+ if (g_MobTypeNames[i].m_Type == a_MobType)
+ {
+ return g_MobTypeNames[i].m_lcName;
+ }
+ }
+
+ // Not found:
+ return "";
+}
+
+
+
+
+
+cMonster::eType cMonster::StringToMobType(const AString & a_Name)
+{
+ AString lcName = StrToLower(a_Name);
+
+ // Binary-search for the lowercase name:
+ int lo = 0, hi = ARRAYCOUNT(g_MobTypeNames) - 1;
+ while (hi - lo > 1)
+ {
+ int mid = (lo + hi) / 2;
+ int res = strcmp(g_MobTypeNames[mid].m_lcName, lcName.c_str());
+ if (res == 0)
+ {
+ return g_MobTypeNames[mid].m_Type;
+ }
+ if (res < 0)
+ {
+ lo = mid;
+ }
+ else
+ {
+ hi = mid;
+ }
+ }
+ // Range has collapsed to at most two elements, compare each:
+ if (strcmp(g_MobTypeNames[lo].m_lcName, lcName.c_str()) == 0)
+ {
+ return g_MobTypeNames[lo].m_Type;
+ }
+ if ((lo != hi) && (strcmp(g_MobTypeNames[hi].m_lcName, lcName.c_str()) == 0))
+ {
+ return g_MobTypeNames[hi].m_Type;
+ }
+
+ // Not found:
+ return mtInvalidType;
+}
+
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index b03390930..417b6d72e 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -54,14 +54,75 @@ public:
mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN,
};
+ enum eFamily
+ {
+ mfHostile = 0, // Spider, Zombies ...
+ mfPassive = 1, // Cows, Pigs
+ mfAmbient = 2, // Bats
+ mfWater = 3, // Squid
+
+ mfNoSpawn,
+ mfUnhandled, // Nothing. Be sure this is the last and the others are in order
+ } ;
+
protected:
eType m_MobType;
public:
cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height);
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
eType GetMobType() const { return m_MobType; }
+
+ // Type Function
virtual bool IsBaby (void) const { return false; }
virtual bool IsTame (void) const { return false; }
+ virtual bool IsUndead (void) const { return false; }
+
+ // Get Functions - Temporary
+
+ AString GetOwnerName (void) const { return m_OwnerName; }
+ AString GetOwnerUUID (void) const { return m_OwnerUUID; }
+ float GetDropChanceBoots() { return m_DropChanceBoots; }
+ float GetDropChanceHelmet() { return m_DropChanceHelmet; }
+ float GetDropChanceChestplate() { return m_DropChanceChestplate; }
+ float GetDropChanceLeggings() { return m_DropChanceLeggings; }
+ float GetDropChanceWeapon() { return m_DropChanceWeapon; }
+ eFamily GetMobFamily() { return mfPassive; }
+
+ // Set Functions - Temporary
+ void SetDropChanceBoots(float a_Chance) { m_DropChanceBoots = a_Chance; }
+ void SetDropChanceHelmet(float a_Chance) { m_DropChanceHelmet = a_Chance; }
+ void SetDropChanceChestplate(float a_Chance) { m_DropChanceChestplate = a_Chance; }
+ void SetDropChanceLeggings(float a_Chance) { m_DropChanceLeggings = a_Chance; }
+ void SetDropChanceWeapon(float a_Chance) { m_DropChanceWeapon = a_Chance; }
+ void SetIsTame(bool m_Tame) {}
+ void SetOwner(AString a_Name, AString a_UUID) { m_OwnerName = a_Name; m_OwnerUUID = a_UUID; }
+
+ // Ability Functions
+ bool CanPickUpLoot() { return false; }
+ void SetCanPickUpLoot(bool a_Looting) {}
+
+ // Static Functions
+ // tolua_begin
+
+ /// Translates MobType enum to a string, empty string if unknown
+ static AString MobTypeToString(eType a_MobType);
+
+ /// Translates MobType string to the enum, mtInvalidType if not recognized
+ static eType StringToMobType(const AString & a_MobTypeName);
+
+ /// Returns the mob family based on the type
+ static eFamily FamilyFromType(eType a_MobType);
+
+ /// Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family
+ static int GetSpawnDelay(cMonster::eFamily a_MobFamily);
+
+ // tolua_end
+
+ /** Creates a new object of the specified mob.
+ a_MobType is the type of the mob to be created
+ Asserts and returns null if mob type is not specified
+ */
+ static cMonster * NewMonsterFromType(eType a_MobType);
protected:
@@ -95,4 +156,8 @@ protected:
float m_DropChanceChestplate;
float m_DropChanceLeggings;
float m_DropChanceBoots;
+
+
+ AString m_OwnerName;
+ AString m_OwnerUUID;
};
diff --git a/src/Mobs/Wither.cpp b/src/Mobs/Wither.cpp
index bda216c5b..e996078dc 100644
--- a/src/Mobs/Wither.cpp
+++ b/src/Mobs/Wither.cpp
@@ -11,7 +11,8 @@
cWither::cWither(void) :
- super("Wither", mtWither, "mob.wither.hurt", "mob.wither.death", 0.9, 4.0)
+ super("Wither", mtWither, "mob.wither.hurt", "mob.wither.death", 0.9, 4.0),
+ m_WitherInvulnerableTicks(0)
{
SetMaxHealth(300);
}
diff --git a/src/Mobs/Wither.h b/src/Mobs/Wither.h
index cc327741a..b0d1f4a3d 100644
--- a/src/Mobs/Wither.h
+++ b/src/Mobs/Wither.h
@@ -19,12 +19,18 @@ public:
/** Returns whether the wither is invulnerable to arrows. */
bool IsArmored(void) const;
- int GetWitherInvulnerableTicks() const { return 0; }
+ int GetWitherInvulnerableTicks() const { return m_WitherInvulnerableTicks; }
+ void SetWitherInvulnerableTicks(unsigned int a_Ticks) { m_WitherInvulnerableTicks = a_Ticks; }
// cEntity overrides
virtual bool Initialize(cWorld & a_World) override;
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+private:
+
+ /** The number of ticks of invulnerability left after being initially created. Zero once invulnerability has expired. */
+ unsigned int m_WitherInvulnerableTicks;
+
} ;