Merge pull request #1272 from Howaner/Food
Fixed hunger bugs, Implemented golden apple, added jump statistic, added...
This commit is contained in:
commit
d2744713bb
@ -635,6 +635,7 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
|
||||
|
||||
if (!m_Player->IsSwimming())
|
||||
{
|
||||
m_Player->GetStatManager().AddValue(statJumps, 1);
|
||||
m_Player->AddFoodExhaustion(m_Player->IsSprinting() ? 0.8 : 0.2);
|
||||
}
|
||||
}
|
||||
@ -1121,6 +1122,7 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
|
||||
return;
|
||||
}
|
||||
|
||||
m_Player->AddFoodExhaustion(0.025);
|
||||
ItemHandler->OnBlockDestroyed(World, m_Player, m_Player->GetEquippedItem(), a_BlockX, a_BlockY, a_BlockZ);
|
||||
// The ItemHandler is also responsible for spawning the pickups
|
||||
cChunkInterface ChunkInterface(World->GetChunkMap());
|
||||
@ -1266,7 +1268,7 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
|
||||
else if ((ItemHandler->IsFood() || ItemHandler->IsDrinkable(EquippedDamage)))
|
||||
{
|
||||
if ((m_Player->IsSatiated() || m_Player->IsGameModeCreative()) &&
|
||||
ItemHandler->IsFood())
|
||||
ItemHandler->IsFood() && (Equipped.m_ItemType != E_ITEM_GOLDEN_APPLE))
|
||||
{
|
||||
// The player is satiated or in creative, and trying to eat
|
||||
return;
|
||||
|
@ -309,7 +309,7 @@ void cEntityEffectHunger::OnTick(cPawn & a_Target)
|
||||
if (a_Target.IsPlayer())
|
||||
{
|
||||
cPlayer & Target = (cPlayer &) a_Target;
|
||||
Target.SetFoodExhaustionLevel(Target.GetFoodExhaustionLevel() + 0.025); // 0.5 per second = 0.025 per tick
|
||||
Target.AddFoodExhaustion(0.025 * ((double)GetIntensity() + 1.0)); // 0.5 per second = 0.025 per tick
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,7 +545,7 @@ void cPlayer::SetFoodTickTimer(int a_FoodTickTimer)
|
||||
|
||||
void cPlayer::SetFoodExhaustionLevel(double a_FoodExhaustionLevel)
|
||||
{
|
||||
m_FoodExhaustionLevel = std::max(0.0, std::min(a_FoodExhaustionLevel, 4.0));
|
||||
m_FoodExhaustionLevel = std::max(0.0, std::min(a_FoodExhaustionLevel, 40.0));
|
||||
}
|
||||
|
||||
|
||||
@ -568,6 +568,18 @@ bool cPlayer::Feed(int a_Food, double a_Saturation)
|
||||
|
||||
|
||||
|
||||
void cPlayer::AddFoodExhaustion(double a_Exhaustion)
|
||||
{
|
||||
if (!IsGameModeCreative())
|
||||
{
|
||||
m_FoodExhaustionLevel = std::min(m_FoodExhaustionLevel + a_Exhaustion, 40.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPlayer::FoodPoison(int a_NumTicks)
|
||||
{
|
||||
AddEntityEffect(cEntityEffect::effHunger, a_NumTicks, 0, 1);
|
||||
@ -1979,19 +1991,34 @@ void cPlayer::HandleFood(void)
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply food exhaustion that has accumulated:
|
||||
if (m_FoodExhaustionLevel > 4.0)
|
||||
{
|
||||
m_FoodExhaustionLevel -= 4.0;
|
||||
|
||||
if (m_FoodSaturationLevel > 0.0)
|
||||
{
|
||||
m_FoodSaturationLevel = std::max(m_FoodSaturationLevel - 1.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFoodLevel(m_FoodLevel - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Heal or damage, based on the food level, using the m_FoodTickTimer:
|
||||
if ((m_FoodLevel > 17) || (m_FoodLevel <= 0))
|
||||
if ((m_FoodLevel >= 18) || (m_FoodLevel <= 0))
|
||||
{
|
||||
m_FoodTickTimer++;
|
||||
if (m_FoodTickTimer >= 80)
|
||||
{
|
||||
m_FoodTickTimer = 0;
|
||||
|
||||
if ((m_FoodLevel > 17) && (GetHealth() < GetMaxHealth()))
|
||||
if ((m_FoodLevel >= 18) && (GetHealth() < GetMaxHealth()))
|
||||
{
|
||||
// Regenerate health from food, incur 3 pts of food exhaustion:
|
||||
Heal(1);
|
||||
m_FoodExhaustionLevel += 3.0;
|
||||
AddFoodExhaustion(3.0);
|
||||
}
|
||||
else if ((m_FoodLevel <= 0) && (m_Health > 1))
|
||||
{
|
||||
@ -2000,20 +2027,9 @@ void cPlayer::HandleFood(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply food exhaustion that has accumulated:
|
||||
if (m_FoodExhaustionLevel >= 4.0)
|
||||
else
|
||||
{
|
||||
m_FoodExhaustionLevel -= 4.0;
|
||||
|
||||
if (m_FoodSaturationLevel >= 1.0)
|
||||
{
|
||||
m_FoodSaturationLevel -= 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFoodLevel(m_FoodLevel - 1);
|
||||
}
|
||||
m_FoodTickTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2088,14 +2104,17 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos)
|
||||
else if (IsSubmerged())
|
||||
{
|
||||
m_Stats.AddValue(statDistDove, Value);
|
||||
AddFoodExhaustion(0.00015 * (double)Value);
|
||||
}
|
||||
else if (IsSwimming())
|
||||
{
|
||||
m_Stats.AddValue(statDistSwum, Value);
|
||||
AddFoodExhaustion(0.00015 * (double)Value);
|
||||
}
|
||||
else if (IsOnGround())
|
||||
{
|
||||
m_Stats.AddValue(statDistWalked, Value);
|
||||
AddFoodExhaustion((m_IsSprinting ? 0.001 : 0.0001) * (double)Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -284,10 +284,7 @@ public:
|
||||
bool Feed(int a_Food, double a_Saturation);
|
||||
|
||||
/** Adds the specified exhaustion to m_FoodExhaustion. Expects only positive values. */
|
||||
void AddFoodExhaustion(double a_Exhaustion)
|
||||
{
|
||||
m_FoodExhaustionLevel += a_Exhaustion;
|
||||
}
|
||||
void AddFoodExhaustion(double a_Exhaustion);
|
||||
|
||||
/** Starts the food poisoning for the specified amount of ticks */
|
||||
void FoodPoison(int a_NumTicks);
|
||||
|
@ -33,29 +33,69 @@ public:
|
||||
case E_ITEM_BREAD: return FoodInfo(5, 6);
|
||||
// Carrots handled in ItemSeeds
|
||||
case E_ITEM_COOKED_CHICKEN: return FoodInfo(6, 7.2);
|
||||
case E_ITEM_COOKED_FISH: return FoodInfo(5, 6);
|
||||
case E_ITEM_COOKED_FISH: return FoodInfo(5, 6); // TODO: Add other fish types
|
||||
case E_ITEM_COOKED_PORKCHOP: return FoodInfo(8, 12.8);
|
||||
case E_ITEM_COOKIE: return FoodInfo(2, 0.4);
|
||||
case E_ITEM_GOLDEN_APPLE: return FoodInfo(4, 9.6);
|
||||
// Golden apple handled in ItemGoldenApple
|
||||
case E_ITEM_GOLDEN_CARROT: return FoodInfo(6, 14.4);
|
||||
case E_ITEM_MELON_SLICE: return FoodInfo(2, 1.2);
|
||||
case E_ITEM_MUSHROOM_SOUP: return FoodInfo(6, 7.2);
|
||||
case E_ITEM_POISONOUS_POTATO: return FoodInfo(2, 1.2, 60);
|
||||
case E_ITEM_POISONOUS_POTATO: return FoodInfo(2, 1.2);
|
||||
// Potatoes handled in ItemSeeds
|
||||
case E_ITEM_PUMPKIN_PIE: return FoodInfo(8, 4.8);
|
||||
case E_ITEM_RAW_BEEF: return FoodInfo(3, 1.8);
|
||||
case E_ITEM_RAW_CHICKEN: return FoodInfo(2, 1.2, 30);
|
||||
case E_ITEM_RAW_CHICKEN: return FoodInfo(2, 1.2);
|
||||
case E_ITEM_RAW_FISH: return FoodInfo(2, 1.2);
|
||||
case E_ITEM_RAW_PORKCHOP: return FoodInfo(3, 1.8);
|
||||
case E_ITEM_RED_APPLE: return FoodInfo(4, 2.4);
|
||||
case E_ITEM_ROTTEN_FLESH: return FoodInfo(4, 0.8, 80);
|
||||
case E_ITEM_SPIDER_EYE: return FoodInfo(2, 3.2, 100);
|
||||
case E_ITEM_ROTTEN_FLESH: return FoodInfo(4, 0.8);
|
||||
case E_ITEM_SPIDER_EYE: return FoodInfo(2, 3.2);
|
||||
case E_ITEM_STEAK: return FoodInfo(8, 12.8);
|
||||
}
|
||||
LOGWARNING("%s: Unknown food item (%d), returning zero nutrition", __FUNCTION__, m_ItemType);
|
||||
return FoodInfo(0, 0.f);
|
||||
}
|
||||
|
||||
|
||||
virtual bool GetEatEffect(cEntityEffect::eType & a_EffectType, int & a_EffectDurationTicks, short & a_EffectIntensity, float & a_Chance) override
|
||||
{
|
||||
switch (m_ItemType)
|
||||
{
|
||||
case E_ITEM_RAW_CHICKEN:
|
||||
{
|
||||
a_EffectType = cEntityEffect::effHunger;
|
||||
a_EffectDurationTicks = 600;
|
||||
a_EffectIntensity = 0;
|
||||
a_Chance = 0.3f;
|
||||
return true;
|
||||
}
|
||||
case E_ITEM_ROTTEN_FLESH:
|
||||
{
|
||||
a_EffectType = cEntityEffect::effHunger;
|
||||
a_EffectDurationTicks = 600;
|
||||
a_EffectIntensity = 0;
|
||||
a_Chance = 0.8f;
|
||||
return true;
|
||||
}
|
||||
case E_ITEM_SPIDER_EYE:
|
||||
{
|
||||
a_EffectType = cEntityEffect::effPoison;
|
||||
a_EffectDurationTicks = 100;
|
||||
a_EffectIntensity = 0;
|
||||
a_Chance = 1.0f;
|
||||
return true;
|
||||
}
|
||||
case E_ITEM_POISONOUS_POTATO:
|
||||
{
|
||||
a_EffectType = cEntityEffect::effPoison;
|
||||
a_EffectDurationTicks = 100;
|
||||
a_EffectIntensity = 0;
|
||||
a_Chance = 0.6f;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
58
src/Items/ItemGoldenApple.h
Normal file
58
src/Items/ItemGoldenApple.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "ItemFood.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cItemGoldenAppleHandler :
|
||||
public cItemFoodHandler
|
||||
{
|
||||
typedef cItemFoodHandler super;
|
||||
|
||||
public:
|
||||
cItemGoldenAppleHandler()
|
||||
: super(E_ITEM_GOLDEN_APPLE)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) override
|
||||
{
|
||||
// Feed the player:
|
||||
FoodInfo Info = GetFoodInfo();
|
||||
a_Player->Feed(Info.FoodLevel, Info.Saturation);
|
||||
|
||||
// Add the effects:
|
||||
a_Player->AddEntityEffect(cEntityEffect::effAbsorption, 2400, 0);
|
||||
a_Player->AddEntityEffect(cEntityEffect::effRegeneration, 100, 1);
|
||||
|
||||
// When the apple is a 'notch apple', give extra effects:
|
||||
if (a_Item->m_ItemDamage > 0)
|
||||
{
|
||||
a_Player->AddEntityEffect(cEntityEffect::effRegeneration, 600, 4);
|
||||
a_Player->AddEntityEffect(cEntityEffect::effResistance, 6000, 0);
|
||||
a_Player->AddEntityEffect(cEntityEffect::effFireResistance, 6000, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual FoodInfo GetFoodInfo(void) override
|
||||
{
|
||||
return FoodInfo(4, 9.6);
|
||||
}
|
||||
|
||||
|
||||
virtual bool GetEatEffect(cEntityEffect::eType & a_EffectType, int & a_EffectDurationTicks, short & a_EffectIntensity, float & a_Chance) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "ItemFishingRod.h"
|
||||
#include "ItemFlowerPot.h"
|
||||
#include "ItemFood.h"
|
||||
#include "ItemGoldenApple.h"
|
||||
#include "ItemItemFrame.h"
|
||||
#include "ItemHoe.h"
|
||||
#include "ItemLeaves.h"
|
||||
@ -106,7 +107,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
|
||||
case E_ITEM_BED: return new cItemBedHandler(a_ItemType);
|
||||
case E_ITEM_BOAT: return new cItemBoatHandler(a_ItemType);
|
||||
case E_ITEM_BOTTLE_O_ENCHANTING: return new cItemBottleOEnchantingHandler();
|
||||
case E_ITEM_BOW: return new cItemBowHandler;
|
||||
case E_ITEM_BOW: return new cItemBowHandler();
|
||||
case E_ITEM_BREWING_STAND: return new cItemBrewingStandHandler(a_ItemType);
|
||||
case E_ITEM_CAKE: return new cItemCakeHandler(a_ItemType);
|
||||
case E_ITEM_CAULDRON: return new cItemCauldronHandler(a_ItemType);
|
||||
@ -120,6 +121,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
|
||||
case E_ITEM_FISHING_ROD: return new cItemFishingRodHandler(a_ItemType);
|
||||
case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType);
|
||||
case E_ITEM_FLOWER_POT: return new cItemFlowerPotHandler(a_ItemType);
|
||||
case E_ITEM_GOLDEN_APPLE: return new cItemGoldenAppleHandler();
|
||||
case E_BLOCK_LILY_PAD: return new cItemLilypadHandler(a_ItemType);
|
||||
case E_ITEM_MAP: return new cItemMapHandler();
|
||||
case E_ITEM_MILK: return new cItemMilkHandler();
|
||||
@ -212,7 +214,6 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
|
||||
case E_ITEM_COOKED_FISH:
|
||||
case E_ITEM_COOKED_PORKCHOP:
|
||||
case E_ITEM_COOKIE:
|
||||
case E_ITEM_GOLDEN_APPLE:
|
||||
case E_ITEM_GOLDEN_CARROT:
|
||||
case E_ITEM_MELON_SLICE:
|
||||
case E_ITEM_MUSHROOM_SOUP:
|
||||
@ -619,29 +620,39 @@ bool cItemHandler::GetPlacementBlockTypeMeta(
|
||||
|
||||
|
||||
|
||||
bool cItemHandler::GetEatEffect(cEntityEffect::eType & a_EffectType, int & a_EffectDurationTicks, short & a_EffectIntensity, float & a_Chance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item)
|
||||
{
|
||||
UNUSED(a_Item);
|
||||
|
||||
FoodInfo Info = GetFoodInfo();
|
||||
|
||||
FoodInfo Info = GetFoodInfo();
|
||||
if ((Info.FoodLevel > 0) || (Info.Saturation > 0.f))
|
||||
{
|
||||
bool Success = a_Player->Feed(Info.FoodLevel, Info.Saturation);
|
||||
|
||||
// If consumed and there's chance of foodpoisoning, do it:
|
||||
if (Success && (Info.PoisonChance > 0))
|
||||
|
||||
// Give effects
|
||||
cEntityEffect::eType EffectType;
|
||||
int EffectDurationTicks;
|
||||
short EffectIntensity;
|
||||
float Chance;
|
||||
if (Success && GetEatEffect(EffectType, EffectDurationTicks, EffectIntensity, Chance))
|
||||
{
|
||||
cFastRandom r1;
|
||||
if ((r1.NextInt(100, a_Player->GetUniqueID()) - Info.PoisonChance) <= 0)
|
||||
if (r1.NextFloat() < Chance)
|
||||
{
|
||||
a_Player->FoodPoison(600); // Give the player food poisoning for 30 seconds.
|
||||
a_Player->AddEntityEffect(EffectType, EffectDurationTicks, EffectIntensity, Chance);
|
||||
}
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "../Defines.h"
|
||||
#include "../Item.h"
|
||||
#include "../Entities/EntityEffect.h"
|
||||
|
||||
|
||||
|
||||
@ -71,23 +72,24 @@ public:
|
||||
|
||||
struct FoodInfo
|
||||
{
|
||||
double Saturation;
|
||||
int FoodLevel;
|
||||
int PoisonChance; // 0 - 100, in percent. 0 = no chance of poisoning, 100 = sure poisoning
|
||||
double Saturation;
|
||||
|
||||
FoodInfo(int a_FoodLevel, double a_Saturation, int a_PoisonChance = 0) :
|
||||
Saturation(a_Saturation),
|
||||
FoodLevel(a_FoodLevel),
|
||||
PoisonChance(a_PoisonChance)
|
||||
Saturation(a_Saturation)
|
||||
{
|
||||
}
|
||||
} ;
|
||||
|
||||
/** Returns the FoodInfo for this item. (FoodRecovery, Saturation and PoisionChance) */
|
||||
/** Returns the FoodInfo for this item. (FoodRecovery and Saturation) */
|
||||
virtual FoodInfo GetFoodInfo();
|
||||
|
||||
|
||||
/** If this function returns true, it sets the arguments to a effect who will be activated when you eat the item. */
|
||||
virtual bool GetEatEffect(cEntityEffect::eType & a_EffectType, int & a_EffectDurationTicks, short & a_EffectIntensity, float & a_Chance);
|
||||
|
||||
/** Lets the player eat a selected item. Returns true if the player ate the item */
|
||||
virtual bool EatItem(cPlayer *a_Player, cItem *a_Item);
|
||||
virtual bool EatItem(cPlayer * a_Player, cItem * a_Item);
|
||||
|
||||
/** Indicates if this item is a tool */
|
||||
virtual bool IsTool(void);
|
||||
|
Loading…
Reference in New Issue
Block a user