diff options
author | Samuel Barney <samjbarney@gmail.com> | 2014-08-21 18:23:35 +0200 |
---|---|---|
committer | Samuel Barney <samjbarney@gmail.com> | 2014-08-21 18:23:35 +0200 |
commit | badced2acd355680685efdfc3ca728338201920f (patch) | |
tree | 9fb560de7c6b60bc11f4514c6b44511791622932 | |
parent | Removed the rest of the references to cNewMonster (diff) | |
download | cuberite-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.cpp | 266 | ||||
-rw-r--r-- | src/Mobs/Monster.h | 65 | ||||
-rw-r--r-- | src/Mobs/Wither.cpp | 3 | ||||
-rw-r--r-- | src/Mobs/Wither.h | 8 |
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; + } ; |