1
0
Fork 0

Implement wither skeletons (#4563)

This commit is contained in:
Mat 2020-04-04 14:44:17 +03:00 committed by GitHub
parent aac592f985
commit 60bcc06f43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 355 additions and 231 deletions

View File

@ -9290,6 +9290,10 @@ a_Player:OpenWindow(Window);
{ {
Notes = "", Notes = "",
}, },
mtWitherSkeleton =
{
Notes = "",
},
mtWolf = mtWolf =
{ {
Notes = "", Notes = "",
@ -16686,6 +16690,10 @@ end
{ {
Notes = "A flag in the metadata of heads that indicates that the head is a zombie head.", Notes = "A flag in the metadata of heads that indicates that the head is a zombie head.",
}, },
E_META_SPAWN_EGG_WITHER_SKELETON =
{
Notes = ""
},
E_META_SPONGE_DRY = E_META_SPONGE_DRY =
{ {
Notes = "A flag in the metadata of sponges that indicates that the sponge is dry.", Notes = "A flag in the metadata of sponges that indicates that the sponge is dry.",
@ -16790,6 +16798,10 @@ end
{ {
Notes = "Something concerning (i.e. reload) is about to happen", Notes = "Something concerning (i.e. reload) is about to happen",
}, },
mtWitherSkeleton =
{
Notes = ""
},
hMain = hMain =
{ {
Notes = "The main hand", Notes = "The main hand",
@ -17049,6 +17061,7 @@ end
"mtVillager", "mtVillager",
"mtWitch", "mtWitch",
"mtWither", "mtWither",
"mtWitherSkeleton",
"mtWolf", "mtWolf",
"mtZombie", "mtZombie",
"mtZombiePigman", "mtZombiePigman",

View File

@ -190,6 +190,14 @@ AttackRate=1.0
MaxHealth=26 MaxHealth=26
SightDistance=25.0 SightDistance=25.0
[WitherSkeleton]
AttackDamage=5.0
AttackRange=1.0
AttackRate=1.0
IsFireproof=1
MaxHealth=20
SightDistance=25.0
[Wolf] [Wolf]
AttackDamage=8.0 AttackDamage=8.0
AttackRange=1.0 AttackRange=1.0

View File

@ -1063,6 +1063,7 @@ enum ENUM_ITEM_META : short
// See also cMonster::eType, since monster type and spawn egg meta are the same // See also cMonster::eType, since monster type and spawn egg meta are the same
E_META_SPAWN_EGG_PICKUP = 1, E_META_SPAWN_EGG_PICKUP = 1,
E_META_SPAWN_EGG_EXPERIENCE_ORB = 2, E_META_SPAWN_EGG_EXPERIENCE_ORB = 2,
E_META_SPAWN_EGG_WITHER_SKELETON = 5,
E_META_SPAWN_EGG_LEASH_KNOT = 8, E_META_SPAWN_EGG_LEASH_KNOT = 8,
E_META_SPAWN_EGG_PAINTING = 9, E_META_SPAWN_EGG_PAINTING = 9,
E_META_SPAWN_EGG_ARROW = 10, E_META_SPAWN_EGG_ARROW = 10,

View File

@ -60,32 +60,33 @@ public:
{ {
switch (a_ItemDamage) switch (a_ItemDamage)
{ {
case E_META_SPAWN_EGG_BAT: return mtBat; case E_META_SPAWN_EGG_BAT: return mtBat;
case E_META_SPAWN_EGG_BLAZE: return mtBlaze; case E_META_SPAWN_EGG_BLAZE: return mtBlaze;
case E_META_SPAWN_EGG_CAVE_SPIDER: return mtCaveSpider; case E_META_SPAWN_EGG_CAVE_SPIDER: return mtCaveSpider;
case E_META_SPAWN_EGG_CHICKEN: return mtChicken; case E_META_SPAWN_EGG_CHICKEN: return mtChicken;
case E_META_SPAWN_EGG_COW: return mtCow; case E_META_SPAWN_EGG_COW: return mtCow;
case E_META_SPAWN_EGG_CREEPER: return mtCreeper; case E_META_SPAWN_EGG_CREEPER: return mtCreeper;
case E_META_SPAWN_EGG_ENDERMAN: return mtEnderman; case E_META_SPAWN_EGG_ENDERMAN: return mtEnderman;
case E_META_SPAWN_EGG_GHAST: return mtGhast; case E_META_SPAWN_EGG_GHAST: return mtGhast;
case E_META_SPAWN_EGG_GUARDIAN: return mtGuardian; case E_META_SPAWN_EGG_GUARDIAN: return mtGuardian;
case E_META_SPAWN_EGG_HORSE: return mtHorse; case E_META_SPAWN_EGG_HORSE: return mtHorse;
case E_META_SPAWN_EGG_MAGMA_CUBE: return mtMagmaCube; case E_META_SPAWN_EGG_MAGMA_CUBE: return mtMagmaCube;
case E_META_SPAWN_EGG_MOOSHROOM: return mtMooshroom; case E_META_SPAWN_EGG_MOOSHROOM: return mtMooshroom;
case E_META_SPAWN_EGG_OCELOT: return mtOcelot; case E_META_SPAWN_EGG_OCELOT: return mtOcelot;
case E_META_SPAWN_EGG_PIG: return mtPig; case E_META_SPAWN_EGG_PIG: return mtPig;
case E_META_SPAWN_EGG_RABBIT: return mtRabbit; case E_META_SPAWN_EGG_RABBIT: return mtRabbit;
case E_META_SPAWN_EGG_SHEEP: return mtSheep; case E_META_SPAWN_EGG_SHEEP: return mtSheep;
case E_META_SPAWN_EGG_SILVERFISH: return mtSilverfish; case E_META_SPAWN_EGG_SILVERFISH: return mtSilverfish;
case E_META_SPAWN_EGG_SKELETON: return mtSkeleton; case E_META_SPAWN_EGG_SKELETON: return mtSkeleton;
case E_META_SPAWN_EGG_SLIME: return mtSlime; case E_META_SPAWN_EGG_SLIME: return mtSlime;
case E_META_SPAWN_EGG_SPIDER: return mtSpider; case E_META_SPAWN_EGG_SPIDER: return mtSpider;
case E_META_SPAWN_EGG_SQUID: return mtSquid; case E_META_SPAWN_EGG_SQUID: return mtSquid;
case E_META_SPAWN_EGG_VILLAGER: return mtVillager; case E_META_SPAWN_EGG_VILLAGER: return mtVillager;
case E_META_SPAWN_EGG_WITCH: return mtWitch; case E_META_SPAWN_EGG_WITCH: return mtWitch;
case E_META_SPAWN_EGG_WOLF: return mtWolf; case E_META_SPAWN_EGG_WITHER_SKELETON: return mtWitherSkeleton;
case E_META_SPAWN_EGG_ZOMBIE: return mtZombie; case E_META_SPAWN_EGG_WOLF: return mtWolf;
case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return mtZombiePigman; case E_META_SPAWN_EGG_ZOMBIE: return mtZombie;
case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return mtZombiePigman;
} }
return mtInvalidType; return mtInvalidType;
} }

View File

@ -287,6 +287,18 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
); );
} }
case mtWitherSkeleton:
{
return (
(targetBlock == E_BLOCK_AIR) &&
(blockAbove == E_BLOCK_AIR) &&
(!cBlockInfo::IsTransparent(blockBelow)) &&
(skyLight <= 7) &&
(blockLight <= 7) &&
(random.RandBool(0.6))
);
}
case mtWolf: case mtWolf:
{ {
return ( return (
@ -443,6 +455,7 @@ std::set<eMonsterType> cMobSpawner::GetAllowedMobTypes(EMCSBiome a_Biome)
ListOfSpawnables.insert(mtBlaze); ListOfSpawnables.insert(mtBlaze);
ListOfSpawnables.insert(mtGhast); ListOfSpawnables.insert(mtGhast);
ListOfSpawnables.insert(mtMagmaCube); ListOfSpawnables.insert(mtMagmaCube);
ListOfSpawnables.insert(mtWitherSkeleton);
ListOfSpawnables.insert(mtZombiePigman); ListOfSpawnables.insert(mtZombiePigman);
return ListOfSpawnables; return ListOfSpawnables;
@ -461,7 +474,11 @@ cMonster * cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, EMCS
{ {
return nullptr; return nullptr;
} }
if (m_MobType == mtWolf) if (m_MobType == mtWitherSkeleton)
{
a_MaxPackSize = 5;
}
else if (m_MobType == mtWolf)
{ {
a_MaxPackSize = 8; a_MaxPackSize = 8;
} }

View File

@ -33,6 +33,7 @@ SET (SRCS
Villager.cpp Villager.cpp
Witch.cpp Witch.cpp
Wither.cpp Wither.cpp
WitherSkeleton.cpp
Wolf.cpp Wolf.cpp
Zombie.cpp Zombie.cpp
ZombiePigman.cpp) ZombiePigman.cpp)
@ -74,6 +75,7 @@ SET (HDRS
Villager.h Villager.h
Witch.h Witch.h
Wither.h Wither.h
WitherSkeleton.h
Wolf.h Wolf.h
Zombie.h Zombie.h
ZombiePigman.h) ZombiePigman.h)

View File

@ -26,6 +26,7 @@
#include "Villager.h" #include "Villager.h"
#include "Witch.h" #include "Witch.h"
#include "Wither.h" #include "Wither.h"
#include "WitherSkeleton.h"
#include "Wolf.h" #include "Wolf.h"
#include "Zombie.h" #include "Zombie.h"
#include "ZombiePigman.h" #include "ZombiePigman.h"

View File

@ -37,37 +37,38 @@ static const struct
const char * m_VanillaNameNBT; const char * m_VanillaNameNBT;
} g_MobTypeNames[] = } g_MobTypeNames[] =
{ {
{mtBat, "bat", "Bat", "bat"}, {mtBat, "bat", "Bat", "bat"},
{mtBlaze, "blaze", "Blaze", "blaze"}, {mtBlaze, "blaze", "Blaze", "blaze"},
{mtCaveSpider, "cavespider", "CaveSpider", "cave_spider"}, {mtCaveSpider, "cavespider", "CaveSpider", "cave_spider"},
{mtChicken, "chicken", "Chicken", "chicken"}, {mtChicken, "chicken", "Chicken", "chicken"},
{mtCow, "cow", "Cow", "cow"}, {mtCow, "cow", "Cow", "cow"},
{mtCreeper, "creeper", "Creeper", "creeper"}, {mtCreeper, "creeper", "Creeper", "creeper"},
{mtEnderman, "enderman", "Enderman", "enderman"}, {mtEnderman, "enderman", "Enderman", "enderman"},
{mtEnderDragon, "enderdragon", "EnderDragon", "ender_dragon"}, {mtEnderDragon, "enderdragon", "EnderDragon", "ender_dragon"},
{mtGhast, "ghast", "Ghast", "ghast"}, {mtGhast, "ghast", "Ghast", "ghast"},
{mtGiant, "giant", "Giant", "giant"}, {mtGiant, "giant", "Giant", "giant"},
{mtGuardian, "guardian", "Guardian", "guardian"}, {mtGuardian, "guardian", "Guardian", "guardian"},
{mtHorse, "horse", "EntityHorse", "horse"}, {mtHorse, "horse", "EntityHorse", "horse"},
{mtIronGolem, "irongolem", "VillagerGolem", "iron_golem"}, {mtIronGolem, "irongolem", "VillagerGolem", "iron_golem"},
{mtMagmaCube, "magmacube", "LavaSlime", "magma_cube"}, {mtMagmaCube, "magmacube", "LavaSlime", "magma_cube"},
{mtMooshroom, "mooshroom", "MushroomCow", "mooshroom"}, {mtMooshroom, "mooshroom", "MushroomCow", "mooshroom"},
{mtOcelot, "ocelot", "Ozelot", "ocelot"}, {mtOcelot, "ocelot", "Ozelot", "ocelot"},
{mtPig, "pig", "Pig", "pig"}, {mtPig, "pig", "Pig", "pig"},
{mtRabbit, "rabbit", "Rabbit", "rabbit"}, {mtRabbit, "rabbit", "Rabbit", "rabbit"},
{mtSheep, "sheep", "Sheep", "sheep"}, {mtSheep, "sheep", "Sheep", "sheep"},
{mtSilverfish, "silverfish", "Silverfish", "silverfish"}, {mtSilverfish, "silverfish", "Silverfish", "silverfish"},
{mtSkeleton, "skeleton", "Skeleton", "skeleton"}, {mtSkeleton, "skeleton", "Skeleton", "skeleton"},
{mtSlime, "slime", "Slime", "slime"}, {mtSlime, "slime", "Slime", "slime"},
{mtSnowGolem, "snowgolem", "SnowMan", "snow_golem"}, {mtSnowGolem, "snowgolem", "SnowMan", "snow_golem"},
{mtSpider, "spider", "Spider", "spider"}, {mtSpider, "spider", "Spider", "spider"},
{mtSquid, "squid", "Squid", "squid"}, {mtSquid, "squid", "Squid", "squid"},
{mtVillager, "villager", "Villager", "villager"}, {mtVillager, "villager", "Villager", "villager"},
{mtWitch, "witch", "Witch", "witch"}, {mtWitch, "witch", "Witch", "witch"},
{mtWither, "wither", "WitherBoss", "wither"}, {mtWither, "wither", "WitherBoss", "wither"},
{mtWolf, "wolf", "Wolf", "wolf"}, {mtWitherSkeleton, "witherskeleton", "WitherSkeleton", "wither_skeleton"},
{mtZombie, "zombie", "Zombie", "zombie"}, {mtWolf, "wolf", "Wolf", "wolf"},
{mtZombiePigman, "zombiepigman", "PigZombie", "zombie_pigman"}, {mtZombie, "zombie", "Zombie", "zombie"},
{mtZombiePigman, "zombiepigman", "PigZombie", "zombie_pigman"},
} ; } ;
@ -658,6 +659,7 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI)
case mtSkeleton: case mtSkeleton:
case mtSpider: case mtSpider:
case mtWitch: case mtWitch:
case mtWitherSkeleton:
case mtZombie: case mtZombie:
case mtZombiePigman: case mtZombiePigman:
case mtSlime: case mtSlime:
@ -1044,37 +1046,38 @@ cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type)
switch (a_Type) switch (a_Type)
{ {
case mtBat: return mfAmbient; case mtBat: return mfAmbient;
case mtBlaze: return mfHostile; case mtBlaze: return mfHostile;
case mtCaveSpider: return mfHostile; case mtCaveSpider: return mfHostile;
case mtChicken: return mfPassive; case mtChicken: return mfPassive;
case mtCow: return mfPassive; case mtCow: return mfPassive;
case mtCreeper: return mfHostile; case mtCreeper: return mfHostile;
case mtEnderDragon: return mfNoSpawn; case mtEnderDragon: return mfNoSpawn;
case mtEnderman: return mfHostile; case mtEnderman: return mfHostile;
case mtGhast: return mfHostile; case mtGhast: return mfHostile;
case mtGiant: return mfNoSpawn; case mtGiant: return mfNoSpawn;
case mtGuardian: return mfWater; // Just because they have special spawning conditions. If Watertemples have been added, this needs to be edited! case mtGuardian: return mfWater; // Just because they have special spawning conditions. If Watertemples have been added, this needs to be edited!
case mtHorse: return mfPassive; case mtHorse: return mfPassive;
case mtIronGolem: return mfPassive; case mtIronGolem: return mfPassive;
case mtMagmaCube: return mfHostile; case mtMagmaCube: return mfHostile;
case mtMooshroom: return mfHostile; case mtMooshroom: return mfHostile;
case mtOcelot: return mfPassive; case mtOcelot: return mfPassive;
case mtPig: return mfPassive; case mtPig: return mfPassive;
case mtRabbit: return mfPassive; case mtRabbit: return mfPassive;
case mtSheep: return mfPassive; case mtSheep: return mfPassive;
case mtSilverfish: return mfHostile; case mtSilverfish: return mfHostile;
case mtSkeleton: return mfHostile; case mtSkeleton: return mfHostile;
case mtSlime: return mfHostile; case mtSlime: return mfHostile;
case mtSnowGolem: return mfNoSpawn; case mtSnowGolem: return mfNoSpawn;
case mtSpider: return mfHostile; case mtSpider: return mfHostile;
case mtSquid: return mfWater; case mtSquid: return mfWater;
case mtVillager: return mfPassive; case mtVillager: return mfPassive;
case mtWitch: return mfHostile; case mtWitch: return mfHostile;
case mtWither: return mfNoSpawn; case mtWither: return mfNoSpawn;
case mtWolf: return mfHostile; case mtWitherSkeleton: return mfHostile;
case mtZombie: return mfHostile; case mtWolf: return mfHostile;
case mtZombiePigman: return mfHostile; case mtZombie: return mfHostile;
case mtZombiePigman: return mfHostile;
default: default:
{ {
@ -1173,11 +1176,6 @@ std::unique_ptr<cMonster> cMonster::NewMonsterFromType(eMonsterType a_MobType)
{ {
return cpp14::make_unique<cSlime>(1 << Random.RandInt(2)); // Size 1, 2 or 4 return cpp14::make_unique<cSlime>(1 << Random.RandInt(2)); // Size 1, 2 or 4
} }
case mtSkeleton:
{
// TODO: Actual detection of spawning in Nether
return cpp14::make_unique<cSkeleton>(false);
}
case mtVillager: case mtVillager:
{ {
int VillagerType = Random.RandInt(6); int VillagerType = Random.RandInt(6);
@ -1206,32 +1204,34 @@ std::unique_ptr<cMonster> cMonster::NewMonsterFromType(eMonsterType a_MobType)
return cpp14::make_unique<cHorse>(HorseType, HorseColor, HorseStyle, HorseTameTimes); return cpp14::make_unique<cHorse>(HorseType, HorseColor, HorseStyle, HorseTameTimes);
} }
case mtBat: return cpp14::make_unique<cBat>(); case mtBat: return cpp14::make_unique<cBat>();
case mtBlaze: return cpp14::make_unique<cBlaze>(); case mtBlaze: return cpp14::make_unique<cBlaze>();
case mtCaveSpider: return cpp14::make_unique<cCaveSpider>(); case mtCaveSpider: return cpp14::make_unique<cCaveSpider>();
case mtChicken: return cpp14::make_unique<cChicken>(); case mtChicken: return cpp14::make_unique<cChicken>();
case mtCow: return cpp14::make_unique<cCow>(); case mtCow: return cpp14::make_unique<cCow>();
case mtCreeper: return cpp14::make_unique < cCreeper>(); case mtCreeper: return cpp14::make_unique<cCreeper>();
case mtEnderDragon: return cpp14::make_unique<cEnderDragon>(); case mtEnderDragon: return cpp14::make_unique<cEnderDragon>();
case mtEnderman: return cpp14::make_unique<cEnderman>(); case mtEnderman: return cpp14::make_unique<cEnderman>();
case mtGhast: return cpp14::make_unique<cGhast>(); case mtGhast: return cpp14::make_unique<cGhast>();
case mtGiant: return cpp14::make_unique<cGiant>(); case mtGiant: return cpp14::make_unique<cGiant>();
case mtGuardian: return cpp14::make_unique<cGuardian>(); case mtGuardian: return cpp14::make_unique<cGuardian>();
case mtIronGolem: return cpp14::make_unique<cIronGolem>(); case mtIronGolem: return cpp14::make_unique<cIronGolem>();
case mtMooshroom: return cpp14::make_unique<cMooshroom>(); case mtMooshroom: return cpp14::make_unique<cMooshroom>();
case mtOcelot: return cpp14::make_unique<cOcelot>(); case mtOcelot: return cpp14::make_unique<cOcelot>();
case mtPig: return cpp14::make_unique<cPig>(); case mtPig: return cpp14::make_unique<cPig>();
case mtRabbit: return cpp14::make_unique<cRabbit>(); case mtRabbit: return cpp14::make_unique<cRabbit>();
case mtSheep: return cpp14::make_unique<cSheep>(); case mtSheep: return cpp14::make_unique<cSheep>();
case mtSilverfish: return cpp14::make_unique<cSilverfish>(); case mtSilverfish: return cpp14::make_unique<cSilverfish>();
case mtSnowGolem: return cpp14::make_unique<cSnowGolem>(); case mtSkeleton: return cpp14::make_unique<cSkeleton>();
case mtSpider: return cpp14::make_unique<cSpider>(); case mtSnowGolem: return cpp14::make_unique<cSnowGolem>();
case mtSquid: return cpp14::make_unique<cSquid>(); case mtSpider: return cpp14::make_unique<cSpider>();
case mtWitch: return cpp14::make_unique<cWitch>(); case mtSquid: return cpp14::make_unique<cSquid>();
case mtWither: return cpp14::make_unique<cWither>(); case mtWitch: return cpp14::make_unique<cWitch>();
case mtWolf: return cpp14::make_unique<cWolf>(); case mtWither: return cpp14::make_unique<cWither>();
case mtZombie: return cpp14::make_unique<cZombie>(false); // TODO: Infected zombie parameter case mtWitherSkeleton: return cpp14::make_unique<cWitherSkeleton>();
case mtZombiePigman: return cpp14::make_unique<cZombiePigman>(); case mtWolf: return cpp14::make_unique<cWolf>();
case mtZombie: return cpp14::make_unique<cZombie>(false); // TODO: Infected zombie parameter
case mtZombiePigman: return cpp14::make_unique<cZombiePigman>();
default: default:
{ {
ASSERT(!"Unhandled mob type whilst trying to spawn mob!"); ASSERT(!"Unhandled mob type whilst trying to spawn mob!");

View File

@ -39,6 +39,7 @@ enum eMonsterType
mtVillager, mtVillager,
mtWitch, mtWitch,
mtWither, mtWither,
mtWitherSkeleton,
mtWolf, mtWolf,
mtZombie, mtZombie,
mtZombiePigman, mtZombiePigman,

View File

@ -9,9 +9,8 @@
cSkeleton::cSkeleton(bool IsWither) : cSkeleton::cSkeleton(void) :
super("Skeleton", mtSkeleton, "entity.skeleton.hurt", "entity.skeleton.death", "entity.skeleton.ambient", 0.6, 1.8), super("Skeleton", mtSkeleton, "entity.skeleton.hurt", "entity.skeleton.death", "entity.skeleton.ambient", 0.6, 1.8)
m_bIsWither(IsWither)
{ {
} }
@ -26,18 +25,8 @@ void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{ {
LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
} }
if (IsWither()) AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ARROW);
{
AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_COAL);
cItems RareDrops;
RareDrops.Add(cItem(E_ITEM_HEAD, 1, 1));
AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel);
}
else
{
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ARROW);
}
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_BONE); AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_BONE);
AddRandomArmorDropItem(a_Drops, LootingLevel); AddRandomArmorDropItem(a_Drops, LootingLevel);
AddRandomWeaponDropItem(a_Drops, LootingLevel); AddRandomWeaponDropItem(a_Drops, LootingLevel);

View File

@ -13,7 +13,7 @@ class cSkeleton :
typedef cAggressiveMonster super; typedef cAggressiveMonster super;
public: public:
cSkeleton(bool IsWither); cSkeleton(void);
CLASS_PROTODEF(cSkeleton) CLASS_PROTODEF(cSkeleton)
@ -23,12 +23,6 @@ public:
virtual bool IsUndead(void) override { return true; } virtual bool IsUndead(void) override { return true; }
bool IsWither(void) const { return m_bIsWither; }
private:
bool m_bIsWither;
} ; } ;

View File

@ -0,0 +1,62 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "WitherSkeleton.h"
#include "../World.h"
#include "../ClientHandle.h"
cWitherSkeleton::cWitherSkeleton(void) :
super("WitherSkeleton", mtWitherSkeleton, "entity.wither_skeleton.hurt", "entity.wither_skeleton.death", "entity.wither_skeleton.ambient", 0.7, 2.4)
{
}
bool cWitherSkeleton::Attack(std::chrono::milliseconds a_Dt)
{
if (GetTarget() == nullptr)
{
return false;
}
GetTarget()->AddEntityEffect(cEntityEffect::effWither, 200, 0);
return super::Attack(a_Dt);
}
void cWitherSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{
unsigned int LootingLevel = 0;
if (a_Killer != nullptr)
{
LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
}
AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_COAL);
AddRandomUncommonDropItem(a_Drops, 8.5f, E_ITEM_STONE_SWORD, GetRandomProvider().RandInt<short>(50));
cItems RareDrops;
RareDrops.Add(cItem(E_ITEM_HEAD, 1, 1));
AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel);
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_BONE);
AddRandomArmorDropItem(a_Drops, LootingLevel);
AddRandomWeaponDropItem(a_Drops, LootingLevel);
}
void cWitherSkeleton::SpawnOn(cClientHandle & a_ClientHandle)
{
super::SpawnOn(a_ClientHandle);
a_ClientHandle.SendEntityEquipment(*this, 0, cItem(E_ITEM_STONE_SWORD));
}

28
src/Mobs/WitherSkeleton.h Normal file
View File

@ -0,0 +1,28 @@
#pragma once
#include "AggressiveMonster.h"
class cWitherSkeleton :
public cAggressiveMonster
{
typedef cAggressiveMonster super;
public:
cWitherSkeleton(void);
CLASS_PROTODEF(cWitherSkeleton)
virtual bool Attack(std::chrono::milliseconds a_Dt) override;
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
} ;

View File

@ -889,15 +889,6 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break; break;
} // case mtSheep } // case mtSheep
case mtSkeleton:
{
auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
a_Pkt.WriteBEUInt8(SKELETON_TYPE);
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(Skeleton.IsWither() ? 1 : 0);
break;
} // case mtSkeleton
case mtSlime: case mtSlime:
{ {
auto & Slime = static_cast<const cSlime &>(a_Mob); auto & Slime = static_cast<const cSlime &>(a_Mob);
@ -940,6 +931,14 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break; break;
} // case mtWither } // case mtWither
case mtWitherSkeleton:
{
a_Pkt.WriteBEUInt8(SKELETON_TYPE);
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(1); // Is wither skeleton
break;
} // case mtWitherSkeleton
case mtWolf: case mtWolf:
{ {
auto & Wolf = static_cast<const cWolf &>(a_Mob); auto & Wolf = static_cast<const cWolf &>(a_Mob);

View File

@ -573,6 +573,7 @@ UInt32 cProtocol_1_11_0::GetProtocolMobType(eMonsterType a_MobType)
case mtVillager: return 120; case mtVillager: return 120;
case mtWitch: return 66; case mtWitch: return 66;
case mtWither: return 64; case mtWither: return 64;
case mtWitherSkeleton: return 5;
case mtWolf: return 95; case mtWolf: return 95;
case mtZombie: return 54; case mtZombie: return 54;
case mtZombiePigman: return 57; case mtZombiePigman: return 57;
@ -1094,17 +1095,6 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break; break;
} // case mtSheep } // case mtSheep
case mtSkeleton:
{
// XXX Skeletons are separate entities; all skeletons are currently treated as regular ones
// auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
// a_Pkt.WriteBEUInt8(SKELETON_TYPE);
// a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
// a_Pkt.WriteVarInt32(Skeleton.IsWither() ? 1 : 0);
break;
} // case mtSkeleton
case mtSlime: case mtSlime:
{ {
auto & Slime = static_cast<const cSlime &>(a_Mob); auto & Slime = static_cast<const cSlime &>(a_Mob);

View File

@ -815,17 +815,6 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
break; break;
} // case mtSheep } // case mtSheep
case mtSkeleton:
{
// XXX Skeletons are separate entities; all skeletons are currently treated as regular ones
// auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
// a_Pkt.WriteBEUInt8(SKELETON_TYPE);
// a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
// a_Pkt.WriteVarInt32(Skeleton.IsWither() ? 1 : 0);
break;
} // case mtSkeleton
case mtSlime: case mtSlime:
{ {
auto & Slime = static_cast<const cSlime &>(a_Mob); auto & Slime = static_cast<const cSlime &>(a_Mob);
@ -954,7 +943,9 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
case mtGiant: case mtGiant:
case mtSilverfish: case mtSilverfish:
case mtSkeleton:
case mtSquid: case mtSquid:
case mtWitherSkeleton:
{ {
// Mobs with no extra fields // Mobs with no extra fields
break; break;

View File

@ -430,6 +430,7 @@ UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType)
case mtVillager: return 79; case mtVillager: return 79;
case mtWitch: return 82; case mtWitch: return 82;
case mtWither: return 83; case mtWither: return 83;
case mtWitherSkeleton: return 84;
case mtWolf: return 86; case mtWolf: return 86;
case mtZombie: return 87; case mtZombie: return 87;
case mtZombiePigman: return 53; case mtZombiePigman: return 53;

View File

@ -1862,6 +1862,7 @@ UInt32 cProtocol_1_8_0::GetProtocolMobType(eMonsterType a_MobType)
case mtVillager: return 120; case mtVillager: return 120;
case mtWitch: return 66; case mtWitch: return 66;
case mtWither: return 64; case mtWither: return 64;
case mtWitherSkeleton: return 51;
case mtWolf: return 95; case mtWolf: return 95;
case mtZombie: return 54; case mtZombie: return 54;
case mtZombiePigman: return 57; case mtZombiePigman: return 57;
@ -3714,14 +3715,6 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break; break;
} // case mtRabbit } // case mtRabbit
case mtSkeleton:
{
auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
a_Pkt.WriteBEUInt8(0x0d);
a_Pkt.WriteBEUInt8(Skeleton.IsWither() ? 1 : 0);
break;
} // case mtSkeleton
case mtSlime: case mtSlime:
{ {
auto & Slime = static_cast<const cSlime &>(a_Mob); auto & Slime = static_cast<const cSlime &>(a_Mob);
@ -3758,6 +3751,13 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break; break;
} // case mtWither } // case mtWither
case mtWitherSkeleton:
{
a_Pkt.WriteBEUInt8(0x0d);
a_Pkt.WriteBEUInt8(1); // Is wither skeleton
break;
} // case mtWitherSkeleton
case mtWolf: case mtWolf:
{ {
auto & Wolf = static_cast<const cWolf &>(a_Mob); auto & Wolf = static_cast<const cWolf &>(a_Mob);

View File

@ -1918,6 +1918,7 @@ UInt32 cProtocol_1_9_0::GetProtocolMobType(eMonsterType a_MobType)
case mtVillager: return 120; case mtVillager: return 120;
case mtWitch: return 66; case mtWitch: return 66;
case mtWither: return 64; case mtWither: return 64;
case mtWitherSkeleton: return 51;
case mtWolf: return 95; case mtWolf: return 95;
case mtZombie: return 54; case mtZombie: return 54;
case mtZombiePigman: return 57; case mtZombiePigman: return 57;
@ -4201,15 +4202,6 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break; break;
} // case mtSheep } // case mtSheep
case mtSkeleton:
{
auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
a_Pkt.WriteBEUInt8(11); // Index 11: Type
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(Skeleton.IsWither() ? 1 : 0);
break;
} // case mtSkeleton
case mtSlime: case mtSlime:
{ {
auto & Slime = static_cast<const cSlime &>(a_Mob); auto & Slime = static_cast<const cSlime &>(a_Mob);
@ -4252,6 +4244,14 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break; break;
} // case mtWither } // case mtWither
case mtWitherSkeleton:
{
a_Pkt.WriteBEUInt8(11); // Index 11: Type
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
a_Pkt.WriteVarInt32(1); // Is wither skeleton
break;
} // case mtWitherSkeleton
case mtWolf: case mtWolf:
{ {
auto & Wolf = static_cast<const cWolf &>(a_Mob); auto & Wolf = static_cast<const cWolf &>(a_Mob);

View File

@ -895,7 +895,7 @@ void cWorld::InitializeAndLoadMobSpawningValues(cIniFile & a_IniFile)
switch (m_Dimension) switch (m_Dimension)
{ {
case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, guardian, horse, mooshroom, ocelot, pig, rabbit, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break; // TODO Re-add Enderman when bugs are fixed case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, guardian, horse, mooshroom, ocelot, pig, rabbit, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break; // TODO Re-add Enderman when bugs are fixed
case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombiepigman"; break; case dimNether: DefaultMonsters = "blaze, ghast, magmacube, witherskeleton, zombiepigman"; break;
case dimEnd: DefaultMonsters = ""; break; // TODO Re-add Enderman when bugs are fixed case dimEnd: DefaultMonsters = ""; break; // TODO Re-add Enderman when bugs are fixed
case dimNotSet: ASSERT(!"Dimension not set"); break; case dimNotSet: ASSERT(!"Dimension not set"); break;
} }

View File

@ -710,37 +710,38 @@ public:
const char * EntityClass = nullptr; const char * EntityClass = nullptr;
switch (a_Monster->GetMobType()) switch (a_Monster->GetMobType())
{ {
case mtBat: EntityClass = "Bat"; break; case mtBat: EntityClass = "Bat"; break;
case mtBlaze: EntityClass = "Blaze"; break; case mtBlaze: EntityClass = "Blaze"; break;
case mtCaveSpider: EntityClass = "CaveSpider"; break; case mtCaveSpider: EntityClass = "CaveSpider"; break;
case mtChicken: EntityClass = "Chicken"; break; case mtChicken: EntityClass = "Chicken"; break;
case mtCow: EntityClass = "Cow"; break; case mtCow: EntityClass = "Cow"; break;
case mtCreeper: EntityClass = "Creeper"; break; case mtCreeper: EntityClass = "Creeper"; break;
case mtEnderDragon: EntityClass = "EnderDragon"; break; case mtEnderDragon: EntityClass = "EnderDragon"; break;
case mtEnderman: EntityClass = "Enderman"; break; case mtEnderman: EntityClass = "Enderman"; break;
case mtGhast: EntityClass = "Ghast"; break; case mtGhast: EntityClass = "Ghast"; break;
case mtGiant: EntityClass = "Giant"; break; case mtGiant: EntityClass = "Giant"; break;
case mtGuardian: EntityClass = "Guardian"; break; case mtGuardian: EntityClass = "Guardian"; break;
case mtHorse: EntityClass = "Horse"; break; case mtHorse: EntityClass = "Horse"; break;
case mtIronGolem: EntityClass = "VillagerGolem"; break; case mtIronGolem: EntityClass = "VillagerGolem"; break;
case mtMagmaCube: EntityClass = "LavaSlime"; break; case mtMagmaCube: EntityClass = "LavaSlime"; break;
case mtMooshroom: EntityClass = "MushroomCow"; break; case mtMooshroom: EntityClass = "MushroomCow"; break;
case mtOcelot: EntityClass = "Ozelot"; break; case mtOcelot: EntityClass = "Ozelot"; break;
case mtPig: EntityClass = "Pig"; break; case mtPig: EntityClass = "Pig"; break;
case mtRabbit: EntityClass = "Rabbit"; break; case mtRabbit: EntityClass = "Rabbit"; break;
case mtSheep: EntityClass = "Sheep"; break; case mtSheep: EntityClass = "Sheep"; break;
case mtSilverfish: EntityClass = "Silverfish"; break; case mtSilverfish: EntityClass = "Silverfish"; break;
case mtSkeleton: EntityClass = "Skeleton"; break; case mtSkeleton: EntityClass = "Skeleton"; break;
case mtSlime: EntityClass = "Slime"; break; case mtSlime: EntityClass = "Slime"; break;
case mtSnowGolem: EntityClass = "SnowMan"; break; case mtSnowGolem: EntityClass = "SnowMan"; break;
case mtSpider: EntityClass = "Spider"; break; case mtSpider: EntityClass = "Spider"; break;
case mtSquid: EntityClass = "Squid"; break; case mtSquid: EntityClass = "Squid"; break;
case mtVillager: EntityClass = "Villager"; break; case mtVillager: EntityClass = "Villager"; break;
case mtWitch: EntityClass = "Witch"; break; case mtWitch: EntityClass = "Witch"; break;
case mtWither: EntityClass = "WitherBoss"; break; case mtWither: EntityClass = "WitherBoss"; break;
case mtWolf: EntityClass = "Wolf"; break; case mtWitherSkeleton: EntityClass = "WitherSkeleton"; break;
case mtZombie: EntityClass = "Zombie"; break; case mtWolf: EntityClass = "Wolf"; break;
case mtZombiePigman: EntityClass = "PigZombie"; break; case mtZombie: EntityClass = "Zombie"; break;
case mtZombiePigman: EntityClass = "PigZombie"; break;
default: default:
{ {
ASSERT(!"Unhandled monster type"); ASSERT(!"Unhandled monster type");
@ -869,11 +870,6 @@ public:
mWriter.AddInt("Size", static_cast<const cSlime *>(a_Monster)->GetSize()); mWriter.AddInt("Size", static_cast<const cSlime *>(a_Monster)->GetSize());
break; break;
} }
case mtSkeleton:
{
mWriter.AddByte("SkeletonType", (static_cast<const cSkeleton *>(a_Monster)->IsWither() ? 1 : 0));
break;
}
case mtVillager: case mtVillager:
{ {
const cVillager *Villager = static_cast<const cVillager *>(a_Monster); const cVillager *Villager = static_cast<const cVillager *>(a_Monster);
@ -927,10 +923,12 @@ public:
case mtIronGolem: case mtIronGolem:
case mtMooshroom: case mtMooshroom:
case mtSilverfish: case mtSilverfish:
case mtSkeleton:
case mtSnowGolem: case mtSnowGolem:
case mtSpider: case mtSpider:
case mtSquid: case mtSquid:
case mtWitch: case mtWitch:
case mtWitherSkeleton:
{ {
// Other mobs have no special tags. // Other mobs have no special tags.
break; break;

View File

@ -1560,6 +1560,8 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
{ "minecraft:witch", &cWSSAnvil::LoadWitchFromNBT }, { "minecraft:witch", &cWSSAnvil::LoadWitchFromNBT },
{ "WitherBoss", &cWSSAnvil::LoadWitherFromNBT }, { "WitherBoss", &cWSSAnvil::LoadWitherFromNBT },
{ "minecraft:wither", &cWSSAnvil::LoadWitherFromNBT }, { "minecraft:wither", &cWSSAnvil::LoadWitherFromNBT },
{ "WitherSkeleton", &cWSSAnvil::LoadWitherSkeletonFromNBT },
{ "minecraft:wither_skeleton", &cWSSAnvil::LoadWitherSkeletonFromNBT },
{ "Wolf", &cWSSAnvil::LoadWolfFromNBT }, { "Wolf", &cWSSAnvil::LoadWolfFromNBT },
{ "minecraft:wolf", &cWSSAnvil::LoadWolfFromNBT }, { "minecraft:wolf", &cWSSAnvil::LoadWolfFromNBT },
{ "Zombie", &cWSSAnvil::LoadZombieFromNBT }, { "Zombie", &cWSSAnvil::LoadZombieFromNBT },
@ -2660,15 +2662,20 @@ void cWSSAnvil::LoadSilverfishFromNBT(cEntityList & a_Entities, const cParsedNBT
void cWSSAnvil::LoadSkeletonFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) void cWSSAnvil::LoadSkeletonFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{ {
// Wither skeleton is a separate mob in Minecraft 1.11+, but we need this to
// load them from older worlds where wither skeletons were only a skeleton with a flag
int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "SkeletonType"); int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "SkeletonType");
if (TypeIdx < 0)
std::unique_ptr<cMonster> Monster;
if ((TypeIdx > 0) && (a_NBT.GetByte(TypeIdx) == 1))
{ {
return; Monster = cpp14::make_unique<cWitherSkeleton>();
}
else
{
Monster = cpp14::make_unique<cSkeleton>();
} }
bool Type = ((a_NBT.GetByte(TypeIdx) == 1) ? true : false);
std::unique_ptr<cSkeleton> Monster = cpp14::make_unique<cSkeleton>(Type);
if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{ {
return; return;
@ -2863,6 +2870,26 @@ void cWSSAnvil::LoadWitherFromNBT(cEntityList & a_Entities, const cParsedNBT & a
void cWSSAnvil::LoadWitherSkeletonFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
auto Monster = cpp14::make_unique<cWitherSkeleton>();
if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;
}
if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;
}
a_Entities.emplace_back(std::move(Monster));
}
void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{ {
std::unique_ptr<cWolf> Monster = cpp14::make_unique<cWolf>(); std::unique_ptr<cWolf> Monster = cpp14::make_unique<cWolf>();

View File

@ -228,6 +228,7 @@ protected:
void LoadVillagerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadVillagerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadWitchFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadWitchFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadWitherFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadWitherFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadWitherSkeletonFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadWolfFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); 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 LoadZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadPigZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPigZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);