1
0

Add Zombie Villagers

This commit is contained in:
Bond-009 2018-02-03 12:24:19 +01:00 committed by Alexander Harkness
parent df8d7332d0
commit 8438def87e
No known key found for this signature in database
GPG Key ID: 5187245ADF160B76
25 changed files with 406 additions and 97 deletions

View File

@ -9306,6 +9306,10 @@ a_Player:OpenWindow(Window);
{
Notes = "",
},
mtZombieVillager =
{
Notes = "",
},
},
ConstantGroups =
{
@ -17065,6 +17069,7 @@ end
"mtWolf",
"mtZombie",
"mtZombiePigman",
"mtZombieVillager",
"mtMax",
},
TextBefore = [[

View File

@ -220,3 +220,10 @@ AttackRate=1.0
IsFireproof=1
MaxHealth=20
SightDistance=25.0
[ZombieVillager]
AttackDamage=4.0
AttackRange=2.0
AttackRate=1.0
MaxHealth=20
SightDistance=25.0

View File

@ -16,37 +16,38 @@ struct
const char * String;
} g_EntityTypes[] =
{
{entBat, "Bat"},
{entBlaze, "Blaze"},
{entCaveSpider, "CaveSpider"},
{entChicken, "Chicken"},
{entCow, "Cow"},
{entCreeper, "Creeper"},
{entEnderDragon, "EnderDragon"},
{entEnderman, "Enderman"},
{entGhast, "Ghast"},
{entGiant, "Giant"},
{entGuardian, "Guardian"},
{entLavaSlime, "LavaSlime"},
{entMushroomCow, "MushroomCow"},
{entOzelot, "Ozelot"},
{entPig, "Pig"},
{entPigZombie, "PigZombie"},
{entRabbit, "Rabbit"},
{entSheep, "Sheep"},
{entSilverfish, "Slverfish"},
{entSkeleton, "Skeleton"},
{entSlime, "Slime"},
{entSnowMan, "SnowMan"},
{entSpider, "Spider"},
{entSquid, "Squid"},
{entVillager, "Villager"},
{entVillagerGolem, "VillagerGolem"},
{entWitch, "Witch"},
{entWitherBoss, "WitherBoss"},
{entWolf, "Wolf"},
{entZombie, "Zombie"},
{entUnknown, "Unknown"},
{entBat, "Bat"},
{entBlaze, "Blaze"},
{entCaveSpider, "CaveSpider"},
{entChicken, "Chicken"},
{entCow, "Cow"},
{entCreeper, "Creeper"},
{entEnderDragon, "EnderDragon"},
{entEnderman, "Enderman"},
{entGhast, "Ghast"},
{entGiant, "Giant"},
{entGuardian, "Guardian"},
{entLavaSlime, "LavaSlime"},
{entMushroomCow, "MushroomCow"},
{entOzelot, "Ozelot"},
{entPig, "Pig"},
{entPigZombie, "PigZombie"},
{entRabbit, "Rabbit"},
{entSheep, "Sheep"},
{entSilverfish, "Slverfish"},
{entSkeleton, "Skeleton"},
{entSlime, "Slime"},
{entSnowMan, "SnowMan"},
{entSpider, "Spider"},
{entSquid, "Squid"},
{entVillager, "Villager"},
{entVillagerGolem, "VillagerGolem"},
{entWitch, "Witch"},
{entWitherBoss, "WitherBoss"},
{entWolf, "Wolf"},
{entZombie, "Zombie"},
{entZombieVillager, "ZombieVillager"},
{entUnknown, "Unknown"},
} ;

View File

@ -45,6 +45,7 @@ enum eEntityType
entWitherBoss,
entWolf,
entZombie,
entZombieVillager,
entUnknown,
entMax = entUnknown,
} ;

View File

@ -1079,6 +1079,7 @@ enum ENUM_ITEM_META : short
E_META_SPAWN_EGG_PRIMED_TNT = 20,
E_META_SPAWN_EGG_FALLING_BLOCK = 21,
E_META_SPAWN_EGG_FIREWORK = 22,
E_META_SPAWN_EGG_ZOMBIE_VILLAGER = 27,
E_META_SPAWN_EGG_BOAT = 41,
E_META_SPAWN_EGG_MINECART = 42,
E_META_SPAWN_EGG_MINECART_CHEST = 43,

View File

@ -456,9 +456,10 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
switch (Monster->GetMobType())
{
case mtSkeleton:
case mtZombie:
case mtWither:
case mtZombie:
case mtZombiePigman:
case mtZombieVillager:
{
a_TDI.FinalDamage += 2.5f * SmiteLevel;
break;

View File

@ -87,11 +87,8 @@ public:
case E_META_SPAWN_EGG_WOLF: return mtWolf;
case E_META_SPAWN_EGG_ZOMBIE: return mtZombie;
case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return mtZombiePigman;
case E_META_SPAWN_EGG_ZOMBIE_VILLAGER: return mtZombieVillager;
default: return mtInvalidType;
}
return mtInvalidType;
}
} ;

View File

@ -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})

View File

@ -30,3 +30,4 @@
#include "Wolf.h"
#include "Zombie.h"
#include "ZombiePigman.h"
#include "ZombieVillager.h"

View File

@ -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> cMonster::NewMonsterFromType(eMonsterType a_MobType)
{
return cpp14::make_unique<cSlime>(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<cVillager>(static_cast<cVillager::eVillagerType>(VillagerType));
}
case mtVillager: return cpp14::make_unique<cVillager>(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> cMonster::NewMonsterFromType(eMonsterType a_MobType)
return cpp14::make_unique<cHorse>(HorseType, HorseColor, HorseStyle, HorseTameTimes);
}
case mtZombieVillager:
{
return cpp14::make_unique<cZombieVillager>(cVillager::GetRandomProfession());
}
case mtBat: return cpp14::make_unique<cBat>();
case mtBlaze: return cpp14::make_unique<cBlaze>();
case mtCaveSpider: return cpp14::make_unique<cCaveSpider>();

View File

@ -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

View File

@ -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<cMonster *>(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<cVillager::eVillagerType>(Profession);
}

View File

@ -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. */

View File

@ -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)
{
}

View File

@ -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;
} ;

View File

@ -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;
}
}

33
src/Mobs/ZombieVillager.h Normal file
View File

@ -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;
} ;

View File

@ -1008,11 +1008,11 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
a_Pkt.WriteBEUInt8(ZOMBIE_TYPE);
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0); // TODO: This actually encodes the zombie villager profession, but that isn't implemented yet.
a_Pkt.WriteVarInt32(0);
a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING);
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(Zombie.IsConverting());
a_Pkt.WriteBool(false);
break;
} // case mtZombie
@ -1025,6 +1025,23 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break;
} // case mtZombiePigman
case mtZombieVillager:
{
auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY);
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(ZombieVillager.IsBaby());
a_Pkt.WriteBEUInt8(ZOMBIE_TYPE);
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(ZombieVillager.GetProfession());
a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING);
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(ZombieVillager.ConversionTime() != -1);
break;
} // case mtZombieVillager
default: break;
} // switch (a_Mob.GetType())
}

View File

@ -1182,15 +1182,6 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY);
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(Zombie.IsBaby());
// These don't exist
// a_Pkt.WriteBEUInt8(ZOMBIE_TYPE);
// a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
// a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0);
// a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING);
// a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
// a_Pkt.WriteBool(Zombie.IsConverting());
break;
} // case mtZombie
@ -1203,6 +1194,23 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break;
} // case mtZombiePigman
case mtZombieVillager:
{
auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY);
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(ZombieVillager.IsBaby());
a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_CONVERTING);
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(static_cast<UInt32>(ZombieVillager.ConversionTime()));
a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_PROFESSION);
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(static_cast<UInt32>(ZombieVillager.GetProfession()));
break;
} // case mtZombieVillager
default: break;
} // switch (a_Mob.GetType())
}

View File

@ -908,9 +908,6 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
// a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
// a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0);
// a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING);
// a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
// a_Pkt.WriteBool(Zombie.IsConverting());
break;
} // case mtZombie
@ -923,6 +920,23 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
break;
} // case mtZombiePigman
case mtZombieVillager:
{
auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY);
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(ZombieVillager.IsBaby());
a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_CONVERTING);
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(static_cast<UInt32>(ZombieVillager.ConversionTime()));
a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_PROFESSION);
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(static_cast<UInt32>(ZombieVillager.GetProfession()));
break;
} // case mtZombieVillager
case mtBlaze:
case mtEnderDragon:
case mtGuardian:

View File

@ -3825,9 +3825,9 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
a_Pkt.WriteBEUInt8(0x0c);
a_Pkt.WriteBEInt8(Zombie.IsBaby() ? 1 : -1);
a_Pkt.WriteBEUInt8(0x0d);
a_Pkt.WriteBEUInt8(Zombie.IsVillagerZombie() ? 1 : 0);
a_Pkt.WriteBEUInt8(0);
a_Pkt.WriteBEUInt8(0x0e);
a_Pkt.WriteBEUInt8(Zombie.IsConverting() ? 1 : 0);
a_Pkt.WriteBEUInt8(0);
break;
} // case mtZombie
@ -3839,6 +3839,18 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break;
} // case mtZombiePigman
case mtZombieVillager:
{
auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
a_Pkt.WriteBEUInt8(0x0c);
a_Pkt.WriteBEInt8(ZombieVillager.IsBaby() ? 1 : -1);
a_Pkt.WriteBEUInt8(0x0d);
a_Pkt.WriteBEUInt8(1);
a_Pkt.WriteBEUInt8(0x0e);
a_Pkt.WriteBEUInt8((ZombieVillager.ConversionTime() == -1) ? 0 : 1);
break;
} // case mtZombieVillager
default: break;
} // switch (a_Mob.GetType())
}

View File

@ -4329,11 +4329,11 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
a_Pkt.WriteBEUInt8(12); // Index 12: Is a villager
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0); // TODO: This actually encodes the zombie villager profession, but that isn't implemented yet.
a_Pkt.WriteVarInt32(0);
a_Pkt.WriteBEUInt8(13); // Index 13: Is converting
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(Zombie.IsConverting());
a_Pkt.WriteBool(false);
break;
} // case mtZombie
@ -4346,6 +4346,23 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break;
} // case mtZombiePigman
case mtZombieVillager:
{
auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(ZombieVillager.IsBaby());
a_Pkt.WriteBEUInt8(12); // Index 12: Is a villager
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(ZombieVillager.GetProfession());
a_Pkt.WriteBEUInt8(13); // Index 13: Is converting
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(ZombieVillager.ConversionTime() != -1);
break;
} // case mtZombieVillager
default: break;
} // switch (a_Mob.GetType())
}

View File

@ -738,10 +738,17 @@ public:
case mtVillager: EntityClass = "Villager"; break;
case mtWitch: EntityClass = "Witch"; break;
case mtWither: EntityClass = "WitherBoss"; break;
<<<<<<< HEAD
case mtWitherSkeleton: EntityClass = "WitherSkeleton"; break;
case mtWolf: EntityClass = "Wolf"; break;
case mtZombie: EntityClass = "Zombie"; break;
case mtZombiePigman: EntityClass = "PigZombie"; break;
=======
case mtWolf: EntityClass = "Wolf"; break;
case mtZombie: EntityClass = "Zombie"; break;
case mtZombiePigman: EntityClass = "PigZombie"; break;
case mtZombieVillager: EntityClass = "ZombieVillager"; break;
>>>>>>> Add Zombie Villagers
default:
{
ASSERT(!"Unhandled monster type");
@ -901,10 +908,7 @@ public:
}
case mtZombie:
{
const cZombie *Zombie = static_cast<const cZombie *>(a_Monster);
mWriter.AddByte("IsVillager", Zombie->IsVillagerZombie() ? 1 : 0);
mWriter.AddByte("IsConverting", Zombie->IsConverting() ? 1 : 0);
mWriter.AddInt ("Age", Zombie->GetAge());
mWriter.AddInt("Age", static_cast<const cZombie *>(a_Monster)->GetAge());
break;
}
case mtZombiePigman:
@ -912,6 +916,13 @@ public:
mWriter.AddInt("Age", static_cast<const cZombiePigman *>(a_Monster)->GetAge());
break;
}
case mtZombieVillager:
{
const cZombieVillager *ZombieVillager = reinterpret_cast<const cZombieVillager *>(a_Monster);
mWriter.AddInt("Profession", ZombieVillager->GetProfession());
mWriter.AddInt("ConversionTime", ZombieVillager->ConversionTime());
mWriter.AddInt("Age", ZombieVillager->GetAge());
}
case mtBlaze:
case mtCaveSpider:
case mtChicken:

View File

@ -1568,6 +1568,8 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
{ "minecraft:zombie", &cWSSAnvil::LoadZombieFromNBT },
{ "PigZombie", &cWSSAnvil::LoadPigZombieFromNBT },
{ "minecraft:zombie_pigman", &cWSSAnvil::LoadPigZombieFromNBT },
{ "ZombieVillager", &cWSSAnvil::LoadZombieVillagerFromNBT },
{ "minecraft:zombie_villager", &cWSSAnvil::LoadZombieVillagerFromNBT },
};
auto it = EntityTypeToFunction.find(AString(a_IDTag, a_IDTagLength));
@ -2968,15 +2970,7 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N
void cWSSAnvil::LoadZombieFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
int IsVillagerIdx = a_NBT.FindChildByName(a_TagIdx, "IsVillager");
if (IsVillagerIdx < 0)
{
return;
}
bool IsVillagerZombie = ((a_NBT.GetByte(IsVillagerIdx) == 1) ? true : false);
std::unique_ptr<cZombie> Monster = cpp14::make_unique<cZombie>(IsVillagerZombie);
std::unique_ptr<cZombie> Monster = cpp14::make_unique<cZombie>();
if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;
@ -2994,7 +2988,7 @@ void cWSSAnvil::LoadZombieFromNBT(cEntityList & a_Entities, const cParsedNBT & a
switch (a_NBT.GetType(AgeableIdx))
{
case TAG_Byte: Age = static_cast<int>(a_NBT.GetByte(AgeableIdx)); break;
case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break;
case TAG_Int: Age = a_NBT.GetInt(AgeableIdx); break;
default: Age = 0; break;
}
Monster->SetAge(Age);
@ -3040,6 +3034,49 @@ void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT
void cWSSAnvil::LoadZombieVillagerFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
int ProfessionIdx = a_NBT.FindChildByName(a_TagIdx, "Profession");
if (ProfessionIdx < 0)
{
return;
}
cVillager::eVillagerType Profession = static_cast<cVillager::eVillagerType>(a_NBT.GetInt(ProfessionIdx));
std::unique_ptr<cZombieVillager> Monster = cpp14::make_unique<cZombieVillager>(Profession);
if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;
}
if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;
}
// TODO: Conversion time
int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age");
if (AgeableIdx > 0)
{
int Age;
switch (a_NBT.GetType(AgeableIdx))
{
case TAG_Byte: Age = static_cast<int>(a_NBT.GetByte(AgeableIdx)); break;
case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break;
default: Age = 0; break;
}
Monster->SetAge(Age);
}
a_Entities.emplace_back(std::move(Monster));
}
std::pair<AString, cUUID> cWSSAnvil::LoadEntityOwner(const cParsedNBT & a_NBT, int a_TagIdx)
{
// Load the owner information. OwnerUUID or Owner may be specified, possibly both:

View File

@ -232,6 +232,7 @@ protected:
void LoadWolfFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadPigZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadZombieVillagerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
/** Loads the owner name and UUID from the entity at the specified NBT tag.
Returns a pair of {name, uuid}. If the entity is not owned, name is an empty string and uuid is nil. */