summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Blocks/BlockAnvil.h7
-rw-r--r--src/Enchantments.cpp9
-rw-r--r--src/Enchantments.h3
-rw-r--r--src/Items/ItemArmor.h43
-rw-r--r--src/Items/ItemHandler.cpp19
-rw-r--r--src/Items/ItemHandler.h6
-rw-r--r--src/Items/ItemPickaxe.h13
-rw-r--r--src/Items/ItemShovel.h14
-rw-r--r--src/Items/ItemSword.h13
-rw-r--r--src/UI/SlotArea.cpp173
-rw-r--r--src/UI/SlotArea.h29
-rw-r--r--src/UI/Window.cpp15
-rw-r--r--src/UI/Window.h12
13 files changed, 356 insertions, 0 deletions
diff --git a/src/Blocks/BlockAnvil.h b/src/Blocks/BlockAnvil.h
index 93a796ef7..c9eec961d 100644
--- a/src/Blocks/BlockAnvil.h
+++ b/src/Blocks/BlockAnvil.h
@@ -23,6 +23,13 @@ public:
{
a_Pickups.push_back(cItem(E_BLOCK_ANVIL, 1, a_BlockMeta >> 2));
}
+
+
+ virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
+ {
+ cWindow * Window = new cAnvilWindow();
+ a_Player->OpenWindow(Window);
+ }
virtual bool GetPlacementBlockTypeMeta(
diff --git a/src/Enchantments.cpp b/src/Enchantments.cpp
index 64f89815b..bfcde9dac 100644
--- a/src/Enchantments.cpp
+++ b/src/Enchantments.cpp
@@ -83,6 +83,15 @@ void cEnchantments::AddFromString(const AString & a_StringSpec)
+int cEnchantments::Size(void)
+{
+ return (int)m_Enchantments.size();
+}
+
+
+
+
+
AString cEnchantments::ToString(void) const
{
// Serialize all the enchantments into a string
diff --git a/src/Enchantments.h b/src/Enchantments.h
index ec42257c8..82eea53f9 100644
--- a/src/Enchantments.h
+++ b/src/Enchantments.h
@@ -84,6 +84,9 @@ public:
/** Adds enchantments in the stringspec; if a specified enchantment already exists, overwrites it */
void AddFromString(const AString & a_StringSpec);
+ /** Get the count of enchantments */
+ int Size(void);
+
/** Serializes all the enchantments into a string */
AString ToString(void) const;
diff --git a/src/Items/ItemArmor.h b/src/Items/ItemArmor.h
index 08cddb1ad..f53100bb1 100644
--- a/src/Items/ItemArmor.h
+++ b/src/Items/ItemArmor.h
@@ -60,6 +60,49 @@ public:
return true;
}
+ virtual bool CanRepairWithItem(const cItem & a_Item) override
+ {
+ switch (m_ItemType)
+ {
+ case E_ITEM_CHAIN_BOOTS:
+ case E_ITEM_CHAIN_CHESTPLATE:
+ case E_ITEM_CHAIN_HELMET:
+ case E_ITEM_CHAIN_LEGGINGS:
+ {
+ return (a_Item.m_ItemType == E_ITEM_IRON);
+ }
+ case E_ITEM_DIAMOND_BOOTS:
+ case E_ITEM_DIAMOND_CHESTPLATE:
+ case E_ITEM_DIAMOND_HELMET:
+ case E_ITEM_DIAMOND_LEGGINGS:
+ {
+ return (a_Item.m_ItemType == E_ITEM_DIAMOND);
+ }
+ case E_ITEM_IRON_BOOTS:
+ case E_ITEM_IRON_CHESTPLATE:
+ case E_ITEM_IRON_HELMET:
+ case E_ITEM_IRON_LEGGINGS:
+ {
+ return (a_Item.m_ItemType == E_ITEM_IRON);
+ }
+ case E_ITEM_GOLD_BOOTS:
+ case E_ITEM_GOLD_CHESTPLATE:
+ case E_ITEM_GOLD_HELMET:
+ case E_ITEM_GOLD_LEGGINGS:
+ {
+ return (a_Item.m_ItemType == E_ITEM_GOLD);
+ }
+ case E_ITEM_LEATHER_BOOTS:
+ case E_ITEM_LEATHER_CAP:
+ case E_ITEM_LEATHER_PANTS:
+ case E_ITEM_LEATHER_TUNIC:
+ {
+ return (a_Item.m_ItemType == E_ITEM_LEATHER);
+ }
+ }
+ return false;
+ }
+
} ;
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index ce9593a70..105def2ce 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -511,6 +511,25 @@ bool cItemHandler::IsPlaceable(void)
+
+bool cItemHandler::CanRepairWithItem(const cItem & a_Item)
+{
+ return false;
+}
+
+
+
+
+
+int cItemHandler::GetRepairCost(void)
+{
+ return 0;
+}
+
+
+
+
+
bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
{
UNUSED(a_BlockType);
diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h
index 4993eac85..420eefcf1 100644
--- a/src/Items/ItemHandler.h
+++ b/src/Items/ItemHandler.h
@@ -85,6 +85,12 @@ public:
/** Blocks simply get placed */
virtual bool IsPlaceable(void);
+ /** Can the anvil repair this item, when a_Item is the second input? */
+ virtual bool CanRepairWithItem(const cItem & a_Item);
+
+ /** Get the repair cost from the item, or 0 if the item hasn't repair cost. */
+ virtual int GetRepairCost(void);
+
/** Called before a block is placed into a world.
The handler should return true to allow placement, false to refuse.
Also, the handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block.
diff --git a/src/Items/ItemPickaxe.h b/src/Items/ItemPickaxe.h
index 2a8e40daa..46e68ec70 100644
--- a/src/Items/ItemPickaxe.h
+++ b/src/Items/ItemPickaxe.h
@@ -85,6 +85,19 @@ public:
}
return false;
}
+
+ virtual bool CanRepairWithItem(const cItem & a_Item) override
+ {
+ switch (m_ItemType)
+ {
+ case E_ITEM_WOODEN_PICKAXE: return (a_Item.m_ItemType == E_BLOCK_PLANKS);
+ case E_ITEM_STONE_PICKAXE: return (a_Item.m_ItemType == E_BLOCK_COBBLESTONE);
+ case E_ITEM_IRON_PICKAXE: return (a_Item.m_ItemType == E_ITEM_IRON);
+ case E_ITEM_GOLD_PICKAXE: return (a_Item.m_ItemType == E_ITEM_GOLD);
+ case E_ITEM_DIAMOND_PICKAXE: return (a_Item.m_ItemType == E_ITEM_DIAMOND);
+ }
+ return false;
+ }
} ;
diff --git a/src/Items/ItemShovel.h b/src/Items/ItemShovel.h
index 873d5ae25..7659ccc54 100644
--- a/src/Items/ItemShovel.h
+++ b/src/Items/ItemShovel.h
@@ -41,4 +41,18 @@ public:
{
return (a_BlockType == E_BLOCK_SNOW);
}
+
+ virtual bool CanRepairWithItem(const cItem & a_Item) override
+ {
+ switch (m_ItemType)
+ {
+ case E_ITEM_WOODEN_SHOVEL: return (a_Item.m_ItemType == E_BLOCK_PLANKS);
+ case E_ITEM_STONE_SHOVEL: return (a_Item.m_ItemType == E_BLOCK_COBBLESTONE);
+ case E_ITEM_IRON_SHOVEL: return (a_Item.m_ItemType == E_ITEM_IRON);
+ case E_ITEM_GOLD_SHOVEL: return (a_Item.m_ItemType == E_ITEM_GOLD);
+ case E_ITEM_DIAMOND_SHOVEL: return (a_Item.m_ItemType == E_ITEM_DIAMOND);
+ }
+ return false;
+ }
+
};
diff --git a/src/Items/ItemSword.h b/src/Items/ItemSword.h
index a7c1d2432..34656ff99 100644
--- a/src/Items/ItemSword.h
+++ b/src/Items/ItemSword.h
@@ -23,6 +23,19 @@ public:
{
return (a_BlockType == E_BLOCK_COBWEB);
}
+
+ virtual bool CanRepairWithItem(const cItem & a_Item) override
+ {
+ switch (m_ItemType)
+ {
+ case E_ITEM_WOODEN_SWORD: return (a_Item.m_ItemType == E_BLOCK_PLANKS);
+ case E_ITEM_STONE_SWORD: return (a_Item.m_ItemType == E_BLOCK_COBBLESTONE);
+ case E_ITEM_IRON_SWORD: return (a_Item.m_ItemType == E_ITEM_IRON);
+ case E_ITEM_GOLD_SWORD: return (a_Item.m_ItemType == E_ITEM_GOLD);
+ case E_ITEM_DIAMOND_SWORD: return (a_Item.m_ItemType == E_ITEM_DIAMOND);
+ }
+ return false;
+ }
} ;
diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp
index 87b4032e0..eac8257ec 100644
--- a/src/UI/SlotArea.cpp
+++ b/src/UI/SlotArea.cpp
@@ -596,6 +596,179 @@ cCraftingRecipe & cSlotAreaCrafting::GetRecipeForPlayer(cPlayer & a_Player)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cSlotAreaAnvil:
+
+cSlotAreaAnvil::cSlotAreaAnvil(cAnvilWindow & a_ParentWindow) :
+ cSlotAreaTemporary(3, a_ParentWindow),
+ m_MaximumCost(0),
+ m_RepairedItemName("")
+{
+}
+
+
+
+
+
+void cSlotAreaAnvil::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
+{
+ super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem);
+ UpdateResult(a_Player);
+}
+
+
+
+
+
+void cSlotAreaAnvil::OnPlayerRemoved(cPlayer & a_Player)
+{
+ TossItems(a_Player, 0, 3);
+ super::OnPlayerRemoved(a_Player);
+}
+
+
+
+
+
+void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
+{
+ cItem Input(*GetSlot(0, a_Player));
+ cItem SecondInput(*GetSlot(1, a_Player));
+ cItem Output(*GetSlot(2, a_Player));
+
+ if (Input.IsEmpty() && !Output.IsEmpty())
+ {
+ Output.Empty();
+ SetSlot(2, a_Player, Output);
+ m_ParentWindow.SetProperty(0, 0, a_Player);
+ return;
+ }
+
+ int RepairCost = cItemHandler::GetItemHandler(Input)->GetRepairCost();
+ int NeedExp = 0;
+ if (!SecondInput.IsEmpty())
+ {
+ RepairCost += cItemHandler::GetItemHandler(SecondInput)->GetRepairCost();
+
+ if (Input.IsDamageable() && cItemHandler::GetItemHandler(Input)->CanRepairWithItem(SecondInput))
+ {
+ // Tool and armor repair with special item (iron / gold / diamond / ...)
+ int DamageDiff = std::min((int)Input.m_ItemDamage, (int)Input.GetMaxDamage() / 4);
+ if (DamageDiff < 0)
+ {
+ // No enchantment
+ Output.Empty();
+ SetSlot(2, a_Player, Output);
+ m_ParentWindow.SetProperty(0, 0, a_Player);
+ return;
+ }
+
+ int x = 0;
+ while ((DamageDiff > 0) && (x < SecondInput.m_ItemCount))
+ {
+ Input.m_ItemDamage -= DamageDiff;
+ NeedExp += std::max(1, DamageDiff / 100) + Input.m_Enchantments.Size();
+ DamageDiff = std::min((int)Input.m_ItemDamage, (int)Input.GetMaxDamage() / 4);
+
+ ++x;
+ }
+ }
+ else
+ {
+ // Tool and armor repair with two tools / armors
+ if (!Input.IsSameType(SecondInput) || !Input.IsDamageable())
+ {
+ // No enchantment
+ Output.Empty();
+ SetSlot(2, a_Player, Output);
+ m_ParentWindow.SetProperty(0, 0, a_Player);
+ return;
+ }
+
+ int FirstDamageDiff = Input.GetMaxDamage() - Input.m_ItemDamage;
+ int SecondDamageDiff = SecondInput.GetMaxDamage() - SecondInput.m_ItemDamage;
+ int Damage = SecondDamageDiff + Input.GetMaxDamage() * 12 / 100;
+
+ int NewItemDamage = Input.GetMaxDamage() - (FirstDamageDiff + Damage);
+ if (NewItemDamage > 0)
+ {
+ NewItemDamage = 0;
+ }
+
+ if (NewItemDamage < Input.m_ItemDamage)
+ {
+ Input.m_ItemDamage = NewItemDamage;
+ NeedExp += std::max(1, Damage / 100);
+ }
+
+ // TODO: Add enchantments.
+ }
+ }
+
+ int NameChangeExp = 0;
+ if (m_RepairedItemName.empty())
+ {
+ // Remove custom name
+ if (!Input.m_CustomName.empty())
+ {
+ NameChangeExp = (Input.IsDamageable()) ? 4 : (Input.m_ItemCount * 5);
+ NeedExp += NameChangeExp;
+ Input.m_CustomName = "";
+ }
+ }
+ else if (m_RepairedItemName != Input.m_CustomName)
+ {
+ // Change custom name
+ NameChangeExp = (Input.IsDamageable()) ? 4 : (Input.m_ItemCount * 5);
+ NeedExp += NameChangeExp;
+
+ if (!Input.m_CustomName.empty())
+ {
+ RepairCost += NameChangeExp / 2;
+ }
+
+ Input.m_CustomName = m_RepairedItemName;
+ }
+
+ // TODO: Add enchantment exp cost.
+
+ int MaximumCost = RepairCost + NeedExp;
+
+ if (NeedExp < 0)
+ {
+ Input.Empty();
+ }
+
+ if (NameChangeExp == NeedExp && NameChangeExp > 0 && MaximumCost >= 40)
+ {
+ MaximumCost = 39;
+ }
+ if (MaximumCost >= 40 && !a_Player.IsGameModeCreative())
+ {
+ Input.Empty();
+ }
+
+ /* TODO: Add repair cost to cItem and not ItemHandler. This is required for this function!
+ if (!Input.IsEmpty())
+ {
+ RepairCost = max(cItemHandler::GetItemHandler(Input)->GetRepairCost(), cItemHandler::GetItemHandler(SecondInput)->GetRepairCost());
+ if (!Input.m_CustomName.empty())
+ {
+ RepairCost -= 9;
+ }
+ RepairCost = max(RepairCost, 0);
+ RepairCost += 2;
+ }*/
+
+ SetSlot(2, a_Player, Input);
+ m_ParentWindow.SetProperty(0, MaximumCost, a_Player);
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnchanting:
cSlotAreaEnchanting::cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow) :
diff --git a/src/UI/SlotArea.h b/src/UI/SlotArea.h
index 254722822..a316480c6 100644
--- a/src/UI/SlotArea.h
+++ b/src/UI/SlotArea.h
@@ -9,6 +9,7 @@
#pragma once
#include "../Inventory.h"
+#include "Window.h"
@@ -259,6 +260,34 @@ protected:
+class cSlotAreaAnvil :
+ public cSlotAreaTemporary
+{
+ typedef cSlotAreaTemporary super;
+
+public:
+ cSlotAreaAnvil(cAnvilWindow & a_ParentWindow);
+
+ // cSlotArea overrides:
+ virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
+
+ // cSlotAreaTemporary overrides:
+ virtual void OnPlayerRemoved(cPlayer & a_Player) override;
+
+protected:
+ /** Handles a click in the item slot. */
+ void UpdateResult(cPlayer & a_Player);
+
+ /** The maximum cost of repairing/renaming in the anvil. */
+ int m_MaximumCost;
+
+ AString m_RepairedItemName;
+} ;
+
+
+
+
+
class cSlotAreaEnchanting :
public cSlotAreaTemporary
{
diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp
index 0a78578fc..eb105f8ab 100644
--- a/src/UI/Window.cpp
+++ b/src/UI/Window.cpp
@@ -805,6 +805,21 @@ cCraftingWindow::cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cAnvilWindow:
+
+cAnvilWindow::cAnvilWindow() :
+ cWindow(wtAnvil, "Repair")
+{
+ m_SlotAreas.push_back(new cSlotAreaAnvil(*this));
+ m_SlotAreas.push_back(new cSlotAreaInventory(*this));
+ m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cEnchantingWindow:
cEnchantingWindow::cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
diff --git a/src/UI/Window.h b/src/UI/Window.h
index 1ca67bfd8..c08b36f9b 100644
--- a/src/UI/Window.h
+++ b/src/UI/Window.h
@@ -231,6 +231,18 @@ public:
+class cAnvilWindow :
+ public cWindow
+{
+ typedef cWindow super;
+public:
+ cAnvilWindow();
+} ;
+
+
+
+
+
class cEnchantingWindow :
public cWindow
{