summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ClientHandle.cpp6
-rw-r--r--src/Entities/EntityEffects.h1
-rw-r--r--src/Entities/Pawn.cpp14
-rw-r--r--src/Entities/Pawn.h1
-rw-r--r--src/Items/ItemHandler.cpp6
-rw-r--r--src/Items/ItemHandler.h2
-rw-r--r--src/Items/ItemMilk.h4
-rw-r--r--src/Items/ItemPotion.h137
8 files changed, 165 insertions, 6 deletions
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 7b114b927..ab36bff91 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -850,7 +850,7 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB
case DIG_STATUS_SHOOT_EAT:
{
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem());
- if (ItemHandler->IsFood() || ItemHandler->IsDrinkable())
+ if (ItemHandler->IsFood() || ItemHandler->IsDrinkable(&m_Player->GetEquippedItem()))
{
m_Player->AbortEating();
return;
@@ -1182,9 +1182,9 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
{
HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler);
}
- else if ((ItemHandler->IsFood() || ItemHandler->IsDrinkable()) && !m_Player->IsGameModeCreative())
+ else if ((ItemHandler->IsFood() || ItemHandler->IsDrinkable(&Equipped)) && !m_Player->IsGameModeCreative())
{
- if (m_Player->IsSatiated() && !ItemHandler->IsDrinkable())
+ if (m_Player->IsSatiated() && !ItemHandler->IsDrinkable(&Equipped))
{
// The player is satiated, they cannot eat
return;
diff --git a/src/Entities/EntityEffects.h b/src/Entities/EntityEffects.h
index 2bda2e104..137eb6480 100644
--- a/src/Entities/EntityEffects.h
+++ b/src/Entities/EntityEffects.h
@@ -9,6 +9,7 @@ public:
/** All types of entity effects (numbers correspond to IDs) */
enum eType
{
+ efNoEffect = 0,
efSpeed = 1,
efSlowness = 2,
efHaste = 3,
diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp
index 4c840e6e1..5cf270006 100644
--- a/src/Entities/Pawn.cpp
+++ b/src/Entities/Pawn.cpp
@@ -52,8 +52,22 @@ void cPawn::Tick(float a_Dt, cChunk & a_Chunk)
+void cPawn::KilledBy(cEntity *a_Killer)
+{
+ ClearEntityEffects();
+}
+
+
+
+
+
void cPawn::AddEntityEffect(cEntityEffect::eType a_EffectType, cEntityEffect a_Effect)
{
+ if (a_EffectType == cEntityEffect::efNoEffect)
+ {
+ return;
+ }
+
m_EntityEffects[a_EffectType] = a_Effect;
m_World->BroadcastEntityEffect(*this, a_EffectType, a_Effect.GetIntensity(), a_Effect.m_Ticks);
}
diff --git a/src/Entities/Pawn.h b/src/Entities/Pawn.h
index 857488901..47fb691f4 100644
--- a/src/Entities/Pawn.h
+++ b/src/Entities/Pawn.h
@@ -21,6 +21,7 @@ public:
cPawn(eEntityType a_EntityType, double a_Width, double a_Height);
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void KilledBy(cEntity * a_Killer) override;
/** Applies an entity effect
* @param a_EffectType The entity effect to apply
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index 83be87b9e..f847c8ffa 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -35,6 +35,7 @@
#include "ItemNetherWart.h"
#include "ItemPainting.h"
#include "ItemPickaxe.h"
+#include "ItemPotion.h"
#include "ItemThrowable.h"
#include "ItemRedstoneDust.h"
#include "ItemRedstoneRepeater.h"
@@ -124,6 +125,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_ITEM_ITEM_FRAME: return new cItemItemFrameHandler(a_ItemType);
case E_ITEM_NETHER_WART: return new cItemNetherWartHandler(a_ItemType);
case E_ITEM_PAINTING: return new cItemPaintingHandler(a_ItemType);
+ case E_ITEM_POTIONS: return new cItemPotionHandler();
case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType);
case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType);
case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType);
@@ -502,8 +504,10 @@ bool cItemHandler::IsFood(void)
-bool cItemHandler::IsDrinkable(void)
+bool cItemHandler::IsDrinkable(const cItem * a_Item)
{
+ UNUSED(a_Item);
+
switch (m_ItemType)
{
case E_ITEM_MILK:
diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h
index 3a25a3f9d..ead2c9769 100644
--- a/src/Items/ItemHandler.h
+++ b/src/Items/ItemHandler.h
@@ -83,7 +83,7 @@ public:
virtual bool IsFood(void);
/** Indicates if this item is drinkable */
- virtual bool IsDrinkable(void);
+ virtual bool IsDrinkable(const cItem * a_Item);
/** Blocks simply get placed */
virtual bool IsPlaceable(void);
diff --git a/src/Items/ItemMilk.h b/src/Items/ItemMilk.h
index 8569c8cbe..62506a223 100644
--- a/src/Items/ItemMilk.h
+++ b/src/Items/ItemMilk.h
@@ -11,13 +11,15 @@ public:
{
}
- virtual bool IsDrinkable(void) override
+ virtual bool IsDrinkable(const cItem * a_Item) override
{
+ UNUSED(a_Item);
return true;
}
virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) override
{
+ UNUSED(a_Item);
a_Player->ClearEntityEffects();
a_Player->GetInventory().RemoveOneEquippedItem();
a_Player->GetInventory().AddItem(E_ITEM_BUCKET);
diff --git a/src/Items/ItemPotion.h b/src/Items/ItemPotion.h
new file mode 100644
index 000000000..e34b251aa
--- /dev/null
+++ b/src/Items/ItemPotion.h
@@ -0,0 +1,137 @@
+
+#pragma once
+
+#include "../Entities/EntityEffects.h"
+
+class cItemPotionHandler:
+public cItemHandler
+{
+ typedef cItemHandler super;
+
+ cEntityEffect::eType GetEntityEffectType(short a_ItemDamage)
+ {
+ // Potion effect bits are different from entity effect values
+ // For reference: http://minecraft.gamepedia.com/Data_values#.22Potion_effect.22_bits
+ switch (a_ItemDamage & 15)
+ {
+ case 1: return cEntityEffect::efRegeneration;
+ case 2: return cEntityEffect::efSpeed;
+ case 3: return cEntityEffect::efFireResistance;
+ case 4: return cEntityEffect::efPoison;
+ case 5: return cEntityEffect::efInstantHealth;
+ case 6: return cEntityEffect::efNightVision;
+ case 8: return cEntityEffect::efWeakness;
+ case 9: return cEntityEffect::efStrength;
+ case 10: return cEntityEffect::efSlowness;
+ case 12: return cEntityEffect::efInstantDamage;
+ case 13: return cEntityEffect::efWaterBreathing;
+ case 14: return cEntityEffect::efInvisibility;
+
+ // No effect potions
+ case 0:
+ case 7:
+ case 11:
+ case 15:
+ {
+ break;
+ }
+ }
+
+ return cEntityEffect::efNoEffect;
+ }
+
+ short GetEntityEffectIntensity(short a_ItemDamage)
+ {
+ // Level II potion if fifth bit is set
+ if (a_ItemDamage & 32) return 1;
+ else return 0;
+ }
+
+ int GetEntityEffectDuration(short a_ItemDamage)
+ {
+ // Base duration in ticks
+ int base = 0;
+ double tier_multi = 1, ext_multi = 1, splash_multi = 1;
+
+ switch (GetEntityEffectType(a_ItemDamage))
+ {
+ case cEntityEffect::efRegeneration:
+ case cEntityEffect::efPoison:
+ {
+ base = 900;
+ break;
+ }
+
+ case cEntityEffect::efSpeed:
+ case cEntityEffect::efFireResistance:
+ case cEntityEffect::efNightVision:
+ case cEntityEffect::efStrength:
+ case cEntityEffect::efWaterBreathing:
+ case cEntityEffect::efInvisibility:
+ {
+ base = 3600;
+ break;
+ }
+
+ case cEntityEffect::efWeakness:
+ case cEntityEffect::efSlowness:
+ {
+ base = 1800;
+ break;
+ }
+ }
+
+ // If potion is level 2, half the duration. If not, stays the same
+ tier_multi = GetEntityEffectIntensity(a_ItemDamage) > 0 ? 0.5 : 1;
+
+ // If potion is extended, multiply duration by 8/3. If not, stays the same
+ // Extended potion if sixth bit is set
+ ext_multi = a_ItemDamage & 64 ? (8.0/3.0) : 1;
+
+ // If potion is splash potion, multiply duration by 3/4. If not, stays the same
+ splash_multi = !IsDrinkable(a_ItemDamage) ? 0.75 : 1;
+
+ // For reference: http://minecraft.gamepedia.com/Data_values#.22Tier.22_bit
+ // http://minecraft.gamepedia.com/Data_values#.22Extended_duration.22_bit
+ // http://minecraft.gamepedia.com/Data_values#.22Splash_potion.22_bit
+
+ return base * tier_multi * ext_multi * splash_multi;
+ }
+
+ bool IsDrinkable(short a_ItemDamage)
+ {
+ // Drinkable potion if 13th bit is set
+ // For reference: http://minecraft.gamepedia.com/Potions#Data_value_table
+ return a_ItemDamage & 8192;
+ }
+
+public:
+ cItemPotionHandler():
+ super(E_ITEM_POTIONS)
+ {
+ }
+
+ virtual bool IsDrinkable(const cItem * a_Item) override
+ {
+ return IsDrinkable(a_Item->m_ItemDamage);
+ }
+
+ virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
+ {
+ // Called when potion is a splash potion
+ return true;
+ }
+
+ virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) override
+ {
+ // Called when potion is a drinkable potion
+ short potion_damage = a_Item->m_ItemDamage;
+ a_Player->AddEntityEffect(GetEntityEffectType(potion_damage),
+ cEntityEffect(GetEntityEffectDuration(potion_damage),
+ GetEntityEffectIntensity(potion_damage),
+ a_Player));
+ a_Player->GetInventory().RemoveOneEquippedItem();
+ a_Player->GetInventory().AddItem(E_ITEM_GLASS_BOTTLE);
+ return true;
+ }
+};