1
0
Fork 0

Implemented basic eating support.

Food is now properly consumed and it takes 1.5 sec.
This commit is contained in:
madmaxoft 2013-07-28 19:15:03 +02:00
parent 00196e975a
commit 4746d2251c
7 changed files with 134 additions and 63 deletions

View File

@ -555,11 +555,8 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem());
if (ItemHandler->IsFood())
{
if (PlgMgr->CallHookPlayerEating(*m_Player))
{
// A plugin doesn't agree with the action. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return;
}
m_Player->AbortEating();
return;
}
else
{
@ -569,7 +566,7 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch
return;
}
}
LOGINFO("%s: Status SHOOT / EAT not implemented", __FUNCTION__);
LOGINFO("%s: Status SHOOT not implemented", __FUNCTION__);
return;
}
@ -804,15 +801,14 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, c
}
else if (ItemHandler->IsFood())
{
cItem Item;
Item.m_ItemType = Equipped.m_ItemType;
Item.m_ItemCount = 1;
if (ItemHandler->EatItem(m_Player, &Item))
m_Player->StartEating();
if (PlgMgr->CallHookPlayerEating(*m_Player))
{
ItemHandler->OnFoodEaten(World, m_Player, &Item);
m_Player->GetInventory().RemoveOneEquippedItem();
// A plugin won't let us eat, abort (send the proper packets to the client, too):
m_Player->AbortEating();
return;
}
return;
}
else
{

View File

@ -281,6 +281,9 @@ private:
/// Buffer for received messages to be processed in the Tick thread
AStringList m_PendingMessages;
static int s_ClientCount;
int m_UniqueID;
@ -307,14 +310,11 @@ private:
/// Processes the messages in m_PendingMessages; called from the Tick thread
void ProcessPendingMessages(void);
// cSocketThreads::cCallback overrides:
virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client
virtual void GetOutgoingData(AString & a_Data) override; // Data can be sent to client
virtual void SocketClosed (void) override; // The socket has been closed for any reason
static int s_ClientCount;
int m_UniqueID;
}; // tolua_export

View File

@ -4,53 +4,53 @@
#include "ItemHandler.h"
class cItemFoodHandler : public cItemHandler
class cItemFoodHandler :
public cItemHandler
{
typedef cItemHandler super;
public:
cItemFoodHandler(int a_ItemType)
: cItemHandler(a_ItemType)
: super(a_ItemType)
{
}
virtual bool IsFood() override
virtual bool IsFood(void) override
{
return true;
}
virtual FoodInfo GetFoodInfo() override
virtual FoodInfo GetFoodInfo(void) override
{
switch(m_ItemType)
{
case E_ITEM_BREAD:
return FoodInfo(5, 6.f);
case E_ITEM_COOKIE:
return FoodInfo(2, 0.4f);
case E_ITEM_MELON_SLICE:
return FoodInfo(2, 1.2f);
case E_ITEM_RAW_CHICKEN:
return FoodInfo(2, 1.2f, 30);
case E_ITEM_COOKED_CHICKEN:
return FoodInfo(6, 7.2f);
case E_ITEM_RAW_BEEF:
case E_ITEM_RAW_PORKCHOP:
return FoodInfo(3, 1.8f);
case E_ITEM_STEAK:
case E_ITEM_COOKED_PORKCHOP:
return FoodInfo(8, 12.8f);
case E_ITEM_RAW_FISH:
return FoodInfo(2, 1.2f);
case E_ITEM_COOKED_FISH:
return FoodInfo(5, 6.f);
case E_ITEM_RED_APPLE:
return FoodInfo(4, 2.4f);
case E_ITEM_GOLDEN_APPLE:
return FoodInfo(4, 9.6f);
case E_ITEM_ROTTEN_FLESH:
return FoodInfo(4, 0.8f, 80);
case E_ITEM_SPIDER_EYE:
return FoodInfo(2, 3.2f, 100);
case E_ITEM_BREAD: return FoodInfo(5, 6);
case E_ITEM_COOKIE: return FoodInfo(2, 0.4);
case E_ITEM_MELON_SLICE: return FoodInfo(2, 1.2);
case E_ITEM_RAW_CHICKEN: return FoodInfo(2, 1.2, 30);
case E_ITEM_COOKED_CHICKEN: return FoodInfo(6, 7.2);
case E_ITEM_RAW_BEEF: return FoodInfo(3, 1.8);
case E_ITEM_RAW_PORKCHOP: return FoodInfo(3, 1.8);
case E_ITEM_STEAK: return FoodInfo(8, 12.8);
case E_ITEM_COOKED_PORKCHOP: return FoodInfo(8, 12.8);
case E_ITEM_RAW_FISH: return FoodInfo(2, 1.2);
case E_ITEM_COOKED_FISH: return FoodInfo(5, 6);
case E_ITEM_RED_APPLE: return FoodInfo(4, 2.4);
case E_ITEM_GOLDEN_APPLE: return FoodInfo(4, 9.6);
case E_ITEM_ROTTEN_FLESH: return FoodInfo(4, 0.8, 80);
case E_ITEM_SPIDER_EYE: return FoodInfo(2, 3.2, 100);
}
LOGWARNING("%s: Unknown food item (%d), returning zero nutrition", __FUNCTION__, m_ItemType);
return FoodInfo(0, 0.f);
}
};
};

View File

@ -4,6 +4,7 @@
#include "../Item.h"
#include "../World.h"
#include "../Player.h"
#include "../FastRandom.h"
// Handlers:
#include "ItemBed.h"
@ -465,15 +466,17 @@ bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item)
{
FoodInfo Info = GetFoodInfo();
if(Info.FoodLevel > 0 || Info.Saturation > 0.f)
if ((Info.FoodLevel > 0) || (Info.Saturation > 0.f))
{
bool Success = a_Player->Feed(Info.FoodLevel, Info.Saturation);
if(Success && Info.PoisionChance > 0)
// If consumed and there's chance of foodpoisoning, do it:
if (Success && (Info.PoisonChance > 0))
{
MTRand r1;
if((r1.randInt(100) - Info.PoisionChance) <= 0)
{ //Unlucky guy :D
//TODO: Make player ill
cFastRandom r1;
if ((r1.NextInt(100, a_Player->GetUniqueID()) - Info.PoisonChance) <= 0)
{
a_Player->FoodPoison(300);
}
}

View File

@ -38,16 +38,17 @@ public:
struct FoodInfo
{
FoodInfo(short a_FoodLevel, float a_Saturation, char a_PoisionChance = 0)
int FoodLevel;
double Saturation;
int PoisonChance; // 0 - 100, in percent. 0 = no chance of poisoning, 100 = sure poisoning
FoodInfo(int a_FoodLevel, double a_Saturation, int a_PoisonChance = 0) :
FoodLevel(a_FoodLevel),
Saturation(a_Saturation),
PoisonChance(a_PoisonChance)
{
FoodLevel = a_FoodLevel;
Saturation = a_Saturation;
PoisionChance = a_PoisionChance;
}
short FoodLevel;
float Saturation;
char PoisionChance; //0 - 100
};
} ;
/// Returns the FoodInfo for this item. (FoodRecovery, Saturation and PoisionChance)
virtual FoodInfo GetFoodInfo();

View File

@ -20,6 +20,7 @@
#include "OSSupport/Timer.h"
#include "MersenneTwister.h"
#include "Chunk.h"
#include "Items/ItemHandler.h"
#include "Vector3d.h"
#include "Vector3f.h"
@ -58,6 +59,7 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
, m_SprintingMaxSpeed(0.13)
, m_IsCrouched(false)
, m_IsSprinting(false)
, m_EatingFinishTick(-1)
{
LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
@ -189,6 +191,11 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
{
m_World->CollectPickupsByPlayer(this);
if ((m_EatingFinishTick >= 0) && (m_EatingFinishTick <= m_World->GetWorldAge()))
{
FinishEating();
}
HandleFood();
}
@ -349,6 +356,57 @@ void cPlayer::FoodPoison(int a_NumTicks)
void cPlayer::StartEating(void)
{
// Set the timer:
m_EatingFinishTick = m_World->GetWorldAge() + EATING_TICKS;
// Send the packets:
m_World->BroadcastPlayerAnimation(*this, 5);
m_World->BroadcastEntityMetadata(*this);
}
void cPlayer::FinishEating(void)
{
// Reset the timer:
m_EatingFinishTick = -1;
// Send the packets:
m_ClientHandle->SendEntityStatus(*this, ENTITY_STATUS_EATING_ACCEPTED);
m_World->BroadcastPlayerAnimation(*this, 0);
m_World->BroadcastEntityMetadata(*this);
// consume the item:
cItem Item(GetEquippedItem());
Item.m_ItemCount = 1;
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(Item.m_ItemType);
if (!ItemHandler->EatItem(this, &Item))
{
return;
}
ItemHandler->OnFoodEaten(m_World, this, &Item);
GetInventory().RemoveOneEquippedItem();
}
void cPlayer::AbortEating(void)
{
m_EatingFinishTick = -1;
m_World->BroadcastPlayerAnimation(*this, 0);
m_World->BroadcastEntityMetadata(*this);
}
void cPlayer::SendHealth(void)
{
if (m_ClientHandle != NULL)

View File

@ -28,6 +28,7 @@ public:
{
MAX_HEALTH = 20,
MAX_FOOD_LEVEL = 20,
EATING_TICKS = 30, ///< Number of ticks it takes to eat an item
} ;
// tolua_end
@ -164,6 +165,15 @@ public:
// tolua_end
/// Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet
void StartEating(void);
/// Finishes eating the currently equipped item. Consumes the item, updates health and broadcasts the packets
void FinishEating(void);
/// Aborts the current eating operation
void AbortEating(void);
virtual void KilledBy(cEntity * a_Killer) override;
void Respawn(void); // tolua_export
@ -296,6 +306,9 @@ protected:
bool m_IsCrouched;
bool m_IsSprinting;
/// The world tick in which eating will be finished. -1 if not eating
Int64 m_EatingFinishTick;
virtual void Destroyed(void);