diff options
Diffstat (limited to 'src/Items')
-rw-r--r-- | src/Items/ItemBucket.h | 4 | ||||
-rw-r--r-- | src/Items/ItemHandler.cpp | 44 | ||||
-rw-r--r-- | src/Items/ItemHandler.h | 5 | ||||
-rw-r--r-- | src/Items/ItemMilk.h | 28 | ||||
-rw-r--r-- | src/Items/ItemPotion.h | 199 | ||||
-rw-r--r-- | src/Items/ItemThrowable.h | 4 |
6 files changed, 251 insertions, 33 deletions
diff --git a/src/Items/ItemBucket.h b/src/Items/ItemBucket.h index 5529b4e36..a733bda19 100644 --- a/src/Items/ItemBucket.h +++ b/src/Items/ItemBucket.h @@ -203,7 +203,7 @@ public: if (a_BlockType != E_BLOCK_AIR) { m_ReplacedBlock = a_BlockType; - if (!cFluidSimulator::CanWashAway(a_BlockType)) + if (!cFluidSimulator::CanWashAway(a_BlockType) && !IsBlockLiquid(a_BlockType)) { AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, (eBlockFace)a_EntryFace); // Was an unwashawayable block, can't overwrite it! } @@ -215,7 +215,7 @@ public: } Callbacks; cLineBlockTracer Tracer(*a_World, Callbacks); - Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector()); + Vector3d Start(a_Player->GetEyePosition()); Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5); // cTracer::Trace returns true when whole line was traversed. By returning true when we hit something, we ensure that this never happens if liquid could be placed diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index 423039cf4..85406c826 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -19,6 +19,7 @@ #include "ItemCloth.h" #include "ItemComparator.h" #include "ItemDoor.h" +#include "ItemMilk.h" #include "ItemDye.h" #include "ItemEmptyMap.h" #include "ItemFishingRod.h" @@ -34,6 +35,7 @@ #include "ItemNetherWart.h" #include "ItemPainting.h" #include "ItemPickaxe.h" +#include "ItemPotion.h" #include "ItemThrowable.h" #include "ItemRedstoneDust.h" #include "ItemRedstoneRepeater.h" @@ -120,9 +122,11 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) case E_ITEM_FLOWER_POT: return new cItemFlowerPotHandler(a_ItemType); case E_BLOCK_LILY_PAD: return new cItemLilypadHandler(a_ItemType); case E_ITEM_MAP: return new cItemMapHandler(); + case E_ITEM_MILK: return new cItemMilkHandler(); 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); @@ -470,33 +474,17 @@ bool cItemHandler::IsTool() bool cItemHandler::IsFood(void) { - switch (m_ItemType) - { - case E_ITEM_RED_APPLE: - case E_ITEM_GOLDEN_APPLE: - case E_ITEM_MUSHROOM_SOUP: - case E_ITEM_BREAD: - case E_ITEM_RAW_PORKCHOP: - case E_ITEM_COOKED_PORKCHOP: - case E_ITEM_MILK: - case E_ITEM_RAW_FISH: - case E_ITEM_COOKED_FISH: - case E_ITEM_COOKIE: - case E_ITEM_MELON_SLICE: - 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_SPIDER_EYE: - case E_ITEM_CARROT: - case E_ITEM_POTATO: - case E_ITEM_BAKED_POTATO: - case E_ITEM_POISONOUS_POTATO: - { - return true; - } - } // switch (m_ItemType) + return false; +} + + + + + +bool cItemHandler::IsDrinkable(short a_ItemDamage) +{ + UNUSED(a_ItemDamage); + return false; } @@ -580,7 +568,7 @@ bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item) cFastRandom r1; if ((r1.NextInt(100, a_Player->GetUniqueID()) - Info.PoisonChance) <= 0) { - a_Player->FoodPoison(300); + a_Player->FoodPoison(600); // Give the player food poisoning for 30 seconds. } } diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h index e13198cd7..cffca11ab 100644 --- a/src/Items/ItemHandler.h +++ b/src/Items/ItemHandler.h @@ -82,6 +82,9 @@ public: /** Indicates if this item is food */ virtual bool IsFood(void); + /** Indicates if this item is drinkable */ + virtual bool IsDrinkable(short a_ItemDamage); + /** Blocks simply get placed */ virtual bool IsPlaceable(void); @@ -99,7 +102,7 @@ public: BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ); - /** Returns whether this tool/item can harvest a specific block (e.g. wooden pickaxe can harvest stone, but wood can�t) DEFAULT: False */ + /** Returns whether this tool/item can harvest a specific block (e.g. wooden pickaxe can harvest stone, but wood can't) DEFAULT: False */ virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType); static cItemHandler * GetItemHandler(int a_ItemType); diff --git a/src/Items/ItemMilk.h b/src/Items/ItemMilk.h new file mode 100644 index 000000000..db7bc13be --- /dev/null +++ b/src/Items/ItemMilk.h @@ -0,0 +1,28 @@ + +#pragma once + +class cItemMilkHandler: + public cItemHandler +{ + typedef cItemHandler super; +public: + cItemMilkHandler(): + super(E_ITEM_MILK) + { + } + + virtual bool IsDrinkable(short a_ItemDamage) override + { + UNUSED(a_ItemDamage); + 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); + return true; + } +}; diff --git a/src/Items/ItemPotion.h b/src/Items/ItemPotion.h new file mode 100644 index 000000000..f3afbf99b --- /dev/null +++ b/src/Items/ItemPotion.h @@ -0,0 +1,199 @@ + +#pragma once + +#include "../Entities/EntityEffect.h" +#include "../Entities/SplashPotionEntity.h" + +class cItemPotionHandler: + public cItemHandler +{ + typedef cItemHandler super; + +public: + + cItemPotionHandler(): + super(E_ITEM_POTION) + { + } + + + /** Returns the potion particle type (used by the client for visuals), based on the potion's damage value */ + static int GetPotionParticleType(short a_ItemDamage) + { + // Lowest six bits + return (a_ItemDamage & 0x3f); + } + + + /** Translates the potion's damage value into the entity effect that the potion gives */ + static cEntityEffect::eType GetEntityEffectType(short a_ItemDamage) + { + // Lowest four bits + // Potion effect bits are different from entity effect values + // For reference: http://minecraft.gamepedia.com/Data_values#.22Potion_effect.22_bits + switch (a_ItemDamage & 0x0f) + { + case 0x01: return cEntityEffect::effRegeneration; + case 0x02: return cEntityEffect::effSpeed; + case 0x03: return cEntityEffect::effFireResistance; + case 0x04: return cEntityEffect::effPoison; + case 0x05: return cEntityEffect::effInstantHealth; + case 0x06: return cEntityEffect::effNightVision; + case 0x08: return cEntityEffect::effWeakness; + case 0x09: return cEntityEffect::effStrength; + case 0x0a: return cEntityEffect::effSlowness; + case 0x0c: return cEntityEffect::effInstantDamage; + case 0x0d: return cEntityEffect::effWaterBreathing; + case 0x0e: return cEntityEffect::effInvisibility; + + // No effect potions + case 0x00: + case 0x07: + case 0x0b: // Will be potion of leaping in 1.8 + case 0x0f: + { + break; + } + } + return cEntityEffect::effNoEffect; + } + + + /** Retrieves the intensity level from the potion's damage value. + Returns 0 for level I potions, 1 for level II potions. */ + static short GetEntityEffectIntensity(short a_ItemDamage) + { + // Level II potion if the fifth lowest bit is set + return ((a_ItemDamage & 0x20) != 0) ? 1 : 0; + } + + + /** Returns the effect duration, in ticks, based on the potion's damage value */ + static int GetEntityEffectDuration(short a_ItemDamage) + { + // Base duration in ticks + int base = 0; + double TierCoeff = 1, ExtCoeff = 1, SplashCoeff = 1; + + switch (GetEntityEffectType(a_ItemDamage)) + { + case cEntityEffect::effRegeneration: + case cEntityEffect::effPoison: + { + base = 900; + break; + } + + case cEntityEffect::effSpeed: + case cEntityEffect::effFireResistance: + case cEntityEffect::effNightVision: + case cEntityEffect::effStrength: + case cEntityEffect::effWaterBreathing: + case cEntityEffect::effInvisibility: + { + base = 3600; + break; + } + + case cEntityEffect::effWeakness: + case cEntityEffect::effSlowness: + { + base = 1800; + break; + } + } + + // If potion is level II, half the duration. If not, stays the same + TierCoeff = (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 lowest bit is set + ExtCoeff = (a_ItemDamage & 0x40) ? (8.0 / 3.0) : 1; + + // If potion is splash potion, multiply duration by 3/4. If not, stays the same + SplashCoeff = IsPotionDrinkable(a_ItemDamage) ? 1 : 0.75; + + // Ref.: + // 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 (int)(base * TierCoeff * ExtCoeff * SplashCoeff); + } + + + /** Returns true if the potion with the given damage is drinkable */ + static bool IsPotionDrinkable(short a_ItemDamage) + { + // Drinkable potion if 13th lowest bit is set + // Ref.: http://minecraft.gamepedia.com/Potions#Data_value_table + return ((a_ItemDamage & 0x2000) != 0); + } + + + // cItemHandler overrides: + virtual bool IsDrinkable(short a_ItemDamage) override + { + // Drinkable potion if 13th lowest bit is set + // Ref.: http://minecraft.gamepedia.com/Potions#Data_value_table + return IsPotionDrinkable(a_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 + { + short PotionDamage = a_Item.m_ItemDamage; + + // Do not throw non-splash potions: + if (IsPotionDrinkable(PotionDamage)) + { + return false; + } + + Vector3d Pos = a_Player->GetThrowStartPos(); + Vector3d Speed = a_Player->GetLookVector() * 7; + + cSplashPotionEntity * Projectile = new cSplashPotionEntity( + a_Player, Pos.x, Pos.y, Pos.z, Speed, + GetEntityEffectType(PotionDamage), cEntityEffect(GetEntityEffectDuration(PotionDamage), + GetEntityEffectIntensity(PotionDamage)), GetPotionParticleType(PotionDamage) + ); + if (Projectile == NULL) + { + return false; + } + if (!Projectile->Initialize(*a_World)) + { + delete Projectile; + return false; + } + + if (!a_Player->IsGameModeCreative()) + { + a_Player->GetInventory().RemoveOneEquippedItem(); + } + + return true; + } + + + virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) override + { + short PotionDamage = a_Item->m_ItemDamage; + + // Do not drink undrinkable potions: + if (!IsDrinkable(a_Item->m_ItemDamage)) + { + return false; + } + + a_Player->AddEntityEffect(GetEntityEffectType(PotionDamage), GetEntityEffectDuration(PotionDamage), GetEntityEffectIntensity(PotionDamage)); + a_Player->GetInventory().RemoveOneEquippedItem(); + a_Player->GetInventory().AddItem(E_ITEM_GLASS_BOTTLE); + return true; + } +}; + + + + diff --git a/src/Items/ItemThrowable.h b/src/Items/ItemThrowable.h index fde7b8e67..c151c5d3a 100644 --- a/src/Items/ItemThrowable.h +++ b/src/Items/ItemThrowable.h @@ -35,7 +35,7 @@ public: cFastRandom Random; a_World->BroadcastSoundEffect("random.bow", a_Player->GetPosX(), a_Player->GetPosY() - a_Player->GetHeight(), a_Player->GetPosZ(), 0.5f, 0.4f / (Random.NextFloat(1.0f) * 0.4f + 0.8f)); - if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed) < 0) + if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem(), &Speed) < 0) { return false; } @@ -135,7 +135,7 @@ public: return false; } - if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem()) < 0) + if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem()) < 0) { return false; } |