From 8438def87e40e43fd66d38dbf8cc287cea7de29b Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Sat, 3 Feb 2018 12:24:19 +0100 Subject: Add Zombie Villagers --- src/Mobs/CMakeLists.txt | 6 ++- src/Mobs/IncludeAllMonsters.h | 1 + src/Mobs/Monster.cpp | 20 ++++------ src/Mobs/MonsterTypes.h | 36 ++++++++++++++++++ src/Mobs/Villager.cpp | 32 +++++++++++++++- src/Mobs/Villager.h | 4 ++ src/Mobs/Zombie.cpp | 6 +-- src/Mobs/Zombie.h | 10 +---- src/Mobs/ZombieVillager.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++ src/Mobs/ZombieVillager.h | 33 ++++++++++++++++ 10 files changed, 207 insertions(+), 28 deletions(-) create mode 100644 src/Mobs/ZombieVillager.cpp create mode 100644 src/Mobs/ZombieVillager.h (limited to 'src/Mobs') diff --git a/src/Mobs/CMakeLists.txt b/src/Mobs/CMakeLists.txt index 15456595c..579ba8938 100644 --- a/src/Mobs/CMakeLists.txt +++ b/src/Mobs/CMakeLists.txt @@ -36,7 +36,8 @@ SET (SRCS WitherSkeleton.cpp Wolf.cpp Zombie.cpp - ZombiePigman.cpp) + ZombiePigman.cpp + ZombieVillager.cpp) SET (HDRS AggressiveMonster.h @@ -78,7 +79,8 @@ SET (HDRS WitherSkeleton.h Wolf.h Zombie.h - ZombiePigman.h) + ZombiePigman.h + ZombieVillager.h) if(NOT MSVC) add_library(Mobs ${SRCS} ${HDRS}) diff --git a/src/Mobs/IncludeAllMonsters.h b/src/Mobs/IncludeAllMonsters.h index 17a9dfacd..afb79c97c 100644 --- a/src/Mobs/IncludeAllMonsters.h +++ b/src/Mobs/IncludeAllMonsters.h @@ -30,3 +30,4 @@ #include "Wolf.h" #include "Zombie.h" #include "ZombiePigman.h" +#include "ZombieVillager.h" diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 5e3026a57..d20afa589 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -69,6 +69,7 @@ static const struct {mtWolf, "wolf", "Wolf", "wolf"}, {mtZombie, "zombie", "Zombie", "zombie"}, {mtZombiePigman, "zombiepigman", "PigZombie", "zombie_pigman"}, + {mtZombieVillager, "zombievillager", "ZombieVillager", "zombie_villager"}, } ; @@ -662,6 +663,7 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI) case mtWitherSkeleton: case mtZombie: case mtZombiePigman: + case mtZombieVillager: case mtSlime: case mtMagmaCube: { @@ -1078,6 +1080,7 @@ cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type) case mtWolf: return mfPassive; case mtZombie: return mfHostile; case mtZombiePigman: return mfHostile; + case mtZombieVillager: return mfHostile; default: { @@ -1176,17 +1179,7 @@ std::unique_ptr cMonster::NewMonsterFromType(eMonsterType a_MobType) { return cpp14::make_unique(1 << Random.RandInt(2)); // Size 1, 2 or 4 } - case mtVillager: - { - int VillagerType = Random.RandInt(6); - if (VillagerType == 6) - { - // Give farmers a better chance of spawning - VillagerType = 0; - } - - return cpp14::make_unique(static_cast(VillagerType)); - } + case mtVillager: return cpp14::make_unique(cVillager::GetRandomProfession()); case mtHorse: { // Horses take a type (species), a colour, and a style (dots, stripes, etc.) @@ -1203,7 +1196,10 @@ std::unique_ptr cMonster::NewMonsterFromType(eMonsterType a_MobType) return cpp14::make_unique(HorseType, HorseColor, HorseStyle, HorseTameTimes); } - + case mtZombieVillager: + { + return cpp14::make_unique(cVillager::GetRandomProfession()); + } case mtBat: return cpp14::make_unique(); case mtBlaze: return cpp14::make_unique(); case mtCaveSpider: return cpp14::make_unique(); diff --git a/src/Mobs/MonsterTypes.h b/src/Mobs/MonsterTypes.h index 7a864fda4..6d3c57852 100644 --- a/src/Mobs/MonsterTypes.h +++ b/src/Mobs/MonsterTypes.h @@ -11,6 +11,7 @@ enum eMonsterType { mtInvalidType = -1, +<<<<<<< HEAD mtBat, mtBlaze, mtCaveSpider, @@ -43,6 +44,41 @@ enum eMonsterType mtWolf, mtZombie, mtZombiePigman, +======= + mtBat = E_META_SPAWN_EGG_BAT, + mtBlaze = E_META_SPAWN_EGG_BLAZE, + mtCaveSpider = E_META_SPAWN_EGG_CAVE_SPIDER, + mtChicken = E_META_SPAWN_EGG_CHICKEN, + mtCow = E_META_SPAWN_EGG_COW, + mtCreeper = E_META_SPAWN_EGG_CREEPER, + mtEnderDragon = E_META_SPAWN_EGG_ENDER_DRAGON, + mtEnderman = E_META_SPAWN_EGG_ENDERMAN, + mtGhast = E_META_SPAWN_EGG_GHAST, + mtGiant = E_META_SPAWN_EGG_GIANT, + mtGuardian = E_META_SPAWN_EGG_GUARDIAN, + mtHorse = E_META_SPAWN_EGG_HORSE, + mtIronGolem = E_META_SPAWN_EGG_IRON_GOLEM, + mtMagmaCube = E_META_SPAWN_EGG_MAGMA_CUBE, + mtMooshroom = E_META_SPAWN_EGG_MOOSHROOM, + mtOcelot = E_META_SPAWN_EGG_OCELOT, + mtPig = E_META_SPAWN_EGG_PIG, + mtRabbit = E_META_SPAWN_EGG_RABBIT, + mtSheep = E_META_SPAWN_EGG_SHEEP, + mtSilverfish = E_META_SPAWN_EGG_SILVERFISH, + mtSkeleton = E_META_SPAWN_EGG_SKELETON, + mtSlime = E_META_SPAWN_EGG_SLIME, + mtSnowGolem = E_META_SPAWN_EGG_SNOW_GOLEM, + mtSpider = E_META_SPAWN_EGG_SPIDER, + mtSquid = E_META_SPAWN_EGG_SQUID, + mtVillager = E_META_SPAWN_EGG_VILLAGER, + mtWitch = E_META_SPAWN_EGG_WITCH, + mtWither = E_META_SPAWN_EGG_WITHER, + mtWolf = E_META_SPAWN_EGG_WOLF, + mtZombie = E_META_SPAWN_EGG_ZOMBIE, + mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN, + mtZombieVillager = E_META_SPAWN_EGG_ZOMBIE_VILLAGER, + mtMax = 120, // This is just a hotfix for https://forum.cuberite.org/thread-1616.html. Tolua is too bad to find the highest value, so this is needed. +>>>>>>> Add Zombie Villagers } ; // tolua_end diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 9558ba536..eca8ed2b6 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -107,6 +107,26 @@ void cVillager::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) + +void cVillager::KilledBy(TakeDamageInfo & a_TDI) +{ + super::KilledBy(a_TDI); + + // TODO: 0% chance on Easy, 50% chance on Normal and 100% chance on Hard + if (GetRandomProvider().RandBool(0.5) && (a_TDI.Attacker != nullptr) && (a_TDI.Attacker->IsMob())) + { + eMonsterType MonsterType = (static_cast(a_TDI.Attacker)->GetMobType()); + if ((MonsterType == mtZombie) || (MonsterType == mtZombieVillager)) + { + m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtZombieVillager, false); + } + } +} + + + + + //////////////////////////////////////////////////////////////////////////////// // Farmer functions: @@ -203,7 +223,17 @@ bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType) { return true; } + default: return false; } - return false; } + + + + +cVillager::eVillagerType cVillager::GetRandomProfession() +{ + int Profession = GetRandomProvider().RandInt(cVillager::eVillagerType::vtMax - 1); + + return static_cast(Profession); +} diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index b9a0b7675..2d6644193 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -29,9 +29,13 @@ public: CLASS_PROTODEF(cVillager) + /** Returns a random Profession. */ + static eVillagerType GetRandomProfession(); + // cEntity overrides virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void Tick (std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; + virtual void KilledBy (TakeDamageInfo & a_TDI) override; // cVillager functions /** return true if the given blocktype are: crops, potatoes or carrots. */ diff --git a/src/Mobs/Zombie.cpp b/src/Mobs/Zombie.cpp index 451255ed2..02c1efa86 100644 --- a/src/Mobs/Zombie.cpp +++ b/src/Mobs/Zombie.cpp @@ -9,10 +9,8 @@ -cZombie::cZombie(bool a_IsVillagerZombie) : - super("Zombie", mtZombie, "entity.zombie.hurt", "entity.zombie.death", "entity.zombie.ambient", 0.6, 1.8), - m_IsVillagerZombie(a_IsVillagerZombie), - m_IsConverting(false) +cZombie::cZombie() : + super("Zombie", mtZombie, "entity.zombie.hurt", "entity.zombie.death", "entity.zombie.ambient", 0.6, 1.8) { } diff --git a/src/Mobs/Zombie.h b/src/Mobs/Zombie.h index 47a9f1904..20f59a627 100644 --- a/src/Mobs/Zombie.h +++ b/src/Mobs/Zombie.h @@ -12,21 +12,13 @@ class cZombie : typedef cAggressiveMonster super; public: - cZombie(bool a_IsVillagerZombie); + cZombie(); CLASS_PROTODEF(cZombie) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool IsUndead(void) override { return true; } - bool IsVillagerZombie(void) const { return m_IsVillagerZombie; } - bool IsConverting (void) const { return m_IsConverting; } - -private: - - bool m_IsVillagerZombie; - bool m_IsConverting; - } ; diff --git a/src/Mobs/ZombieVillager.cpp b/src/Mobs/ZombieVillager.cpp new file mode 100644 index 000000000..9d17e6038 --- /dev/null +++ b/src/Mobs/ZombieVillager.cpp @@ -0,0 +1,87 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "ZombieVillager.h" +#include "../World.h" +#include "../LineBlockTracer.h" +#include "../Entities/Player.h" + + + + + +cZombieVillager::cZombieVillager(cVillager::eVillagerType a_Profession) : + super("ZombieVillager", mtZombieVillager, "entity.zombie_villager.hurt", "entity.zombie_villager.death", "entity.ambient", 0.6, 1.8), + m_ConversionTime(-1), + m_Profession(a_Profession) +{ + SetBurnsInDaylight(true); +} + + + + + +void cZombieVillager::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + unsigned int LootingLevel = 0; + if (a_Killer != nullptr) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ROTTEN_FLESH); + cItems RareDrops; + RareDrops.Add(cItem(E_ITEM_IRON)); + RareDrops.Add(cItem(E_ITEM_CARROT)); + RareDrops.Add(cItem(E_ITEM_POTATO)); + AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); + AddRandomArmorDropItem(a_Drops, LootingLevel); + AddRandomWeaponDropItem(a_Drops, LootingLevel); +} + + + + + +void cZombieVillager::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + if (!IsTicking()) + { + // The base class tick destroyed us + return; + } + + LOGD("Conversion time: %d", m_ConversionTime); + + if (m_ConversionTime == 0) + { + m_World->BroadcastSoundEffect("entity.zombie_villager.cure", GetPosition(), 1.0f, 1.0f); + Destroy(); + m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtVillager, false); + } + else if (m_ConversionTime > 0) + { + m_ConversionTime--; + } +} + + + + + +void cZombieVillager::OnRightClicked(cPlayer & a_Player) +{ + super::OnRightClicked(a_Player); + + const cItem & EquippedItem = a_Player.GetEquippedItem(); + if ((EquippedItem.m_ItemType == E_ITEM_GOLDEN_APPLE) && GetEntityEffect(cEntityEffect::effWeakness) != nullptr) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + + m_ConversionTime = 6000; + } +} diff --git a/src/Mobs/ZombieVillager.h b/src/Mobs/ZombieVillager.h new file mode 100644 index 000000000..c4c4ae3d1 --- /dev/null +++ b/src/Mobs/ZombieVillager.h @@ -0,0 +1,33 @@ +#pragma once + +#include "AggressiveMonster.h" +#include "Villager.h" + + + + + +class cZombieVillager : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cZombieVillager(cVillager::eVillagerType a_Profession); + + CLASS_PROTODEF(cZombieVillager) + + virtual void GetDrops (cItems & a_Drops, cEntity * a_Killer = nullptr) override; + virtual void Tick (std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; + virtual void OnRightClicked (cPlayer & a_Player) override; + virtual bool IsUndead (void) override { return true; } + + int ConversionTime (void) const { return m_ConversionTime; } + cVillager::eVillagerType GetProfession (void) const { return m_Profession; } + +private: + + int m_ConversionTime; + cVillager::eVillagerType m_Profession; + +} ; -- cgit v1.2.3