commit
01c38505fd
@ -22,14 +22,99 @@ public:
|
|||||||
a_Pickups.push_back(cItem(E_ITEM_HEAD, 1, 0));
|
a_Pickups.push_back(cItem(E_ITEM_HEAD, 1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TrySpawnWither(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
|
bool TrySpawnWither(cChunkInterface & a_ChunkInterface, cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
{
|
{
|
||||||
if (a_BlockY < 2)
|
if (a_BlockY < 2)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 2014-03-24 xdot
|
class cCallback : public cMobHeadCallback
|
||||||
|
{
|
||||||
|
bool m_IsWither;
|
||||||
|
|
||||||
|
virtual bool Item (cMobHeadEntity * a_MobHeadEntity)
|
||||||
|
{
|
||||||
|
m_IsWither = (a_MobHeadEntity->GetType() == SKULL_TYPE_WITHER);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
cCallback () : m_IsWither(false) {}
|
||||||
|
|
||||||
|
bool IsWither(void) const { return m_IsWither; }
|
||||||
|
|
||||||
|
void Reset(void) { m_IsWither = false; }
|
||||||
|
} CallbackA, CallbackB;
|
||||||
|
|
||||||
|
a_World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, CallbackA);
|
||||||
|
|
||||||
|
if (!CallbackA.IsWither())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallbackA.Reset();
|
||||||
|
|
||||||
|
BLOCKTYPE BlockY1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
|
||||||
|
BLOCKTYPE BlockY2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 2, a_BlockZ);
|
||||||
|
|
||||||
|
if ((BlockY1 != E_BLOCK_SOULSAND) || (BlockY2 != E_BLOCK_SOULSAND))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_World->DoWithMobHeadAt(a_BlockX - 1, a_BlockY, a_BlockZ, CallbackA);
|
||||||
|
a_World->DoWithMobHeadAt(a_BlockX + 1, a_BlockY, a_BlockZ, CallbackB);
|
||||||
|
|
||||||
|
BLOCKTYPE Block1 = a_ChunkInterface.GetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ);
|
||||||
|
BLOCKTYPE Block2 = a_ChunkInterface.GetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ);
|
||||||
|
|
||||||
|
if ((Block1 == E_BLOCK_SOULSAND) && (Block2 == E_BLOCK_SOULSAND) && CallbackA.IsWither() && CallbackB.IsWither())
|
||||||
|
{
|
||||||
|
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
a_ChunkInterface.FastSetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
a_ChunkInterface.FastSetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
|
||||||
|
// Block entities
|
||||||
|
a_World->SetBlock(a_BlockX + 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
a_World->SetBlock(a_BlockX - 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
|
||||||
|
// Spawn the wither:
|
||||||
|
a_World->SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallbackA.Reset();
|
||||||
|
CallbackB.Reset();
|
||||||
|
|
||||||
|
a_World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ - 1, CallbackA);
|
||||||
|
a_World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ + 1, CallbackB);
|
||||||
|
|
||||||
|
Block1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1);
|
||||||
|
Block2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1);
|
||||||
|
|
||||||
|
if ((Block1 == E_BLOCK_SOULSAND) && (Block2 == E_BLOCK_SOULSAND) && CallbackA.IsWither() && CallbackB.IsWither())
|
||||||
|
{
|
||||||
|
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1, E_BLOCK_AIR, 0);
|
||||||
|
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1, E_BLOCK_AIR, 0);
|
||||||
|
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
|
||||||
|
// Block entities
|
||||||
|
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ + 1, E_BLOCK_AIR, 0);
|
||||||
|
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ - 1, E_BLOCK_AIR, 0);
|
||||||
|
|
||||||
|
// Spawn the wither:
|
||||||
|
a_World->SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -75,7 +160,24 @@ public:
|
|||||||
World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
|
World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
|
||||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
|
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
|
||||||
|
|
||||||
TrySpawnWither(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
|
if (a_BlockMeta == SKULL_TYPE_WITHER)
|
||||||
|
{
|
||||||
|
static const Vector3i Coords[] =
|
||||||
|
{
|
||||||
|
Vector3i( 0, 0, 0),
|
||||||
|
Vector3i( 1, 0, 0),
|
||||||
|
Vector3i(-1, 0, 0),
|
||||||
|
Vector3i( 0, 0, 1),
|
||||||
|
Vector3i( 0, 0, -1),
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < ARRAYCOUNT(Coords); ++i)
|
||||||
|
{
|
||||||
|
if (TrySpawnWither(a_ChunkInterface, World, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // for i - Coords[]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
@ -13,8 +13,27 @@ cWither::cWither(void) :
|
|||||||
m_InvulnerableTicks(220)
|
m_InvulnerableTicks(220)
|
||||||
{
|
{
|
||||||
SetMaxHealth(300);
|
SetMaxHealth(300);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cWither::IsArmored(void) const
|
||||||
|
{
|
||||||
|
return GetHealth() <= (GetMaxHealth() / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cWither::Initialize(cWorld * a_World)
|
||||||
|
{
|
||||||
|
// Set health before BroadcastSpawnEntity()
|
||||||
SetHealth(GetMaxHealth() / 3);
|
SetHealth(GetMaxHealth() / 3);
|
||||||
|
|
||||||
|
return super::Initialize(a_World);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -33,6 +52,11 @@ void cWither::DoTakeDamage(TakeDamageInfo & a_TDI)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsArmored() && (a_TDI.DamageType == dtRangedAttack))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
super::DoTakeDamage(a_TDI);
|
super::DoTakeDamage(a_TDI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +84,8 @@ void cWither::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
Heal(10);
|
Heal(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_World->BroadcastEntityMetadata(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,11 @@ public:
|
|||||||
|
|
||||||
void SetNumInvulnerableTicks(unsigned int a_Ticks) { m_InvulnerableTicks = a_Ticks; }
|
void SetNumInvulnerableTicks(unsigned int a_Ticks) { m_InvulnerableTicks = a_Ticks; }
|
||||||
|
|
||||||
|
/** Returns whether the wither is invulnerable to arrows. */
|
||||||
|
bool IsArmored(void) const;
|
||||||
|
|
||||||
// cEntity overrides
|
// cEntity overrides
|
||||||
|
virtual bool Initialize(cWorld * a_World) override;
|
||||||
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
|
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
|
||||||
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
|
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||||
|
@ -1951,6 +1951,14 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
|
|||||||
WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything
|
WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case cMonster::mtWither:
|
||||||
|
{
|
||||||
|
WriteByte(0x54); // Int at index 20
|
||||||
|
WriteInt(((const cWither &)a_Mob).GetNumInvulnerableTicks());
|
||||||
|
WriteByte(0x66); // Float at index 6
|
||||||
|
WriteFloat((float)(a_Mob.GetHealth()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case cMonster::mtSlime:
|
case cMonster::mtSlime:
|
||||||
case cMonster::mtMagmaCube:
|
case cMonster::mtMagmaCube:
|
||||||
{
|
{
|
||||||
|
@ -2535,6 +2535,7 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
|||||||
WriteByte(Frame.GetRotation());
|
WriteByte(Frame.GetRotation());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2660,6 +2661,15 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case cMonster::mtWither:
|
||||||
|
{
|
||||||
|
WriteByte(0x54); // Int at index 20
|
||||||
|
WriteInt(((const cWither &)a_Mob).GetNumInvulnerableTicks());
|
||||||
|
WriteByte(0x66); // Float at index 6
|
||||||
|
WriteFloat((float)(a_Mob.GetHealth()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case cMonster::mtSlime:
|
case cMonster::mtSlime:
|
||||||
{
|
{
|
||||||
WriteByte(0x10);
|
WriteByte(0x10);
|
||||||
|
Loading…
Reference in New Issue
Block a user