diff options
Diffstat (limited to 'src/Items')
-rw-r--r-- | src/Items/CMakeLists.txt | 7 | ||||
-rw-r--r-- | src/Items/ItemArmor.h | 110 | ||||
-rw-r--r-- | src/Items/ItemBoat.h | 2 | ||||
-rw-r--r-- | src/Items/ItemBow.h | 4 | ||||
-rw-r--r-- | src/Items/ItemFishingRod.h | 8 | ||||
-rw-r--r-- | src/Items/ItemHandler.cpp | 37 | ||||
-rw-r--r-- | src/Items/ItemHandler.h | 37 | ||||
-rw-r--r-- | src/Items/ItemItemFrame.h | 2 | ||||
-rw-r--r-- | src/Items/ItemLilypad.h | 14 | ||||
-rw-r--r-- | src/Items/ItemMinecart.h | 4 | ||||
-rw-r--r-- | src/Items/ItemPainting.h | 2 | ||||
-rw-r--r-- | src/Items/ItemPickaxe.h | 14 | ||||
-rw-r--r-- | src/Items/ItemShovel.h | 14 | ||||
-rw-r--r-- | src/Items/ItemSpawnEgg.h | 40 | ||||
-rw-r--r-- | src/Items/ItemSword.h | 13 | ||||
-rw-r--r-- | src/Items/ItemThrowable.h | 17 |
16 files changed, 284 insertions, 41 deletions
diff --git a/src/Items/CMakeLists.txt b/src/Items/CMakeLists.txt index 44a9f594f..a6fe6ea70 100644 --- a/src/Items/CMakeLists.txt +++ b/src/Items/CMakeLists.txt @@ -4,4 +4,9 @@ project (MCServer) include_directories ("${PROJECT_SOURCE_DIR}/../") -add_library(Items ItemHandler) +file(GLOB SOURCE + "*.cpp" + "*.h" +) + +add_library(Items ${SOURCE}) diff --git a/src/Items/ItemArmor.h b/src/Items/ItemArmor.h new file mode 100644 index 000000000..2436df5bd --- /dev/null +++ b/src/Items/ItemArmor.h @@ -0,0 +1,110 @@ + +#pragma once + +#include "ItemHandler.h" +#include "../World.h" + + + + + +class cItemArmorHandler : + public cItemHandler +{ +public: + cItemArmorHandler(int a_ItemType) : + cItemHandler(a_ItemType) + { + } + + /** Move the armor to the armor slot of the player's inventory */ + 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 + { + int SlotNum; + if (ItemCategory::IsHelmet(a_Item.m_ItemType)) + { + SlotNum = 0; + } + else if (ItemCategory::IsChestPlate(a_Item.m_ItemType)) + { + SlotNum = 1; + } + else if (ItemCategory::IsLeggings(a_Item.m_ItemType)) + { + SlotNum = 2; + } + else if (ItemCategory::IsBoots(a_Item.m_ItemType)) + { + SlotNum = 3; + } + else + { + LOGWARNING("Used unknown armor: %i", a_Item.m_ItemType); + return false; + } + + if (!a_Player->GetInventory().GetArmorSlot(SlotNum).IsEmpty()) + { + return false; + } + + a_Player->GetInventory().SetArmorSlot(SlotNum, a_Item.CopyOne()); + + cItem Item(a_Item); + Item.m_ItemCount--; + if (Item.m_ItemCount <= 0) + { + Item.Empty(); + } + a_Player->GetInventory().SetHotbarSlot(a_Player->GetInventory().GetEquippedSlotNum(), Item); + return true; + } + + virtual bool CanRepairWithRawMaterial(short a_ItemType) 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_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_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_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_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_ItemType == E_ITEM_LEATHER); + } + } + return false; + } + +} ; + + + + diff --git a/src/Items/ItemBoat.h b/src/Items/ItemBoat.h index 42f4ffc8f..7faac1e32 100644 --- a/src/Items/ItemBoat.h +++ b/src/Items/ItemBoat.h @@ -75,7 +75,7 @@ public: double z = Callbacks.m_Pos.z; cBoat * Boat = new cBoat(x + 0.5, y + 1, z + 0.5); - Boat->Initialize(a_World); + Boat->Initialize(*a_World); return true; } diff --git a/src/Items/ItemBow.h b/src/Items/ItemBow.h index 410c5f512..e0ab339d3 100644 --- a/src/Items/ItemBow.h +++ b/src/Items/ItemBow.h @@ -9,7 +9,7 @@ #pragma once -#include "../Entities/ProjectileEntity.h" +#include "../Entities/ArrowEntity.h" @@ -66,7 +66,7 @@ public: { return; } - if (!Arrow->Initialize(a_Player->GetWorld())) + if (!Arrow->Initialize(*a_Player->GetWorld())) { delete Arrow; return; diff --git a/src/Items/ItemFishingRod.h b/src/Items/ItemFishingRod.h index 0431b88b7..3b1ad1717 100644 --- a/src/Items/ItemFishingRod.h +++ b/src/Items/ItemFishingRod.h @@ -142,6 +142,8 @@ public: break; } } + + a_Player->GetStatManager().AddValue(statTreasureFished, 1); } else if (ItemCategory <= 14) // Junk 10% { @@ -190,6 +192,8 @@ public: { Drops.Add(cItem(E_BLOCK_TRIPWIRE_HOOK)); } + + a_Player->GetStatManager().AddValue(statJunkFished, 1); } else // Fish { @@ -210,6 +214,8 @@ public: { Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_FISH)); } + + a_Player->GetStatManager().AddValue(statFishCaught, 1); } if (cRoot::Get()->GetPluginManager()->CallHookPlayerFishing(*a_Player, Drops)) @@ -225,7 +231,7 @@ public: else { cFloater * Floater = new cFloater(a_Player->GetPosX(), a_Player->GetStance(), a_Player->GetPosZ(), a_Player->GetLookVector() * 15, a_Player->GetUniqueID(), 100 + a_World->GetTickRandomNumber(800) - (a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchLure) * 100)); - Floater->Initialize(a_World); + Floater->Initialize(*a_World); a_Player->SetIsFishing(true, Floater->GetUniqueID()); } return true; diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index 1e77717e3..d97f986ba 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -8,6 +8,7 @@ #include "../BlockInServerPluginInterface.h" // Handlers: +#include "ItemArmor.h" #include "ItemBed.h" #include "ItemBoat.h" #include "ItemBow.h" @@ -222,6 +223,31 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) { return new cItemFoodHandler(a_ItemType); } + + // Armor: + case E_ITEM_LEATHER_CAP: + case E_ITEM_GOLD_HELMET: + case E_ITEM_CHAIN_HELMET: + case E_ITEM_IRON_HELMET: + case E_ITEM_DIAMOND_HELMET: + case E_ITEM_LEATHER_TUNIC: + case E_ITEM_GOLD_CHESTPLATE: + case E_ITEM_CHAIN_CHESTPLATE: + case E_ITEM_IRON_CHESTPLATE: + case E_ITEM_DIAMOND_CHESTPLATE: + case E_ITEM_LEATHER_PANTS: + case E_ITEM_GOLD_LEGGINGS: + case E_ITEM_CHAIN_LEGGINGS: + case E_ITEM_IRON_LEGGINGS: + case E_ITEM_DIAMOND_LEGGINGS: + case E_ITEM_LEATHER_BOOTS: + case E_ITEM_GOLD_BOOTS: + case E_ITEM_CHAIN_BOOTS: + case E_ITEM_IRON_BOOTS: + case E_ITEM_DIAMOND_BOOTS: + { + return new cItemArmorHandler(a_ItemType); + } } } @@ -431,7 +457,6 @@ bool cItemHandler::IsTool() || (m_ItemType >= 267 && m_ItemType <= 279) || (m_ItemType >= 283 && m_ItemType <= 286) || (m_ItemType >= 290 && m_ItemType <= 294) - || (m_ItemType >= 256 && m_ItemType <= 259) || (m_ItemType == 325) || (m_ItemType == 346); } @@ -486,6 +511,16 @@ bool cItemHandler::IsPlaceable(void) + +bool cItemHandler::CanRepairWithRawMaterial(short a_ItemType) +{ + return false; +} + + + + + bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType) { UNUSED(a_BlockType); diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h index 5b6c239cc..e13198cd7 100644 --- a/src/Items/ItemHandler.h +++ b/src/Items/ItemHandler.h @@ -21,13 +21,13 @@ class cItemHandler public: cItemHandler(int a_ItemType); - // Force virtual destructor + /** Force virtual destructor */ virtual ~cItemHandler() {} - /// Called when the player tries to use the item (right mouse button). Return false to make the item unusable. DEFAULT: False + /** Called when the player tries to use the item (right mouse button). Return false to make the item unusable. DEFAULT: False */ 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); - /// Called when the client sends the SHOOT status in the lclk packet + /** Called when the client sends the SHOOT status in the lclk packet */ virtual void OnItemShoot(cPlayer *, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) { UNUSED(a_BlockX); @@ -36,7 +36,7 @@ public: UNUSED(a_BlockFace); } - /// Called every tick while the item is on the player's inventory (Used by maps) - For now, called only for equipped items + /** Called every tick while the item is on the player's inventory (Used by maps) - For now, called only for equipped items */ virtual void OnUpdate(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item) { UNUSED(a_World); @@ -44,48 +44,51 @@ public: UNUSED(a_Item); } - /// Called while the player diggs a block using this item + /** Called while the player diggs a block using this item */ virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace); - /// Called when the player destroys a block using this item. This also calls the drop function for the destroyed block + /** Called when the player destroys a block using this item. This also calls the drop function for the destroyed block */ virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_X, int a_Y, int a_Z); - /// Called after the player has eaten this item. + /** Called after the player has eaten this item. */ virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item); - /// Returns the maximum stack size for a given item + /** Returns the maximum stack size for a given item */ virtual char GetMaxStackSize(void); struct FoodInfo { - int FoodLevel; double Saturation; + int FoodLevel; int PoisonChance; // 0 - 100, in percent. 0 = no chance of poisoning, 100 = sure poisoning FoodInfo(int a_FoodLevel, double a_Saturation, int a_PoisonChance = 0) : - FoodLevel(a_FoodLevel), Saturation(a_Saturation), + FoodLevel(a_FoodLevel), PoisonChance(a_PoisonChance) { } } ; - /// Returns the FoodInfo for this item. (FoodRecovery, Saturation and PoisionChance) + /** Returns the FoodInfo for this item. (FoodRecovery, Saturation and PoisionChance) */ virtual FoodInfo GetFoodInfo(); - /// Lets the player eat a selected item. Returns true if the player ate the item + /** Lets the player eat a selected item. Returns true if the player ate the item */ virtual bool EatItem(cPlayer *a_Player, cItem *a_Item); - /// Indicates if this item is a tool + /** Indicates if this item is a tool */ virtual bool IsTool(void); - /// Indicates if this item is food + /** Indicates if this item is food */ virtual bool IsFood(void); - /// Blocks simply get placed + /** Blocks simply get placed */ virtual bool IsPlaceable(void); - /** Called before a block is placed into a world. + /** Can the anvil repair this item, when a_Item is the second input? */ + virtual bool CanRepairWithRawMaterial(short a_ItemType); + + /** 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. */ @@ -96,7 +99,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/ItemItemFrame.h b/src/Items/ItemItemFrame.h index 27e7dba35..097f04d0b 100644 --- a/src/Items/ItemItemFrame.h +++ b/src/Items/ItemItemFrame.h @@ -34,7 +34,7 @@ public: if (Block == E_BLOCK_AIR) { cItemFrame * ItemFrame = new cItemFrame(a_Dir, a_BlockX, a_BlockY, a_BlockZ); - if (!ItemFrame->Initialize(a_World)) + if (!ItemFrame->Initialize(*a_World)) { delete ItemFrame; return false; diff --git a/src/Items/ItemLilypad.h b/src/Items/ItemLilypad.h index 8fc1d8543..bc650cdbd 100644 --- a/src/Items/ItemLilypad.h +++ b/src/Items/ItemLilypad.h @@ -47,9 +47,9 @@ public: public cBlockTracer::cCallbacks { public: - cCallbacks(cWorld * a_CBWorld) : - m_HasHitFluid(false), - m_World(a_CBWorld) + + cCallbacks(void) : + m_HasHitFluid(false) { } @@ -62,10 +62,9 @@ public: return false; } AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, BLOCK_FACE_YP); // Always place pad at top of water block - BLOCKTYPE Block = m_World->GetBlock(a_CBBlockX, a_CBBlockY, a_CBBlockZ); if ( - !IsBlockWater(Block) && - cBlockInfo::FullyOccupiesVoxel(Block) + !IsBlockWater(a_CBBlockType) && + cBlockInfo::FullyOccupiesVoxel(a_CBBlockType) ) { // Can't place lilypad on air/in another block! @@ -80,11 +79,10 @@ public: Vector3i m_Pos; bool m_HasHitFluid; - cWorld * m_World; }; - cCallbacks Callbacks(a_World); + cCallbacks Callbacks; cLineBlockTracer Tracer(*a_Player->GetWorld(), Callbacks); Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector()); Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5); diff --git a/src/Items/ItemMinecart.h b/src/Items/ItemMinecart.h index 25500aeb9..63038de51 100644 --- a/src/Items/ItemMinecart.h +++ b/src/Items/ItemMinecart.h @@ -70,7 +70,7 @@ public: return false; } } // switch (m_ItemType) - Minecart->Initialize(a_World); + Minecart->Initialize(*a_World); if (!a_Player->IsGameModeCreative()) { @@ -78,7 +78,7 @@ public: } return true; } - + } ; diff --git a/src/Items/ItemPainting.h b/src/Items/ItemPainting.h index b85098221..e4bb76ebe 100644 --- a/src/Items/ItemPainting.h +++ b/src/Items/ItemPainting.h @@ -79,7 +79,7 @@ public: }; cPainting * Painting = new cPainting(gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)].Title, Dir, a_BlockX, a_BlockY, a_BlockZ); - Painting->Initialize(a_World); + Painting->Initialize(*a_World); if (!a_Player->IsGameModeCreative()) { diff --git a/src/Items/ItemPickaxe.h b/src/Items/ItemPickaxe.h index 2a8e40daa..82bec52d4 100644 --- a/src/Items/ItemPickaxe.h +++ b/src/Items/ItemPickaxe.h @@ -76,6 +76,7 @@ public: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_BRICK: case E_BLOCK_COBBLESTONE_STAIRS: + case E_BLOCK_COBBLESTONE_WALL: case E_BLOCK_STONE_BRICK_STAIRS: case E_BLOCK_NETHER_BRICK_STAIRS: case E_BLOCK_CAULDRON: @@ -85,6 +86,19 @@ public: } return false; } + + virtual bool CanRepairWithRawMaterial(short a_ItemType) override + { + switch (m_ItemType) + { + case E_ITEM_WOODEN_PICKAXE: return (a_ItemType == E_BLOCK_PLANKS); + case E_ITEM_STONE_PICKAXE: return (a_ItemType == E_BLOCK_COBBLESTONE); + case E_ITEM_IRON_PICKAXE: return (a_ItemType == E_ITEM_IRON); + case E_ITEM_GOLD_PICKAXE: return (a_ItemType == E_ITEM_GOLD); + case E_ITEM_DIAMOND_PICKAXE: return (a_ItemType == E_ITEM_DIAMOND); + } + return false; + } } ; diff --git a/src/Items/ItemShovel.h b/src/Items/ItemShovel.h index 873d5ae25..333ba46e8 100644 --- a/src/Items/ItemShovel.h +++ b/src/Items/ItemShovel.h @@ -41,4 +41,18 @@ public: { return (a_BlockType == E_BLOCK_SNOW); } + + virtual bool CanRepairWithRawMaterial(short a_ItemType) override + { + switch (m_ItemType) + { + case E_ITEM_WOODEN_SHOVEL: return (a_ItemType == E_BLOCK_PLANKS); + case E_ITEM_STONE_SHOVEL: return (a_ItemType == E_BLOCK_COBBLESTONE); + case E_ITEM_IRON_SHOVEL: return (a_ItemType == E_ITEM_IRON); + case E_ITEM_GOLD_SHOVEL: return (a_ItemType == E_ITEM_GOLD); + case E_ITEM_DIAMOND_SHOVEL: return (a_ItemType == E_ITEM_DIAMOND); + } + return false; + } + }; diff --git a/src/Items/ItemSpawnEgg.h b/src/Items/ItemSpawnEgg.h index 0d6019398..bba97afa1 100644 --- a/src/Items/ItemSpawnEgg.h +++ b/src/Items/ItemSpawnEgg.h @@ -33,7 +33,10 @@ public: a_BlockY--; } - if (a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, (cMonster::eType)(a_Item.m_ItemDamage)) >= 0) + cMonster::eType MonsterType = ItemDamageToMonsterType(a_Item.m_ItemDamage); + if ( + (MonsterType != cMonster::mtInvalidType) && // Valid monster type + (a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, MonsterType) >= 0)) // Spawning succeeded { if (!a_Player->IsGameModeCreative()) { @@ -45,6 +48,41 @@ public: return false; } + + + /** Converts the Spawn egg item damage to the monster type to spawn. + Returns mtInvalidType for invalid damage values. */ + static cMonster::eType ItemDamageToMonsterType(short a_ItemDamage) + { + switch (a_ItemDamage) + { + case E_META_SPAWN_EGG_BAT: return cMonster::mtBat; + case E_META_SPAWN_EGG_BLAZE: return cMonster::mtBlaze; + case E_META_SPAWN_EGG_CAVE_SPIDER: return cMonster::mtCaveSpider; + case E_META_SPAWN_EGG_CHICKEN: return cMonster::mtChicken; + case E_META_SPAWN_EGG_COW: return cMonster::mtCow; + case E_META_SPAWN_EGG_CREEPER: return cMonster::mtCreeper; + case E_META_SPAWN_EGG_ENDERMAN: return cMonster::mtEnderman; + case E_META_SPAWN_EGG_GHAST: return cMonster::mtGhast; + case E_META_SPAWN_EGG_HORSE: return cMonster::mtHorse; + case E_META_SPAWN_EGG_MAGMA_CUBE: return cMonster::mtMagmaCube; + case E_META_SPAWN_EGG_MOOSHROOM: return cMonster::mtMooshroom; + case E_META_SPAWN_EGG_OCELOT: return cMonster::mtOcelot; + case E_META_SPAWN_EGG_PIG: return cMonster::mtPig; + case E_META_SPAWN_EGG_SHEEP: return cMonster::mtSheep; + case E_META_SPAWN_EGG_SILVERFISH: return cMonster::mtSilverfish; + case E_META_SPAWN_EGG_SKELETON: return cMonster::mtSkeleton; + case E_META_SPAWN_EGG_SLIME: return cMonster::mtSlime; + case E_META_SPAWN_EGG_SPIDER: return cMonster::mtSpider; + case E_META_SPAWN_EGG_SQUID: return cMonster::mtSquid; + case E_META_SPAWN_EGG_VILLAGER: return cMonster::mtVillager; + case E_META_SPAWN_EGG_WITCH: return cMonster::mtWitch; + case E_META_SPAWN_EGG_WOLF: return cMonster::mtWolf; + case E_META_SPAWN_EGG_ZOMBIE: return cMonster::mtZombie; + case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return cMonster::mtZombiePigman; + } + return cMonster::mtInvalidType; + } } ; diff --git a/src/Items/ItemSword.h b/src/Items/ItemSword.h index a7c1d2432..44feb2d83 100644 --- a/src/Items/ItemSword.h +++ b/src/Items/ItemSword.h @@ -23,6 +23,19 @@ public: { return (a_BlockType == E_BLOCK_COBWEB); } + + virtual bool CanRepairWithRawMaterial(short a_ItemType) override + { + switch (m_ItemType) + { + case E_ITEM_WOODEN_SWORD: return (a_ItemType == E_BLOCK_PLANKS); + case E_ITEM_STONE_SWORD: return (a_ItemType == E_BLOCK_COBBLESTONE); + case E_ITEM_IRON_SWORD: return (a_ItemType == E_ITEM_IRON); + case E_ITEM_GOLD_SWORD: return (a_ItemType == E_ITEM_GOLD); + case E_ITEM_DIAMOND_SWORD: return (a_ItemType == E_ITEM_DIAMOND); + } + return false; + } } ; diff --git a/src/Items/ItemThrowable.h b/src/Items/ItemThrowable.h index c6a4e714e..35c2b8731 100644 --- a/src/Items/ItemThrowable.h +++ b/src/Items/ItemThrowable.h @@ -28,15 +28,19 @@ public: 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 { + Vector3d Pos = a_Player->GetThrowStartPos(); + Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff; + + if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed) < 0) + { + return false; + } + if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } - Vector3d Pos = a_Player->GetThrowStartPos(); - Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff; - a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed); - return true; } @@ -127,7 +131,10 @@ public: return false; } - a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem()); + 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; + } if (!a_Player->IsGameModeCreative()) { |