Initial Metadata Commit [SEE DESC]
+ Pigs, Minecarts, Sheep, Skeletons, Slimes, Villagers, Wolves, and Horses have metadata + Base code on taming wolves, shearing sheep, and taming horses + Sheep and horses have different colours when spawned
This commit is contained in:
parent
21b23ff1e7
commit
5db6213f34
@ -1139,6 +1139,10 @@
|
||||
RelativePath="..\source\Mobs\Wither.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\source\Mobs\Wolf.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\source\Mobs\Wolf.h"
|
||||
>
|
||||
|
@ -71,6 +71,13 @@ public:
|
||||
ENTITY_STATUS_WOLF_SHAKING = 8,
|
||||
ENTITY_STATUS_EATING_ACCEPTED = 9,
|
||||
ENTITY_STATUS_SHEEP_EATING = 10,
|
||||
ENTITY_STATUS_GOLEM_ROSING = 11,
|
||||
ENTITY_STATUS_VILLAGER_HEARTS = 12,
|
||||
ENTITY_STATUS_VILLAGER_ANGRY = 13,
|
||||
ENTITY_STATUS_VILLAGER_HAPPY = 14,
|
||||
ENTITY_STATUS_WITCH_MAGICKING = 15,
|
||||
// It seems 16 (zombie conversion) is now done with metadata
|
||||
ENTITY_STATUS_FIREWORK_EXPLODE= 17,
|
||||
} ;
|
||||
|
||||
enum
|
||||
@ -333,6 +340,62 @@ public:
|
||||
virtual bool IsRiding (void) const {return false; }
|
||||
virtual bool IsSprinting(void) const {return false; }
|
||||
virtual bool IsRclking (void) const {return false; }
|
||||
virtual bool IsInvisible(void) const {return false; }
|
||||
|
||||
// Ageables + Tameables
|
||||
virtual bool IsBabby (void) const {return false; }
|
||||
virtual bool IsSitting (void) const {return false; }
|
||||
virtual bool IsTame (void) const {return false; }
|
||||
|
||||
// Creepers
|
||||
virtual bool IsCharged (void) const {return false; }
|
||||
virtual bool IsBlowing (void) const {return false; }
|
||||
|
||||
// Furnace Minecarts & Minecarts
|
||||
virtual int LastDamage (void) const {return 0; }
|
||||
virtual bool IsFueled (void) const {return false; }
|
||||
|
||||
// Bat
|
||||
virtual bool IsHanging (void) const {return false; }
|
||||
|
||||
// Pig
|
||||
virtual bool IsSaddled (void) const {return false; }
|
||||
|
||||
// TESTIFICATE
|
||||
virtual int GetVilType(void) const {return 0; }
|
||||
|
||||
// Zombie
|
||||
virtual bool IsVillager(void) const {return false; }
|
||||
virtual bool IsConvert (void) const {return false; }
|
||||
|
||||
// Ghast
|
||||
virtual bool IsCharging(void) const {return false; }
|
||||
|
||||
// Arrow
|
||||
virtual bool IsCritical(void) const {return false; }
|
||||
|
||||
// Wolf
|
||||
virtual bool IsAngry (void) const {return false; }
|
||||
virtual bool IsBegging (void) const {return false; }
|
||||
virtual int GetCollar (void) const {return 0; }
|
||||
|
||||
// Sheep
|
||||
virtual int GetFurColor(void) const {return 0; }
|
||||
virtual bool IsSheared (void) const {return false; }
|
||||
|
||||
// Enderman
|
||||
virtual BLOCKTYPE CarriedBlock (void) const {return E_BLOCK_AIR; }
|
||||
virtual NIBBLETYPE CarriedMeta (void) const {return 0; }
|
||||
virtual bool IsScream (void) const {return false; }
|
||||
|
||||
// Skeleton || Wither Skeleton
|
||||
virtual bool IsWither (void) const {return false; }
|
||||
|
||||
// Witch
|
||||
virtual bool IsNosey (void) const {return false; }
|
||||
|
||||
// Slimes and Magma cubes
|
||||
virtual int GetSize (void) const {return 1; }
|
||||
|
||||
// tolua_end
|
||||
|
||||
|
@ -16,7 +16,8 @@
|
||||
|
||||
cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) :
|
||||
super(etMinecart, a_X, a_Y, a_Z, 0.98, 0.7),
|
||||
m_Payload(a_Payload)
|
||||
m_Payload(a_Payload),
|
||||
m_LastDamage(0)
|
||||
{
|
||||
SetMass(20.f);
|
||||
SetMaxHealth(6);
|
||||
@ -344,11 +345,51 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk)
|
||||
|
||||
void cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
|
||||
{
|
||||
m_LastDamage = TDI.FinalDamage;
|
||||
super::DoTakeDamage(TDI);
|
||||
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
|
||||
if (GetHealth() <= 0)
|
||||
{
|
||||
Destroy(true);
|
||||
|
||||
cItems Drops;
|
||||
switch (m_Payload)
|
||||
{
|
||||
case mpNone:
|
||||
{
|
||||
Drops.push_back(cItem(E_ITEM_MINECART, 1, 0));
|
||||
break;
|
||||
}
|
||||
case mpChest:
|
||||
{
|
||||
Drops.push_back(cItem(E_ITEM_CHEST_MINECART, 1, 0));
|
||||
break;
|
||||
}
|
||||
case mpFurnace:
|
||||
{
|
||||
Drops.push_back(cItem(E_ITEM_FURNACE_MINECART, 1, 0));
|
||||
break;
|
||||
}
|
||||
case mpTNT:
|
||||
{
|
||||
Drops.push_back(cItem(0, 1, 0));
|
||||
break;
|
||||
}
|
||||
case mpHopper:
|
||||
{
|
||||
Drops.push_back(cItem(0, 1, 0));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled minecart type when spawning pickup!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,7 +475,8 @@ void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
|
||||
// cMinecartWithFurnace:
|
||||
|
||||
cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) :
|
||||
super(mpFurnace, a_X, a_Y, a_Z)
|
||||
super(mpFurnace, a_X, a_Y, a_Z),
|
||||
m_IsFueled(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -444,8 +486,16 @@ cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) :
|
||||
|
||||
void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
|
||||
{
|
||||
// Try to power the furnace with whatever the player is holding
|
||||
// TODO
|
||||
if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_COAL)
|
||||
{
|
||||
if (!a_Player.IsGameModeCreative())
|
||||
{
|
||||
a_Player.GetInventory().RemoveOneEquippedItem();
|
||||
}
|
||||
|
||||
m_IsFueled = true;
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,16 +50,19 @@ public:
|
||||
// cEntity overrides:
|
||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
|
||||
void HandleRailPhysics(float a_Dt, cChunk & a_Chunk);
|
||||
virtual void DoTakeDamage(TakeDamageInfo & TDI) override;
|
||||
int LastDamage(void) const { return m_LastDamage; }
|
||||
|
||||
|
||||
void HandleRailPhysics(float a_Dt, cChunk & a_Chunk);
|
||||
ePayload GetPayload(void) const { return m_Payload; }
|
||||
|
||||
protected:
|
||||
ePayload m_Payload;
|
||||
|
||||
cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z);
|
||||
|
||||
int m_LastDamage;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@ -127,6 +130,12 @@ public:
|
||||
|
||||
// cEntity overrides:
|
||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||
bool IsFueled (void) const { return m_IsFueled; }
|
||||
|
||||
private:
|
||||
|
||||
bool m_IsFueled;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -2,13 +2,26 @@
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "Horse.h"
|
||||
#include "../World.h"
|
||||
#include "../Entities/Player.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cHorse::cHorse(void) :
|
||||
super("Horse", 100, "mob.horse.hit", "mob.horse.death", 1.4, 1.6)
|
||||
cHorse::cHorse(int Type, int Color, int Style, int TameTimes) :
|
||||
super("Horse", 100, "mob.horse.hit", "mob.horse.death", 1.4, 1.6),
|
||||
m_bIsChested(false),
|
||||
m_bIsEating(false),
|
||||
m_bIsRearing(false),
|
||||
m_bIsMouthOpen(false),
|
||||
m_bIsTame(false),
|
||||
m_Type(Type),
|
||||
m_Color(Color),
|
||||
m_Style(Style),
|
||||
m_Armour(0),
|
||||
m_TimesToTame(TameTimes),
|
||||
m_TameAttemptTimes(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -16,6 +29,84 @@ cHorse::cHorse(void) :
|
||||
|
||||
|
||||
|
||||
void cHorse::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
if (!m_bIsMouthOpen)
|
||||
{
|
||||
if (m_World->GetTickRandomNumber(50) == 25)
|
||||
{
|
||||
m_bIsMouthOpen = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_World->GetTickRandomNumber(10) == 5)
|
||||
{
|
||||
m_bIsMouthOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_Attachee != NULL) && (!m_bIsTame))
|
||||
{
|
||||
if (m_TameAttemptTimes < m_TimesToTame)
|
||||
{
|
||||
if (m_World->GetTickRandomNumber(50) == 25)
|
||||
{
|
||||
m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 0);
|
||||
m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 2);
|
||||
m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 6);
|
||||
m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 8);
|
||||
|
||||
m_Attachee->Detach();
|
||||
m_bIsRearing = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bIsTame = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_bIsRearing) && (m_World->GetTickRandomNumber(15) == 6))
|
||||
{
|
||||
m_bIsRearing = false;
|
||||
}
|
||||
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cHorse::OnRightClicked(cPlayer & a_Player)
|
||||
{
|
||||
if (m_Attachee != NULL)
|
||||
{
|
||||
if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
|
||||
{
|
||||
a_Player.Detach();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Attachee->IsPlayer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_Attachee->Detach();
|
||||
}
|
||||
|
||||
m_TameAttemptTimes++;
|
||||
a_Player.AttachTo(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
{
|
||||
AddRandomDropItem(a_Drops, 0, 2, E_ITEM_LEATHER);
|
||||
|
@ -13,11 +13,28 @@ class cHorse :
|
||||
typedef cPassiveMonster super;
|
||||
|
||||
public:
|
||||
cHorse(void);
|
||||
cHorse(int Type, int Color, int Style, int TameTimes);
|
||||
|
||||
CLASS_PROTODEF(cHorse);
|
||||
|
||||
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||
bool IsChested (void) const {return m_bIsChested; }
|
||||
bool IsEating (void) const {return m_bIsEating; }
|
||||
bool IsRearing (void) const {return m_bIsRearing; }
|
||||
bool IsMthOpen (void) const {return m_bIsMouthOpen; }
|
||||
bool IsTame (void) const {return m_bIsTame; }
|
||||
int GetHType (void) const {return m_Type; }
|
||||
int GetHColor (void) const {return m_Color; }
|
||||
int GetHStyle (void) const {return m_Style; }
|
||||
int GetHArmour (void) const {return m_Armour;}
|
||||
|
||||
private:
|
||||
|
||||
bool m_bIsChested, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame;
|
||||
int m_Type, m_Color, m_Style, m_Armour, m_TimesToTame, m_TameAttemptTimes;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
CLASS_PROTODEF(cMagmaCube);
|
||||
|
||||
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
|
||||
int GetSize(void) const { return m_Size; }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -2,13 +2,16 @@
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "Pig.h"
|
||||
#include "../Entities/Player.h"
|
||||
#include "../World.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPig::cPig(void) :
|
||||
super("Pig", 90, "mob.pig.say", "mob.pig.death", 0.9, 0.9)
|
||||
super("Pig", 90, "mob.pig.say", "mob.pig.death", 0.9, 0.9),
|
||||
m_bIsSaddled(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -24,3 +27,47 @@ void cPig::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
|
||||
|
||||
|
||||
|
||||
void cPig::OnRightClicked(cPlayer & a_Player)
|
||||
{
|
||||
if (m_bIsSaddled)
|
||||
{
|
||||
if (m_Attachee != NULL)
|
||||
{
|
||||
if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
|
||||
{
|
||||
// This player is already sitting in, they want out.
|
||||
a_Player.Detach();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Attachee->IsPlayer())
|
||||
{
|
||||
// Another player is already sitting in here, cannot attach
|
||||
return;
|
||||
}
|
||||
|
||||
// Detach whatever is sitting in this pig now:
|
||||
m_Attachee->Detach();
|
||||
}
|
||||
|
||||
// Attach the player to this pig
|
||||
a_Player.AttachTo(this);
|
||||
}
|
||||
else if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_SADDLE)
|
||||
{
|
||||
if (!a_Player.IsGameModeCreative())
|
||||
{
|
||||
a_Player.GetInventory().RemoveOneEquippedItem();
|
||||
}
|
||||
|
||||
// Set saddle state & broadcast metadata
|
||||
m_bIsSaddled = true;
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -18,6 +18,13 @@ public:
|
||||
CLASS_PROTODEF(cPig);
|
||||
|
||||
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
|
||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||
bool IsSaddled(void) const { return m_bIsSaddled; }
|
||||
|
||||
private:
|
||||
|
||||
bool m_bIsSaddled;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -3,15 +3,17 @@
|
||||
|
||||
#include "Sheep.h"
|
||||
#include "../BlockID.h"
|
||||
#include "../Entities/Player.h"
|
||||
#include "../World.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cSheep::cSheep(void) :
|
||||
cSheep::cSheep(int a_Color) :
|
||||
super("Sheep", 91, "mob.sheep.say", "mob.sheep.say", 0.6, 1.3),
|
||||
m_IsSheared(false),
|
||||
m_WoolColor(E_META_WOOL_WHITE)
|
||||
m_WoolColor(a_Color)
|
||||
{
|
||||
}
|
||||
|
||||
@ -30,3 +32,25 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
|
||||
|
||||
|
||||
|
||||
void cSheep::OnRightClicked(cPlayer & a_Player)
|
||||
{
|
||||
if ((a_Player.GetEquippedItem().m_ItemType == E_ITEM_SHEARS) && (!m_IsSheared))
|
||||
{
|
||||
m_IsSheared = true;
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
|
||||
if (!a_Player.IsGameModeCreative())
|
||||
{
|
||||
a_Player.UseEquippedItem();
|
||||
}
|
||||
|
||||
cItems Drops;
|
||||
Drops.push_back(cItem(E_BLOCK_WOOL, 4, m_WoolColor));
|
||||
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -13,14 +13,20 @@ class cSheep :
|
||||
typedef cPassiveMonster super;
|
||||
|
||||
public:
|
||||
cSheep(void);
|
||||
|
||||
bool m_IsSheared;
|
||||
NIBBLETYPE m_WoolColor; // Uses E_META_WOOL_ constants for colors
|
||||
cSheep(int a_Color);
|
||||
|
||||
CLASS_PROTODEF(cSheep);
|
||||
|
||||
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
|
||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||
bool IsSheared(void) const { return m_IsSheared; }
|
||||
int GetFurColor(void) const { return m_WoolColor; }
|
||||
|
||||
private:
|
||||
|
||||
bool m_IsSheared;
|
||||
int m_WoolColor;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -8,8 +8,9 @@
|
||||
|
||||
|
||||
|
||||
cSkeleton::cSkeleton(void) :
|
||||
super("Skeleton", 51, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8)
|
||||
cSkeleton::cSkeleton(bool IsWither) :
|
||||
super("Skeleton", 51, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8),
|
||||
m_bIsWither(IsWither)
|
||||
{
|
||||
SetBurnsInDaylight(true);
|
||||
}
|
||||
|
@ -13,11 +13,17 @@ class cSkeleton :
|
||||
typedef cAggressiveMonster super;
|
||||
|
||||
public:
|
||||
cSkeleton();
|
||||
cSkeleton(bool IsWither);
|
||||
|
||||
CLASS_PROTODEF(cSkeleton);
|
||||
|
||||
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
|
||||
bool IsWither(void) const { return m_bIsWither; };
|
||||
|
||||
private:
|
||||
|
||||
bool m_bIsWither;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -3,8 +3,6 @@
|
||||
|
||||
#include "Slime.h"
|
||||
|
||||
// TODO: Implement sized slimes
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
CLASS_PROTODEF(cSlime);
|
||||
|
||||
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
|
||||
int GetSize(void) const { return m_Size; }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -2,16 +2,34 @@
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "Villager.h"
|
||||
#include "../World.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cVillager::cVillager(void) :
|
||||
super("Villager", 120, "", "", 0.6, 1.8)
|
||||
cVillager::cVillager(int Type) :
|
||||
super("Villager", 120, "", "", 0.6, 1.8),
|
||||
m_Type(Type)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
{
|
||||
super::DoTakeDamage(a_TDI);
|
||||
if (a_TDI.Attacker->IsPlayer())
|
||||
{
|
||||
if (m_World->GetTickRandomNumber(5) == 3)
|
||||
{
|
||||
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_VILLAGER_ANGRY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -13,9 +13,17 @@ class cVillager :
|
||||
typedef cPassiveMonster super;
|
||||
|
||||
public:
|
||||
cVillager();
|
||||
cVillager(int Type);
|
||||
|
||||
CLASS_PROTODEF(cVillager);
|
||||
|
||||
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
|
||||
int GetVilType(void) const { return m_Type; }
|
||||
|
||||
private:
|
||||
|
||||
int m_Type;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
79
source/Mobs/Wolf.cpp
Normal file
79
source/Mobs/Wolf.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "Wolf.h"
|
||||
#include "../World.h"
|
||||
#include "../Entities/Player.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cWolf::cWolf(void) :
|
||||
super("Wolf", 95, "mob.wolf.hurt", "mob.wolf.death", 0.6, 0.8),
|
||||
m_bIsAngry(false),
|
||||
m_bIsTame(false),
|
||||
m_bIsSitting(false),
|
||||
m_bIsBegging(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
{
|
||||
super::DoTakeDamage(a_TDI);
|
||||
if (!m_bIsTame)
|
||||
{
|
||||
m_bIsAngry = true;
|
||||
}
|
||||
m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWolf::OnRightClicked(cPlayer & a_Player)
|
||||
{
|
||||
if ((!m_bIsTame) && (!m_bIsAngry))
|
||||
{
|
||||
if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_BONE)
|
||||
{
|
||||
if (!a_Player.IsGameModeCreative())
|
||||
{
|
||||
a_Player.GetInventory().RemoveOneEquippedItem();
|
||||
}
|
||||
|
||||
if (m_World->GetTickRandomNumber(10) == 5)
|
||||
{
|
||||
SetMaxHealth(20);
|
||||
m_bIsTame = true;
|
||||
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMED);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMING);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_bIsTame)
|
||||
{
|
||||
if (m_bIsSitting)
|
||||
{
|
||||
m_bIsSitting = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bIsSitting = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -13,13 +13,25 @@ class cWolf :
|
||||
typedef cPassiveAggressiveMonster super;
|
||||
|
||||
public:
|
||||
cWolf(void) :
|
||||
// TODO: The size is only a guesstimate, measure in vanilla and fix the size values here (wiki.vg values are suspicious)
|
||||
super("Wolf", 95, "mob.wolf.hurt", "mob.wolf.death", 0.9, 0.9)
|
||||
{
|
||||
}
|
||||
cWolf(void);
|
||||
|
||||
CLASS_PROTODEF(cWolf);
|
||||
|
||||
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
|
||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||
|
||||
bool IsSitting(void) const { return m_bIsSitting; }
|
||||
bool IsTame(void) const { return m_bIsTame; }
|
||||
bool IsBegging(void) const { return m_bIsBegging; }
|
||||
bool IsAngry(void) const { return m_bIsAngry; }
|
||||
|
||||
private:
|
||||
|
||||
bool m_bIsSitting;
|
||||
bool m_bIsTame;
|
||||
bool m_bIsBegging;
|
||||
bool m_bIsAngry;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -343,8 +343,9 @@ void cProtocol125::SendEntityMetadata(const cEntity & a_Entity)
|
||||
cCSLock Lock(m_CSPacket);
|
||||
WriteByte(PACKET_METADATA);
|
||||
WriteInt (a_Entity.GetUniqueID());
|
||||
AString MetaData = GetEntityMetaData(a_Entity);
|
||||
SendData(MetaData.data(), MetaData.size());
|
||||
|
||||
WriteMetadata(a_Entity);
|
||||
|
||||
Flush();
|
||||
}
|
||||
|
||||
@ -710,8 +711,7 @@ void cProtocol125::SendSpawnMob(const cMonster & a_Mob)
|
||||
WriteByte (0);
|
||||
WriteByte (0);
|
||||
WriteByte (0);
|
||||
AString MetaData = GetEntityMetaData(a_Mob);
|
||||
SendData (MetaData.data(), MetaData.size());
|
||||
WriteMetadata(a_Mob);
|
||||
Flush();
|
||||
}
|
||||
|
||||
@ -1614,48 +1614,212 @@ int cProtocol125::ParseItem(cItem & a_Item)
|
||||
|
||||
|
||||
|
||||
AString cProtocol125::GetEntityMetaData(const cEntity & a_Entity)
|
||||
void cProtocol125::WriteMetadata(const cEntity & a_Entity)
|
||||
{
|
||||
// We should send all the metadata here
|
||||
AString MetaData;
|
||||
// Common metadata (index 0, byte):
|
||||
MetaData.push_back(0);
|
||||
MetaData.push_back(GetEntityMetadataFlags(a_Entity));
|
||||
// Common Metadata
|
||||
|
||||
// TODO: Add more entity-specific metadata
|
||||
Byte CommonMetadata = 0;
|
||||
|
||||
MetaData.push_back(0x7f); // End metadata
|
||||
return MetaData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char cProtocol125::GetEntityMetadataFlags(const cEntity & a_Entity)
|
||||
{
|
||||
char Flags = 0;
|
||||
if (a_Entity.IsOnFire())
|
||||
{
|
||||
Flags |= 1;
|
||||
CommonMetadata |= 0x1;
|
||||
}
|
||||
if (a_Entity.IsCrouched())
|
||||
{
|
||||
Flags |= 2;
|
||||
CommonMetadata |= 0x2;
|
||||
}
|
||||
if (a_Entity.IsRiding())
|
||||
{
|
||||
Flags |= 4;
|
||||
CommonMetadata |= 0x4;
|
||||
}
|
||||
if (a_Entity.IsSprinting())
|
||||
{
|
||||
Flags |= 8;
|
||||
CommonMetadata |= 0x8;
|
||||
}
|
||||
if (a_Entity.IsRclking())
|
||||
{
|
||||
Flags |= 16;
|
||||
CommonMetadata |= 0x16;
|
||||
}
|
||||
return Flags;
|
||||
if (a_Entity.IsInvisible())
|
||||
{
|
||||
CommonMetadata |= 0x32;
|
||||
}
|
||||
|
||||
WriteByte(0x0);
|
||||
WriteByte(CommonMetadata);
|
||||
|
||||
// Common Metadata End
|
||||
// Specific Entity Metadata
|
||||
|
||||
if (a_Entity.IsMinecart())
|
||||
{
|
||||
WriteByte(0x51);
|
||||
// No idea how Mojang makes their carts shakey shakey, so here is a complicated one-liner expression that does something similar
|
||||
WriteInt( (((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * a_Entity.LastDamage()) * 4 );
|
||||
WriteByte(0x52);
|
||||
WriteInt(1); // Shaking direction, doesn't seem to affect anything
|
||||
WriteByte(0x73);
|
||||
WriteFloat((float)(a_Entity.LastDamage() + 10)); // Damage taken / shake effect multiplyer
|
||||
}
|
||||
else if (a_Entity.IsA("cCreeper"))
|
||||
{
|
||||
WriteByte(0x10);
|
||||
WriteByte(a_Entity.IsBlowing() ? 1 : -1); // Blowing up?
|
||||
WriteByte(0x11);
|
||||
WriteByte(a_Entity.IsCharged() ? 1 : 0); // Lightning-charged?
|
||||
}
|
||||
else if (a_Entity.IsA("cMinecartWithFurnace"))
|
||||
{
|
||||
WriteByte(0x10);
|
||||
WriteByte(a_Entity.IsFueled() ? 1 : 0); // Fueled?
|
||||
}
|
||||
else if (a_Entity.IsA("cBat"))
|
||||
{
|
||||
WriteByte(0x10);
|
||||
WriteByte(a_Entity.IsHanging() ? 1 : 0); // Upside down?
|
||||
}
|
||||
else if (a_Entity.IsA("cPig"))
|
||||
{
|
||||
WriteByte(0x10);
|
||||
WriteByte(a_Entity.IsSaddled() ? 1 : 0); // Saddled?
|
||||
}
|
||||
else if (a_Entity.IsA("cVillager"))
|
||||
{
|
||||
WriteByte(0x50);
|
||||
WriteInt(a_Entity.GetVilType()); // What sort of TESTIFICATE?
|
||||
}
|
||||
else if (a_Entity.IsA("cZombie"))
|
||||
{
|
||||
WriteByte(0xC);
|
||||
WriteByte(a_Entity.IsBabby() ? 1 : 0); // Babby zombie?
|
||||
WriteByte(0xD);
|
||||
WriteByte(a_Entity.IsVillZomb() ? 1 : 0); // Converted zombie?
|
||||
WriteByte(0xE);
|
||||
WriteByte(a_Entity.IsConvert() ? 1 : 0); // Converted-but-converting-back zombllager?
|
||||
}
|
||||
else if (a_Entity.IsA("cGhast"))
|
||||
{
|
||||
WriteByte(0x10);
|
||||
WriteByte(a_Entity.IsCharging()); // About to eject un flamé-bol? :P
|
||||
}
|
||||
else if (a_Entity.IsA("cArrowEntity"))
|
||||
{
|
||||
WriteByte(0x10);
|
||||
WriteByte(a_Entity.IsCritical() ? 1 : 0); // Critical hitting arrow?
|
||||
}
|
||||
else if (a_Entity.IsA("cWolf"))
|
||||
{
|
||||
Byte WolfStatus = 0;
|
||||
if (a_Entity.IsSitting())
|
||||
{
|
||||
WolfStatus |= 0x1;
|
||||
}
|
||||
if (a_Entity.IsAngry())
|
||||
{
|
||||
WolfStatus |= 0x2;
|
||||
}
|
||||
if (a_Entity.IsTame())
|
||||
{
|
||||
WolfStatus |= 0x4;
|
||||
}
|
||||
WriteByte(0x10);
|
||||
WriteByte(WolfStatus);
|
||||
|
||||
WriteByte(0x72);
|
||||
WriteFloat((float)(a_Entity.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way)
|
||||
WriteByte(0x13);
|
||||
WriteByte(a_Entity.IsBegging() ? 1 : 0); // Ultra cute mode?
|
||||
}
|
||||
else if (a_Entity.IsA("cSheep"))
|
||||
{
|
||||
// [1](1111)
|
||||
// [] = Is sheared? () = Color, from 0 to 15
|
||||
|
||||
WriteByte(0x10);
|
||||
Byte SheepMetadata = 0;
|
||||
SheepMetadata = a_Entity.GetFurColor(); // Fur colour
|
||||
|
||||
if (a_Entity.IsSheared()) // Is sheared?
|
||||
{
|
||||
SheepMetadata |= 0x16;
|
||||
}
|
||||
WriteByte(SheepMetadata);
|
||||
}
|
||||
else if (a_Entity.IsA("cEnderman"))
|
||||
{
|
||||
WriteByte(0x10);
|
||||
WriteByte(a_Entity.CarriedBlock()); // Stolen block
|
||||
WriteByte(0x11);
|
||||
WriteByte(a_Entity.CarriedMeta()); // Stolen metea
|
||||
WriteByte(0x12);
|
||||
WriteByte(a_Entity.IsScream() ? 1 : 0); // I HATE YER FACE, I SCWEAM AT YER FACE
|
||||
}
|
||||
else if (a_Entity.IsA("cSkeleton"))
|
||||
{
|
||||
WriteByte(0xD);
|
||||
WriteByte(a_Entity.IsWither() ? 1 : 0); // It's a skeleton, but it's not
|
||||
}
|
||||
else if (a_Entity.IsA("cWitch"))
|
||||
{
|
||||
WriteByte(0x15);
|
||||
WriteByte(a_Entity.IsNosey() ? 1 : 0); // Drinking-nose: like Squidward
|
||||
}
|
||||
else if ((a_Entity.IsA("cSlime")) || (a_Entity.IsA("cMagmaCube")))
|
||||
{
|
||||
WriteByte(0x10);
|
||||
WriteByte(a_Entity.GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
|
||||
}
|
||||
else if (a_Entity.IsA("cHorse"))
|
||||
{
|
||||
int Flags = 0;
|
||||
if (a_Entity.IsTame())
|
||||
{
|
||||
Flags |= 0x2;
|
||||
}
|
||||
if (a_Entity.IsSaddled())
|
||||
{
|
||||
Flags |= 0x4;
|
||||
}
|
||||
if (a_Entity.IsChested())
|
||||
{
|
||||
Flags |= 0x8;
|
||||
}
|
||||
if (a_Entity.IsBabby())
|
||||
{
|
||||
Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer
|
||||
}
|
||||
if (a_Entity.IsEating())
|
||||
{
|
||||
Flags |= 0x20;
|
||||
}
|
||||
if (a_Entity.IsRearing())
|
||||
{
|
||||
Flags |= 0x40;
|
||||
}
|
||||
if (a_Entity.IsMthOpen())
|
||||
{
|
||||
Flags |= 0x80;
|
||||
}
|
||||
WriteByte(0x50);
|
||||
WriteInt(Flags);
|
||||
|
||||
WriteByte(0x13);
|
||||
WriteByte(a_Entity.GetHType()); // Type of horse (donkey, chestnut, etc.)
|
||||
|
||||
WriteByte(0x54);
|
||||
int Appearance = 0;
|
||||
Appearance = a_Entity.GetHColor(); // Mask FF
|
||||
Appearance |= a_Entity.GetHStyle() * 256; // Mask FF00, so multiply by 256
|
||||
WriteInt(Appearance);
|
||||
|
||||
WriteByte(0x56);
|
||||
WriteInt(a_Entity.GetHArmour()); // Horshey armour
|
||||
}
|
||||
|
||||
// End Specific Metadata
|
||||
// End Metadata Packet
|
||||
|
||||
WriteByte(0x7f);
|
||||
}
|
||||
|
||||
|
||||
|
@ -142,11 +142,8 @@ protected:
|
||||
/// Parses one item, "slot" as the protocol wiki calls it, from m_ReceivedData; returns the usual ParsePacket() codes
|
||||
virtual int ParseItem(cItem & a_Item);
|
||||
|
||||
/// Returns the entity metadata representation
|
||||
AString GetEntityMetaData(const cEntity & a_Entity);
|
||||
|
||||
/// Returns the entity common metadata, index 0 (generic flags)
|
||||
char GetEntityMetadataFlags(const cEntity & a_Entity);
|
||||
/// Writes the entity metadata
|
||||
void WriteMetadata(const cEntity & a_Entity);
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -416,8 +416,7 @@ void cProtocol132::SendSpawnMob(const cMonster & a_Mob)
|
||||
WriteShort ((short)(a_Mob.GetSpeedX() * 400));
|
||||
WriteShort ((short)(a_Mob.GetSpeedY() * 400));
|
||||
WriteShort ((short)(a_Mob.GetSpeedZ() * 400));
|
||||
AString MetaData = GetEntityMetaData(a_Mob);
|
||||
SendData (MetaData.data(), MetaData.size());
|
||||
WriteMetadata(a_Mob);
|
||||
Flush();
|
||||
}
|
||||
|
||||
|
@ -2572,7 +2572,17 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp
|
||||
{
|
||||
cMonster * Monster = NULL;
|
||||
|
||||
int Size = GetTickRandomNumber(2) + 1; // 1 .. 3
|
||||
int SlSize = GetTickRandomNumber(2) + 1; // 1 .. 3 - Slime
|
||||
int ShColor = GetTickRandomNumber(15); // 0 .. 15 - Sheep
|
||||
bool SkType = GetDimension() == biNether; // Skeleton
|
||||
int VilType = GetTickRandomNumber(5); // 0 .. 5 - Villager
|
||||
|
||||
int HseType = GetTickRandomNumber(7); // 0 .. 7 - Horse Type (donkey, zombie, etc.)
|
||||
int HseColor = GetTickRandomNumber(6); // 0 .. 6 - Horse
|
||||
int HseStyle = GetTickRandomNumber(4); // 0 .. 4 - Horse
|
||||
int HseTameTimes = GetTickRandomNumber(6) + 1; // 1 .. 7 - Horse tame amount
|
||||
|
||||
if ((HseType == 5) || (HseType == 6) || (HseType == 7)) { HseType = 0; } // 5,6,7 = 0 because little chance of getting 0 with TickRand
|
||||
|
||||
switch (a_MonsterType)
|
||||
{
|
||||
@ -2586,20 +2596,23 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp
|
||||
case cMonster::mtEnderDragon: Monster = new cEnderDragon(); break;
|
||||
case cMonster::mtGhast: Monster = new cGhast(); break;
|
||||
case cMonster::mtGiant: Monster = new cGiant(); break;
|
||||
case cMonster::mtHorse: Monster = new cHorse(); break;
|
||||
case cMonster::mtHorse:
|
||||
{
|
||||
Monster = new cHorse(HseType, HseColor, HseStyle, HseTameTimes); break;
|
||||
}
|
||||
case cMonster::mtIronGolem: Monster = new cIronGolem(); break;
|
||||
case cMonster::mtMagmaCube: Monster = new cMagmaCube(Size); break;
|
||||
case cMonster::mtMagmaCube: Monster = new cMagmaCube(SlSize); break;
|
||||
case cMonster::mtMooshroom: Monster = new cMooshroom(); break;
|
||||
case cMonster::mtOcelot: Monster = new cOcelot(); break;
|
||||
case cMonster::mtPig: Monster = new cPig(); break;
|
||||
case cMonster::mtSheep: Monster = new cSheep(); break;
|
||||
case cMonster::mtSheep: Monster = new cSheep(ShColor); break;
|
||||
case cMonster::mtSilverfish: Monster = new cSilverfish(); break;
|
||||
case cMonster::mtSkeleton: Monster = new cSkeleton(); break;
|
||||
case cMonster::mtSlime: Monster = new cSlime(Size); break;
|
||||
case cMonster::mtSkeleton: Monster = new cSkeleton(SkType); break;
|
||||
case cMonster::mtSlime: Monster = new cSlime(SlSize); break;
|
||||
case cMonster::mtSnowGolem: Monster = new cSnowGolem(); break;
|
||||
case cMonster::mtSpider: Monster = new cSpider(); break;
|
||||
case cMonster::mtSquid: Monster = new cSquid(); break;
|
||||
case cMonster::mtVillager: Monster = new cVillager(); break;
|
||||
case cMonster::mtVillager: Monster = new cVillager(VilType); break;
|
||||
case cMonster::mtWitch: Monster = new cWitch(); break;
|
||||
case cMonster::mtWither: Monster = new cWither(); break;
|
||||
case cMonster::mtWolf: Monster = new cWolf(); break;
|
||||
@ -2624,7 +2637,11 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp
|
||||
delete Monster;
|
||||
return -1;
|
||||
}
|
||||
|
||||
BroadcastSpawnEntity(*Monster);
|
||||
// Because it's logical that ALL mob spawns need spawn effects, not just spawners
|
||||
BroadcastSoundParticleEffect(2004, (int)(floor(a_PosX) * 8), (int)(floor(a_PosY) * 8), (int)(floor(a_PosZ) * 8), 0);
|
||||
|
||||
cPluginManager::Get()->CallHookSpawnedMonster(*this, *Monster);
|
||||
return Monster->GetUniqueID();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user