summaryrefslogtreecommitdiffstats
path: root/src/Items
diff options
context:
space:
mode:
Diffstat (limited to 'src/Items')
-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
4 files changed, 146 insertions, 3 deletions
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;
+ }
+};