1
0
cuberite-2a/src/Mobs/Wolf.cpp
Gargaj 392a3d319c fix cavespider poisoning even if attack is in cooldown
make attack function more responsive

fix cavespider poisoning even if attack is in cooldown
make attack function more responsive

Merge branch 'cavespider-attack' of github.com:Gargaj/cuberite into cavespider-attack

code style

fix cavespider poisoning even if attack is in cooldown
make attack function more responsive

fix cavespider poisoning even if attack is in cooldown
make attack function more responsive

Merge branch 'cavespider-attack' of github.com:Gargaj/cuberite into cavespider-attack

code style

Merge branch 'cavespider-attack' of github.com:Gargaj/cuberite into cavespider-attack

Merge branch 'master' into cavespider-attack

Merge branch 'master' into cavespider-attack

fix cavespider poisoning even if attack is in cooldown
make attack function more responsive

fix cavespider poisoning even if attack is in cooldown
make attack function more responsive

Merge branch 'cavespider-attack' of github.com:Gargaj/cuberite into cavespider-attack

code style

fix cavespider poisoning even if attack is in cooldown
make attack function more responsive

fix cavespider poisoning even if attack is in cooldown
make attack function more responsive

Merge branch 'cavespider-attack' of github.com:Gargaj/cuberite into cavespider-attack

code style

Merge branch 'cavespider-attack' of github.com:Gargaj/cuberite into cavespider-attack

Merge branch 'master' into cavespider-attack

Merge branch 'master' into cavespider-attack

Merge branch 'cavespider-attack' of github.com:Gargaj/cuberite into cavespider-attack
2015-11-08 21:01:02 +01:00

251 lines
4.8 KiB
C++

#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"
#include "../Items/ItemHandler.h"
#include "Broadcaster.h"
cWolf::cWolf(void) :
super("Wolf", mtWolf, "mob.wolf.hurt", "mob.wolf.death", 0.6, 0.8),
m_IsSitting(false),
m_IsTame(false),
m_IsBegging(false),
m_IsAngry(false),
m_OwnerName(""),
m_CollarColor(14)
{
m_RelativeWalkSpeed = 2;
}
bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
{
if (super::DoTakeDamage(a_TDI))
{
return false;
}
if (!m_IsTame)
{
m_IsAngry = true;
}
m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face
return true;
}
bool cWolf::Attack(std::chrono::milliseconds a_Dt)
{
UNUSED(a_Dt);
if ((m_Target != nullptr) && (m_Target->IsPlayer()))
{
if (static_cast<cPlayer *>(m_Target)->GetName() != m_OwnerName)
{
return super::Attack(a_Dt);
}
}
else
{
return super::Attack(a_Dt);
}
return false;
}
void cWolf::OnRightClicked(cPlayer & a_Player)
{
if (!IsTame() && !IsAngry())
{
// If the player is holding a bone, try to tame the wolf:
if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_BONE)
{
if (!a_Player.IsGameModeCreative())
{
a_Player.GetInventory().RemoveOneEquippedItem();
}
if (m_World->GetTickRandomNumber(7) == 0)
{
// Taming succeeded
SetMaxHealth(20);
SetIsTame(true);
SetOwner(a_Player.GetName(), a_Player.GetUUID());
m_World->BroadcastEntityStatus(*this, esWolfTamed);
m_World->GetBroadcaster().BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
}
else
{
// Taming failed
m_World->BroadcastEntityStatus(*this, esWolfTaming);
m_World->GetBroadcaster().BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
}
}
}
else if (IsTame())
{
// Feed the wolf, restoring its health, or dye its collar:
switch (a_Player.GetEquippedItem().m_ItemType)
{
case E_ITEM_RAW_BEEF:
case E_ITEM_STEAK:
case E_ITEM_RAW_PORKCHOP:
case E_ITEM_COOKED_PORKCHOP:
case E_ITEM_RAW_CHICKEN:
case E_ITEM_COOKED_CHICKEN:
case E_ITEM_ROTTEN_FLESH:
{
if (m_Health < m_MaxHealth)
{
Heal(ItemHandler(a_Player.GetEquippedItem().m_ItemType)->GetFoodInfo().FoodLevel);
if (!a_Player.IsGameModeCreative())
{
a_Player.GetInventory().RemoveOneEquippedItem();
}
}
break;
}
case E_ITEM_DYE:
{
if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog?
{
SetCollarColor(15 - a_Player.GetEquippedItem().m_ItemDamage);
if (!a_Player.IsGameModeCreative())
{
a_Player.GetInventory().RemoveOneEquippedItem();
}
}
break;
}
default:
{
if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog?
{
SetIsSitting(!IsSitting());
}
}
}
}
m_World->BroadcastEntityMetadata(*this);
}
void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
if (!IsAngry())
{
cMonster::Tick(a_Dt, a_Chunk);
}
else
{
super::Tick(a_Dt, a_Chunk);
}
cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance));
if (a_Closest_Player != nullptr)
{
switch (a_Closest_Player->GetEquippedItem().m_ItemType)
{
case E_ITEM_BONE:
case E_ITEM_RAW_BEEF:
case E_ITEM_STEAK:
case E_ITEM_RAW_CHICKEN:
case E_ITEM_COOKED_CHICKEN:
case E_ITEM_ROTTEN_FLESH:
case E_ITEM_RAW_PORKCHOP:
case E_ITEM_COOKED_PORKCHOP:
{
if (!IsBegging())
{
SetIsBegging(true);
m_World->BroadcastEntityMetadata(*this);
}
m_FinalDestination = a_Closest_Player->GetPosition(); // So that we will look at a player holding food
// Don't move to the player if the wolf is sitting.
if (!IsSitting())
{
MoveToPosition(a_Closest_Player->GetPosition());
}
break;
}
default:
{
if (IsBegging())
{
SetIsBegging(false);
m_World->BroadcastEntityMetadata(*this);
}
}
}
}
if (IsTame() && !IsSitting())
{
TickFollowPlayer();
}
else if (IsSitting())
{
StopMovingToPosition();
}
}
void cWolf::TickFollowPlayer()
{
class cCallback :
public cPlayerListCallback
{
virtual bool Item(cPlayer * a_Player) override
{
OwnerPos = a_Player->GetPosition();
return false;
}
public:
Vector3d OwnerPos;
} Callback;
if (m_World->DoWithPlayer(m_OwnerName, Callback))
{
// The player is present in the world, follow him:
double Distance = (Callback.OwnerPos - GetPosition()).Length();
if (Distance > 20)
{
Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z);
TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z);
}
else
{
MoveToPosition(Callback.OwnerPos);
}
}
}