Browse Source

add item modifiers to shaped recipies to allow recipies that do not consume an item completly

Kolja Strohm 2 years ago
parent
commit
acbc9e424e

+ 24 - 28
FactoryCraft/BasicBlock.cpp

@@ -27,22 +27,18 @@ BasicBlockType::BasicBlockType(int typeId, int itemTypeId, ModelInfo model)
 
 
 void BasicBlockType::createSuperBlock(Block* zBlock, Item* zItem) const
 void BasicBlockType::createSuperBlock(Block* zBlock, Item* zItem) const
 {
 {
-	if (zItem)
-		BlockType::createSuperBlock(zBlock, zItem);
-	else
-	{
-		BasicBlock* block = dynamic_cast<BasicBlock*>(zBlock);
-		if (!block)
-			throw "DirtBlockType::createSuperBlock was called with a block witch is not an instance of BasicBlock";
-		block->transparent = transparent;
-		block->passable = passable;
-		block->hp = (float)getInitialMaxHP();
-		block->maxHP = (float)getInitialMaxHP();
-		block->hardness = hardness;
-		block->zTool = zTool;
-		block->speedModifier = speedModifier;
-		block->interactable = interactable;
-	}
+	BasicBlock* block = dynamic_cast<BasicBlock*>(zBlock);
+	if (!block)
+		throw "DirtBlockType::createSuperBlock was called with a block witch is not an instance of BasicBlock";
+	block->transparent = transparent;
+	block->passable = passable;
+	block->hp = (float)getInitialMaxHP();
+	block->maxHP = (float)getInitialMaxHP();
+	block->hardness = hardness;
+	block->zTool = zTool;
+	block->speedModifier = speedModifier;
+	block->interactable = interactable;
+	BlockType::createSuperBlock(zBlock, zItem);
 }
 }
 
 
 Block* BasicBlockType::createBlock(Framework::Vec3<int> position) const
 Block* BasicBlockType::createBlock(Framework::Vec3<int> position) const
@@ -70,7 +66,7 @@ DirtBlockItemType::DirtBlockItemType()
 Item* DirtBlockItemType::createItem() const
 Item* DirtBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, DirtBlockType::INSTANCE, "Dirt");
 	BasicBlockItem* item = new BasicBlockItem(this, DirtBlockType::INSTANCE, "Dirt");
-	initializeItem(item, 0, 0, 100, 100, 1, 0, 1);
+	initializeItem(item, 0, 0, 1, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -90,7 +86,7 @@ StoneBlockItemType::StoneBlockItemType()
 Item* StoneBlockItemType::createItem() const
 Item* StoneBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, StoneBlockType::INSTANCE, "Stone");
 	BasicBlockItem* item = new BasicBlockItem(this, StoneBlockType::INSTANCE, "Stone");
-	initializeItem(item, 0, 0, 100, 100, 2, 0, 1);
+	initializeItem(item, 0, 0, 2, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -110,7 +106,7 @@ SandBlockItemType::SandBlockItemType()
 Item* SandBlockItemType::createItem() const
 Item* SandBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, SandBlockType::INSTANCE, "Sand");
 	BasicBlockItem* item = new BasicBlockItem(this, SandBlockType::INSTANCE, "Sand");
-	initializeItem(item, 0, 0, 100, 100, 0.5f, 0, 1);
+	initializeItem(item, 0, 0, 0.5f, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -130,7 +126,7 @@ OakBlockItemType::OakBlockItemType()
 Item* OakBlockItemType::createItem() const
 Item* OakBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, OakBlockType::INSTANCE, "Oak");
 	BasicBlockItem* item = new BasicBlockItem(this, OakBlockType::INSTANCE, "Oak");
-	initializeItem(item, 0, 0, 100, 100, 1.5f, 0, 1);
+	initializeItem(item, 0, 0, 1.5f, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -150,7 +146,7 @@ LeavesBlockItemType::LeavesBlockItemType()
 Item* LeavesBlockItemType::createItem() const
 Item* LeavesBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, LeavesBlockType::INSTANCE, "Leaves");
 	BasicBlockItem* item = new BasicBlockItem(this, LeavesBlockType::INSTANCE, "Leaves");
-	initializeItem(item, 0, 0, 100, 100, 0.1f, 0, 1);
+	initializeItem(item, 0, 0, 0.1f, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -170,7 +166,7 @@ GravelBlockItemType::GravelBlockItemType()
 Item* GravelBlockItemType::createItem() const
 Item* GravelBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, GravelBlockType::INSTANCE, "Gravel");
 	BasicBlockItem* item = new BasicBlockItem(this, GravelBlockType::INSTANCE, "Gravel");
-	initializeItem(item, 0, 0, 100, 100, 0.75f, 0, 1);
+	initializeItem(item, 0, 0, 0.75f, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -190,7 +186,7 @@ GraniteBlockItemType::GraniteBlockItemType()
 Item* GraniteBlockItemType::createItem() const
 Item* GraniteBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, GraniteBlockType::INSTANCE, "Granite");
 	BasicBlockItem* item = new BasicBlockItem(this, GraniteBlockType::INSTANCE, "Granite");
-	initializeItem(item, 0, 0, 100, 100, 3.f, 0, 1);
+	initializeItem(item, 0, 0, 3.f, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -210,7 +206,7 @@ CobbleBlockItemType::CobbleBlockItemType()
 Item* CobbleBlockItemType::createItem() const
 Item* CobbleBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, CobbleBlockType::INSTANCE, "Cobble");
 	BasicBlockItem* item = new BasicBlockItem(this, CobbleBlockType::INSTANCE, "Cobble");
-	initializeItem(item, 0, 0, 100, 100, 1.f, 0, 1);
+	initializeItem(item, 0, 0, 1.f, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -230,7 +226,7 @@ BirchBlockItemType::BirchBlockItemType()
 Item* BirchBlockItemType::createItem() const
 Item* BirchBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, BirchBlockType::INSTANCE, "Birch");
 	BasicBlockItem* item = new BasicBlockItem(this, BirchBlockType::INSTANCE, "Birch");
-	initializeItem(item, 0, 0, 100, 100, 1.5f, 0, 1);
+	initializeItem(item, 0, 0, 1.5f, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -250,7 +246,7 @@ BeechBlockItemType::BeechBlockItemType()
 Item* BeechBlockItemType::createItem() const
 Item* BeechBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, BeechBlockType::INSTANCE, "Beech");
 	BasicBlockItem* item = new BasicBlockItem(this, BeechBlockType::INSTANCE, "Beech");
-	initializeItem(item, 0, 0, 100, 100, 1.5f, 0, 1);
+	initializeItem(item, 0, 0, 1.5f, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -270,7 +266,7 @@ BasaltBlockItemType::BasaltBlockItemType()
 Item* BasaltBlockItemType::createItem() const
 Item* BasaltBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, BasaltBlockType::INSTANCE, "Basalt");
 	BasicBlockItem* item = new BasicBlockItem(this, BasaltBlockType::INSTANCE, "Basalt");
-	initializeItem(item, 0, 0, 100, 100, 2.f, 0, 1);
+	initializeItem(item, 0, 0, 2.f, 0, 1);
 	return item;
 	return item;
 }
 }
 
 
@@ -290,6 +286,6 @@ PineBlockItemType::PineBlockItemType()
 Item* PineBlockItemType::createItem() const
 Item* PineBlockItemType::createItem() const
 {
 {
 	BasicBlockItem* item = new BasicBlockItem(this, PineBlockType::INSTANCE, "Pine");
 	BasicBlockItem* item = new BasicBlockItem(this, PineBlockType::INSTANCE, "Pine");
-	initializeItem(item, 0, 0, 100, 100, 1.4f, 0, 1);
+	initializeItem(item, 0, 0, 1.4f, 0, 1);
 	return item;
 	return item;
 }
 }

+ 1 - 9
FactoryCraft/Block.cpp

@@ -257,8 +257,6 @@ bool BasicBlockItem::canBeStackedWith(const Item* zItem) const
 		return Item::canBeStackedWith(zItem) &&
 		return Item::canBeStackedWith(zItem) &&
 			transparent == item->transparent &&
 			transparent == item->transparent &&
 			passable == item->passable &&
 			passable == item->passable &&
-			hp == item->hp &&
-			maxHP == item->maxHP &&
 			hardness == item->hardness &&
 			hardness == item->hardness &&
 			toolId == item->toolId &&
 			toolId == item->toolId &&
 			speedModifier == item->speedModifier && interactable == item->interactable;
 			speedModifier == item->speedModifier && interactable == item->interactable;
@@ -279,8 +277,6 @@ void BasicBlockItemType::loadSuperItem(Item* zItem, Framework::StreamReader* zRe
 		throw "BasicBlockItemType::loadSuperItem was called with an invalid item";
 		throw "BasicBlockItemType::loadSuperItem was called with an invalid item";
 	zReader->lese((char*)&item->transparent, 1);
 	zReader->lese((char*)&item->transparent, 1);
 	zReader->lese((char*)&item->passable, 1);
 	zReader->lese((char*)&item->passable, 1);
-	zReader->lese((char*)&item->hp, 4);
-	zReader->lese((char*)&item->maxHP, 4);
 	zReader->lese((char*)&item->hardness, 4);
 	zReader->lese((char*)&item->hardness, 4);
 	zReader->lese((char*)&item->toolId, 4);
 	zReader->lese((char*)&item->toolId, 4);
 	zReader->lese((char*)&item->speedModifier, 4);
 	zReader->lese((char*)&item->speedModifier, 4);
@@ -295,20 +291,16 @@ void BasicBlockItemType::saveSuperItem(const Item* zItem, Framework::StreamWrite
 		throw "BasicBlockItemType::saveSuperItem was called with an invalid item";
 		throw "BasicBlockItemType::saveSuperItem was called with an invalid item";
 	zWriter->schreibe((char*)&item->transparent, 1);
 	zWriter->schreibe((char*)&item->transparent, 1);
 	zWriter->schreibe((char*)&item->passable, 1);
 	zWriter->schreibe((char*)&item->passable, 1);
-	zWriter->schreibe((char*)&item->hp, 4);
-	zWriter->schreibe((char*)&item->maxHP, 4);
 	zWriter->schreibe((char*)&item->hardness, 4);
 	zWriter->schreibe((char*)&item->hardness, 4);
 	zWriter->schreibe((char*)&item->toolId, 4);
 	zWriter->schreibe((char*)&item->toolId, 4);
 	zWriter->schreibe((char*)&item->speedModifier, 4);
 	zWriter->schreibe((char*)&item->speedModifier, 4);
 	zWriter->schreibe((char*)&item->interactable, 1);
 	zWriter->schreibe((char*)&item->interactable, 1);
 }
 }
 
 
-void BasicBlockItemType::initializeItem(BasicBlockItem* zItem, bool transparent, bool passable, float hp, float maxHP, float hardness, int toolId, float speedModifier) const
+void BasicBlockItemType::initializeItem(BasicBlockItem* zItem, bool transparent, bool passable, float hardness, int toolId, float speedModifier) const
 {
 {
 	zItem->transparent = transparent;
 	zItem->transparent = transparent;
 	zItem->passable = passable;
 	zItem->passable = passable;
-	zItem->hp = hp;
-	zItem->maxHP = maxHP;
 	zItem->hardness = hardness;
 	zItem->hardness = hardness;
 	zItem->toolId = toolId;
 	zItem->toolId = toolId;
 	zItem->speedModifier = speedModifier;
 	zItem->speedModifier = speedModifier;

+ 1 - 3
FactoryCraft/Block.h

@@ -102,8 +102,6 @@ class BasicBlockItem : public Item
 protected:
 protected:
 	bool transparent;
 	bool transparent;
 	bool passable;
 	bool passable;
-	float hp;
-	float maxHP;
 	float hardness;
 	float hardness;
 	int toolId;
 	int toolId;
 	float speedModifier;
 	float speedModifier;
@@ -123,5 +121,5 @@ protected:
 	BasicBlockItemType(int id, const char* name, ItemSkillLevelUpRule* levelUpRule, const ItemType* zBrokenType, ModelInfo model);
 	BasicBlockItemType(int id, const char* name, ItemSkillLevelUpRule* levelUpRule, const ItemType* zBrokenType, ModelInfo model);
 	virtual void loadSuperItem(Item* zItem, Framework::StreamReader* zReader) const override;
 	virtual void loadSuperItem(Item* zItem, Framework::StreamReader* zReader) const override;
 	virtual void saveSuperItem(const Item* zItem, Framework::StreamWriter* zWriter) const override;
 	virtual void saveSuperItem(const Item* zItem, Framework::StreamWriter* zWriter) const override;
-	void initializeItem(BasicBlockItem* zItem, bool transparent, bool passable, float hp, float maxHP, float hardness, int toolId, float speedModifier) const;
+	void initializeItem(BasicBlockItem* zItem, bool transparent, bool passable, float hardness, int toolId, float speedModifier) const;
 };
 };

+ 12 - 13
FactoryCraft/BlockType.cpp

@@ -58,19 +58,20 @@ void BlockType::saveSuperBlock(Block* zBlock, Framework::StreamWriter* zWriter)
 
 
 void BlockType::createSuperBlock(Block* zBlock, Item* zItem) const
 void BlockType::createSuperBlock(Block* zBlock, Item* zItem) const
 {
 {
-	BasicBlockItem* item = dynamic_cast<BasicBlockItem*>(zItem);
-	if (!item)
+	if (zItem)
 	{
 	{
-		throw "BlockType::createSuperBlock was called with an item witch was not an instance of BasicBlockItem";
+		BasicBlockItem* item = dynamic_cast<BasicBlockItem*>(zItem);
+		if (!item)
+		{
+			throw "BlockType::createSuperBlock was called with an item witch was not an instance of BasicBlockItem";
+		}
+		zBlock->transparent = item->transparent;
+		zBlock->passable = item->passable;
+		zBlock->hardness = item->hardness;
+		zBlock->speedModifier = item->speedModifier;
+		zBlock->zTool = item->toolId >= 0 ? StaticRegistry<ItemType>::INSTANCE.zElement(item->toolId) : 0;
+		zBlock->interactable = item->interactable;
 	}
 	}
-	zBlock->transparent = item->transparent;
-	zBlock->passable = item->passable;
-	zBlock->hp = item->hp;
-	zBlock->maxHP = item->maxHP;
-	zBlock->hardness = item->hardness;
-	zBlock->speedModifier = item->speedModifier;
-	zBlock->zTool = item->toolId >= 0 ? StaticRegistry<ItemType>::INSTANCE.zElement(item->toolId) : 0;
-	zBlock->interactable = item->interactable;
 }
 }
 
 
 void BlockType::createSuperItem(Block* zBlock, Item* zItem) const
 void BlockType::createSuperItem(Block* zBlock, Item* zItem) const
@@ -82,8 +83,6 @@ void BlockType::createSuperItem(Block* zBlock, Item* zItem) const
 	}
 	}
 	item->transparent = zBlock->transparent;
 	item->transparent = zBlock->transparent;
 	item->passable = zBlock->passable;
 	item->passable = zBlock->passable;
-	item->hp = zBlock->maxHP; // reset hp
-	item->maxHP = zBlock->maxHP;
 	item->hardness = zBlock->hardness;
 	item->hardness = zBlock->hardness;
 	item->speedModifier = zBlock->speedModifier;
 	item->speedModifier = zBlock->speedModifier;
 	item->toolId = zBlock->zTool ? zBlock->zTool->getId() : -1;
 	item->toolId = zBlock->zTool ? zBlock->zTool->getId() : -1;

+ 55 - 13
FactoryCraft/CraftingStorage.cpp

@@ -55,9 +55,9 @@ void BasicShapedCrafter::getOutputPreview(NetworkMessage* zMessage)
 			buffer.schreibe((char*)&itemCount, 4);
 			buffer.schreibe((char*)&itemCount, 4);
 			if (itemCount > 0)
 			if (itemCount > 0)
 			{
 			{
-				float f = slot.damage;
+				float f = slot.hp;
 				buffer.schreibe((char*)&f, 4);
 				buffer.schreibe((char*)&f, 4);
-				f = slot.maxDamage;
+				f = slot.maxHp;
 				buffer.schreibe((char*)&f, 4);
 				buffer.schreibe((char*)&f, 4);
 				f = slot.durability;
 				f = slot.durability;
 				buffer.schreibe((char*)&f, 4);
 				buffer.schreibe((char*)&f, 4);
@@ -132,28 +132,70 @@ bool BasicShapedCrafter::hasFreeSpace(const Item* zItem, int amount)
 	return addable >= amount;
 	return addable >= amount;
 }
 }
 
 
-bool BasicShapedCrafter::consume(Framework::RCArray<ItemFilter>& filters, int width, int height)
+bool BasicShapedCrafter::consume(Framework::RCArray<ItemFilter>& filters, Framework::RCArray<ItemModifier>& modfiers, int width, int height)
 {
 {
-	for (ItemSlot* slot : craftingInput)
+	int beginX = this->width;
+	int beginY = this->height;
+	SourceSlotBlacklistFilter otherSlots;
+	for (int i = 0; i < craftingInput.getEintragAnzahl(); i++)
 	{
 	{
-		if (slot && slot->zStack())
+		if (!craftingInput.get(i)->isEmpty())
 		{
 		{
-			ItemStack* stack = zInventory->takeItemsOut(slot, 1, INSIDE);
-			if (stack)
-				stack->release();
+			int x = i % this->width;
+			int y = i / this->width;
+			beginX = MIN(beginX, x);
+			beginY = MIN(beginY, y);
 		}
 		}
+		otherSlots.addBlackListSlotId(craftingInput.get(i)->getId());
 	}
 	}
 	for (int x = 0; x < width; x++)
 	for (int x = 0; x < width; x++)
 	{
 	{
 		for (int y = 0; y < height; y++)
 		for (int y = 0; y < height; y++)
 		{
 		{
-			ItemFilter* f = filters.z(x * width + y);
+			ItemSlot* target = craftingInput.get((y + beginY) * this->width + x + beginX);
+			ItemStack* stack = zInventory->takeItemsOut(target, 1, INSIDE);
+			if (stack)
+			{
+				if (stack->getSize() > 0 && stack->zItem())
+				{
+					ItemModifier* m = modfiers.z(y * width + x);
+					if (m)
+						m->applyOn((Item*)stack->zItem());
+				}
+				if (stack->zItem()->getHp() == 0)
+					stack->release();
+				else if (stack->zItem()->getDurability() == 0)
+				{
+					Item* broken = stack->zItem()->zItemType()->breakItem(stack->zItem());
+					stack->release();
+					if (broken)
+					{
+						ItemStack* brokenStack = new ItemStack(broken, 1);
+						zInventory->addItems(brokenStack, INSIDE);
+						// TODO: if brokenStack is not empty spawn an item entity
+						brokenStack->release();
+					}
+				}
+				else
+				{
+					// TODO: transfer all items from target to other slots or drop them
+					zInventory->addItems(target, stack, INSIDE);
+					// TODO: if stack is not empty spawn an item entity
+				}
+			}
+			ItemFilter* f = filters.z(y * width + x);
 			if (f)
 			if (f)
 			{
 			{
-				ItemSlot* target = craftingInput.get(x * this->width + y);
-				Framework::Array< ItemSlot*> tmp;
-				tmp.add(target);
-				zInventory->localTransaction(0, &tmp, f, 1, NO_DIRECTION, INSIDE);
+				if (target->isEmpty())
+				{
+					Framework::Array< ItemSlot*> tmp;
+					tmp.add(target);
+					CombinedItemFilter combinedFilter(dynamic_cast<ItemFilter*>(f->getThis()), dynamic_cast<ItemFilter*>(otherSlots.getThis()), [](bool a, bool b)
+						{
+							return a && b;
+						});
+					zInventory->localTransaction(0, &tmp, &combinedFilter, 1, NO_DIRECTION, INSIDE);
+				}
 			}
 			}
 		}
 		}
 	}
 	}

+ 5 - 5
FactoryCraft/CraftingStorage.h

@@ -22,7 +22,7 @@ class ShapedCraftingStorage
 public:
 public:
 	virtual bool isAllAvailable(Framework::RCArray<ItemFilter>& filters, int width, int height) = 0;
 	virtual bool isAllAvailable(Framework::RCArray<ItemFilter>& filters, int width, int height) = 0;
 	virtual bool hasFreeSpace(const Item* zItem, int amount) = 0;
 	virtual bool hasFreeSpace(const Item* zItem, int amount) = 0;
-	virtual bool consume(Framework::RCArray<ItemFilter>& filters, int width, int height) = 0;
+	virtual bool consume(Framework::RCArray<ItemFilter>& filters, Framework::RCArray<ItemModifier>& modifiers, int width, int height) = 0;
 	virtual void addCraftingResult(ItemStack* stack) = 0;
 	virtual void addCraftingResult(ItemStack* stack) = 0;
 };
 };
 
 
@@ -40,10 +40,10 @@ private:
 
 
 public:
 public:
 	BasicShapedCrafter(int width, int height, Inventory* zInventory, Framework::Text recipieList);
 	BasicShapedCrafter(int width, int height, Inventory* zInventory, Framework::Text recipieList);
-	virtual bool isAllAvailable(Framework::RCArray<ItemFilter>& filters, int width, int height);
-	virtual bool hasFreeSpace(const Item* zItem, int amount);
-	virtual bool consume(Framework::RCArray<ItemFilter>& filters, int width, int height);
-	virtual void addCraftingResult(ItemStack* stack);
+	virtual bool isAllAvailable(Framework::RCArray<ItemFilter>& filters, int width, int height) override;
+	virtual bool hasFreeSpace(const Item* zItem, int amount) override;
+	virtual bool consume(Framework::RCArray<ItemFilter>& filters, Framework::RCArray<ItemModifier>& modifiers, int width, int height) override;
+	virtual void addCraftingResult(ItemStack* stack) override;
 	void applyCurrentRecipie();
 	void applyCurrentRecipie();
 	void calculateOutputPreview();
 	void calculateOutputPreview();
 };
 };

+ 2 - 0
FactoryCraft/FactoryCraft.vcxproj

@@ -120,6 +120,7 @@
     <ClInclude Include="Item.h" />
     <ClInclude Include="Item.h" />
     <ClInclude Include="ItemEntity.h" />
     <ClInclude Include="ItemEntity.h" />
     <ClInclude Include="ItemFilter.h" />
     <ClInclude Include="ItemFilter.h" />
+    <ClInclude Include="ItemModifier.h" />
     <ClInclude Include="ItemSkill.h" />
     <ClInclude Include="ItemSkill.h" />
     <ClInclude Include="ItemSlot.h" />
     <ClInclude Include="ItemSlot.h" />
     <ClInclude Include="ItemStack.h" />
     <ClInclude Include="ItemStack.h" />
@@ -176,6 +177,7 @@
     <ClCompile Include="Item.cpp" />
     <ClCompile Include="Item.cpp" />
     <ClCompile Include="ItemEntity.cpp" />
     <ClCompile Include="ItemEntity.cpp" />
     <ClCompile Include="ItemFilter.cpp" />
     <ClCompile Include="ItemFilter.cpp" />
+    <ClCompile Include="ItemModifier.cpp" />
     <ClCompile Include="ItemSkill.cpp" />
     <ClCompile Include="ItemSkill.cpp" />
     <ClCompile Include="ItemSlot.cpp" />
     <ClCompile Include="ItemSlot.cpp" />
     <ClCompile Include="ItemStack.cpp" />
     <ClCompile Include="ItemStack.cpp" />

+ 6 - 0
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -237,6 +237,9 @@
     <ClInclude Include="WormCaveGenerator.h">
     <ClInclude Include="WormCaveGenerator.h">
       <Filter>world\generator\caves</Filter>
       <Filter>world\generator\caves</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="ItemModifier.h">
+      <Filter>inventory\recipies</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Server.cpp">
     <ClCompile Include="Server.cpp">
@@ -398,5 +401,8 @@
     <ClCompile Include="CaveGenerator.cpp">
     <ClCompile Include="CaveGenerator.cpp">
       <Filter>world\generator\caves</Filter>
       <Filter>world\generator\caves</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="ItemModifier.cpp">
+      <Filter>inventory\recipies</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 4 - 4
FactoryCraft/Inventory.cpp

@@ -334,8 +334,8 @@ void Inventory::afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem
 		*(int*)(message + 1) = zSlot->getId();
 		*(int*)(message + 1) = zSlot->getId();
 		*(int*)(message + 5) = zSlot->getNumberOfItems();
 		*(int*)(message + 5) = zSlot->getNumberOfItems();
 		const Item* zItem = zSlot->zStack()->zItem();
 		const Item* zItem = zSlot->zStack()->zItem();
-		*(float*)(message + 9) = zItem->getDamage();
-		*(float*)(message + 13) = zItem->getMaxDamage();
+		*(float*)(message + 9) = zItem->getHp();
+		*(float*)(message + 13) = zItem->getMaxHp();
 		*(float*)(message + 17) = zItem->getDurability();
 		*(float*)(message + 17) = zItem->getDurability();
 		*(float*)(message + 21) = zItem->getMaxDurability();
 		*(float*)(message + 21) = zItem->getMaxDurability();
 		*(int*)(message + 25) = zItem->zItemType()->getId();
 		*(int*)(message + 25) = zItem->zItemType()->getId();
@@ -724,9 +724,9 @@ void Inventory::inventoryApi(Framework::StreamReader* zRequest, NetworkMessage*
 				buffer.schreibe((char*)&itemCount, 4);
 				buffer.schreibe((char*)&itemCount, 4);
 				if (itemCount > 0)
 				if (itemCount > 0)
 				{
 				{
-					float f = slot->zStack()->zItem()->getDamage();
+					float f = slot->zStack()->zItem()->getHp();
 					buffer.schreibe((char*)&f, 4);
 					buffer.schreibe((char*)&f, 4);
-					f = slot->zStack()->zItem()->getMaxDamage();
+					f = slot->zStack()->zItem()->getMaxHp();
 					buffer.schreibe((char*)&f, 4);
 					buffer.schreibe((char*)&f, 4);
 					f = slot->zStack()->zItem()->getDurability();
 					f = slot->zStack()->zItem()->getDurability();
 					buffer.schreibe((char*)&f, 4);
 					buffer.schreibe((char*)&f, 4);

+ 14 - 11
FactoryCraft/Item.cpp

@@ -5,8 +5,8 @@ Item::Item(const ItemType* zType, const char* name)
 	: ReferenceCounter(),
 	: ReferenceCounter(),
 	zType(zType),
 	zType(zType),
 	zBlockType(0),
 	zBlockType(0),
-	damage(0),
-	maxDamage(0),
+	hp(1),
+	maxHp(1),
 	durability(1),
 	durability(1),
 	maxDurability(1),
 	maxDurability(1),
 	eatable(0),
 	eatable(0),
@@ -18,6 +18,11 @@ Item::Item(const ItemType* zType, const char* name)
 	name(name)
 	name(name)
 {}
 {}
 
 
+void Item::setHp(float hp)
+{
+	this->hp = hp;
+}
+
 void Item::tick()
 void Item::tick()
 {}
 {}
 
 
@@ -31,9 +36,9 @@ const BlockType* Item::zPlacedBlockType() const
 	return zBlockType;
 	return zBlockType;
 }
 }
 
 
-float Item::getDamage() const
+float Item::getHp() const
 {
 {
-	return damage;
+	return hp;
 }
 }
 
 
 float Item::getDurability() const
 float Item::getDurability() const
@@ -76,18 +81,17 @@ int Item::getMaxStackSize() const
 	return maxStackSize;
 	return maxStackSize;
 }
 }
 
 
-float Item::getMaxDamage() const
+float Item::getMaxHp() const
 {
 {
-	return maxDamage;
+	return maxHp;
 }
 }
 
 
 bool Item::canBeStackedWith(const Item* zItem) const
 bool Item::canBeStackedWith(const Item* zItem) const
 {
 {
-	return zType == zItem->zType && damage == 0 &&
-		zItem->damage == 0 &&
+	return zType == zItem->zType &&
 		durability == maxDurability &&
 		durability == maxDurability &&
 		zItem->durability == zItem->maxDurability &&
 		zItem->durability == zItem->maxDurability &&
-		maxDamage == zItem->maxDamage &&
+		maxHp == zItem->maxHp &&
 		eatable == zItem->eatable &&
 		eatable == zItem->eatable &&
 		placeable == zItem->placeable &&
 		placeable == zItem->placeable &&
 		equippable == zItem->eatable &&
 		equippable == zItem->eatable &&
@@ -99,8 +103,7 @@ bool Item::canBeStackedWith(const Item* zItem) const
 
 
 void Item::onPlaced()
 void Item::onPlaced()
 {
 {
-	damage = maxDamage;
-	durability = 0;
+	hp = 0;
 }
 }
 
 
 void Item::applyInventoryEffects(Entity* zTarget)
 void Item::applyInventoryEffects(Entity* zTarget)

+ 6 - 5
FactoryCraft/Item.h

@@ -12,9 +12,9 @@ class Item : public virtual Framework::ReferenceCounter
 protected:
 protected:
 	const ItemType* zType;
 	const ItemType* zType;
 	const BlockType* zBlockType;
 	const BlockType* zBlockType;
-	float damage;
-	float maxDamage;
-	float durability;
+	float hp; // an item will be removed once its hp reaches 0
+	float maxHp;
+	float durability; // an item will break into another item once its durability reaches 0
 	float maxDurability;
 	float maxDurability;
 	bool eatable;
 	bool eatable;
 	bool placeable;
 	bool placeable;
@@ -26,11 +26,12 @@ protected:
 	Item(const ItemType* zType, const char* name);
 	Item(const ItemType* zType, const char* name);
 
 
 public:
 public:
+	void setHp(float hp);
 	virtual void tick();
 	virtual void tick();
 
 
 	const ItemType* zItemType() const;
 	const ItemType* zItemType() const;
 	const BlockType* zPlacedBlockType() const;
 	const BlockType* zPlacedBlockType() const;
-	float getDamage() const;
+	float getHp() const;
 	float getDurability() const;
 	float getDurability() const;
 	bool isUsable() const;
 	bool isUsable() const;
 	bool isEatable() const;
 	bool isEatable() const;
@@ -39,7 +40,7 @@ public:
 	bool isSolid() const;
 	bool isSolid() const;
 	float getMaxDurability() const;
 	float getMaxDurability() const;
 	int getMaxStackSize() const;
 	int getMaxStackSize() const;
-	float getMaxDamage() const;
+	float getMaxHp() const;
 	virtual bool canBeStackedWith(const Item* zItem) const;
 	virtual bool canBeStackedWith(const Item* zItem) const;
 	virtual void onPlaced();
 	virtual void onPlaced();
 
 

+ 31 - 0
FactoryCraft/ItemFilter.cpp

@@ -31,6 +31,12 @@ CombinedItemFilter::CombinedItemFilter(ItemFilter* filterA, ItemFilter* filterB,
 	op(op)
 	op(op)
 {}
 {}
 
 
+CombinedItemFilter::~CombinedItemFilter()
+{
+	filterA->release();
+	filterB->release();
+}
+
 bool CombinedItemFilter::matchItem(const Item* zItem) const
 bool CombinedItemFilter::matchItem(const Item* zItem) const
 {
 {
 	return op(filterA->matchItem(zItem), filterB->matchItem(zItem));
 	return op(filterA->matchItem(zItem), filterB->matchItem(zItem));
@@ -72,4 +78,29 @@ bool SpecificSlotFilter::matchSourceSlot(ItemSlot* zSlot) const
 bool SpecificSlotFilter::matchTargetSlot(ItemSlot* zSlot) const
 bool SpecificSlotFilter::matchTargetSlot(ItemSlot* zSlot) const
 {
 {
 	return targetSlotId == zSlot->getId();
 	return targetSlotId == zSlot->getId();
+}
+
+
+SourceSlotBlacklistFilter::SourceSlotBlacklistFilter()
+	: ItemFilter()
+{}
+
+void SourceSlotBlacklistFilter::addBlackListSlotId(int id)
+{
+	blackList.add(id);
+}
+
+bool SourceSlotBlacklistFilter::matchSourceSlot(ItemSlot* zSlot) const
+{
+	for (int black : blackList)
+	{
+		if (black == zSlot->getId())
+			return 0;
+	}
+	return 1;
+}
+
+bool SourceSlotBlacklistFilter::matchTargetSlot(ItemSlot* zSlot) const
+{
+	return 1;
 }
 }

+ 16 - 0
FactoryCraft/ItemFilter.h

@@ -2,6 +2,7 @@
 
 
 #include <ReferenceCounter.h>
 #include <ReferenceCounter.h>
 #include <functional>
 #include <functional>
+#include <Array.h>
 
 
 class Item;
 class Item;
 class ItemType;
 class ItemType;
@@ -16,6 +17,7 @@ public:
 	virtual bool matchTargetSlot(ItemSlot* zSlot) const;
 	virtual bool matchTargetSlot(ItemSlot* zSlot) const;
 };
 };
 
 
+
 class CombinedItemFilter : public ItemFilter
 class CombinedItemFilter : public ItemFilter
 {
 {
 private:
 private:
@@ -25,9 +27,11 @@ private:
 
 
 public:
 public:
 	CombinedItemFilter(ItemFilter* filterA, ItemFilter* filterB, std::function<bool(bool, bool)> op);
 	CombinedItemFilter(ItemFilter* filterA, ItemFilter* filterB, std::function<bool(bool, bool)> op);
+	~CombinedItemFilter();
 	bool matchItem(const Item* zItem) const override;
 	bool matchItem(const Item* zItem) const override;
 };
 };
 
 
+
 class AnyItemFilter : public ItemFilter
 class AnyItemFilter : public ItemFilter
 {
 {
 public:
 public:
@@ -35,6 +39,7 @@ public:
 	bool matchItem(const Item* zItem) const override;
 	bool matchItem(const Item* zItem) const override;
 };
 };
 
 
+
 class TypeItemFilter : public ItemFilter
 class TypeItemFilter : public ItemFilter
 {
 {
 private:
 private:
@@ -59,3 +64,14 @@ public:
 };
 };
 
 
 
 
+class SourceSlotBlacklistFilter : public ItemFilter
+{
+private:
+	Framework::Array<int> blackList;
+
+public:
+	SourceSlotBlacklistFilter();
+	void addBlackListSlotId(int id);
+	bool matchSourceSlot(ItemSlot* zSlot) const override;
+	bool matchTargetSlot(ItemSlot* zSlot) const override;
+};

+ 53 - 0
FactoryCraft/ItemModifier.cpp

@@ -0,0 +1,53 @@
+#include "ItemModifier.h"
+
+using namespace Framework;
+
+ItemModifier::ItemModifier()
+	: ReferenceCounter()
+{}
+
+
+AttributeItemModifier::AttributeItemModifier(Framework::Text attribute, Framework::Text value)
+	: ItemModifier(),
+	attribute(attribute),
+	value(value)
+{}
+
+void AttributeItemModifier::applyOn(Item* zItem)
+{
+	if (attribute.istGleich("hp"))
+	{
+		float hp = 0;
+		if (value.positionVon("+=") == 0 || value.positionVon("-=") == 0)
+		{
+			hp = zItem->getHp();
+			if (value.positionVon("+=") == 0)
+				hp += TextZuFloat(value.getText() + 2);
+			if (value.positionVon("-=") == 0)
+				hp -= TextZuFloat(value.getText() + 2);
+		}
+		if (value.positionVon("=") == 0)
+		{
+			hp = TextZuFloat(value.getText() + 1);
+		}
+		zItem->setHp(hp);
+	}
+}
+
+
+CombinedItemModifier::CombinedItemModifier()
+	: ItemModifier()
+{}
+
+void CombinedItemModifier::addModifier(ItemModifier* modifier)
+{
+	modifiers.add(modifier);
+}
+
+void CombinedItemModifier::applyOn(Item* zItem)
+{
+	for (ItemModifier* modifier : modifiers)
+	{
+		modifier->applyOn(zItem);
+	}
+}

+ 35 - 0
FactoryCraft/ItemModifier.h

@@ -0,0 +1,35 @@
+#pragma once
+
+#include <ReferenceCounter.h>
+#include <Text.h>
+
+#include "Item.h"
+
+
+class ItemModifier : public virtual Framework::ReferenceCounter
+{
+public:
+	ItemModifier();
+	virtual void applyOn(Item* zItem) = 0;
+};
+
+class AttributeItemModifier : public ItemModifier
+{
+private:
+	Framework::Text attribute;
+	Framework::Text value;
+
+public:
+	AttributeItemModifier(Framework::Text attribute, Framework::Text value);
+	void applyOn(Item* zItem) override;
+};
+
+class CombinedItemModifier : public ItemModifier
+{
+	Framework::RCArray<ItemModifier> modifiers;
+
+public:
+	CombinedItemModifier();
+	void addModifier(ItemModifier* modifier);
+	void applyOn(Item* zItem) override;
+};

+ 8 - 8
FactoryCraft/ItemType.cpp

@@ -24,8 +24,8 @@ ItemType::~ItemType()
 
 
 void ItemType::loadSuperItem(Item* zItem, Framework::StreamReader* zReader) const
 void ItemType::loadSuperItem(Item* zItem, Framework::StreamReader* zReader) const
 {
 {
-	zReader->lese((char*)&zItem->damage, 4);
-	zReader->lese((char*)&zItem->maxDamage, 4);
+	zReader->lese((char*)&zItem->hp, 4);
+	zReader->lese((char*)&zItem->maxHp, 4);
 	zReader->lese((char*)&zItem->durability, 4);
 	zReader->lese((char*)&zItem->durability, 4);
 	zReader->lese((char*)&zItem->maxDurability, 4);
 	zReader->lese((char*)&zItem->maxDurability, 4);
 	unsigned char flags = 0;
 	unsigned char flags = 0;
@@ -44,8 +44,8 @@ void ItemType::loadSuperItem(Item* zItem, Framework::StreamReader* zReader) cons
 
 
 void ItemType::saveSuperItem(const Item* zItem, Framework::StreamWriter* zWriter) const
 void ItemType::saveSuperItem(const Item* zItem, Framework::StreamWriter* zWriter) const
 {
 {
-	zWriter->schreibe((char*)&zItem->damage, 4);
-	zWriter->schreibe((char*)&zItem->maxDamage, 4);
+	zWriter->schreibe((char*)&zItem->hp, 4);
+	zWriter->schreibe((char*)&zItem->maxHp, 4);
 	zWriter->schreibe((char*)&zItem->durability, 4);
 	zWriter->schreibe((char*)&zItem->durability, 4);
 	zWriter->schreibe((char*)&zItem->maxDurability, 4);
 	zWriter->schreibe((char*)&zItem->maxDurability, 4);
 	unsigned char flags = (unsigned char)((zItem->usable << 4) | (zItem->solid << 3) | (zItem->equippable << 2) | (zItem->placeable << 1) | zItem->eatable);
 	unsigned char flags = (unsigned char)((zItem->usable << 4) | (zItem->solid << 3) | (zItem->equippable << 2) | (zItem->placeable << 1) | zItem->eatable);
@@ -66,11 +66,11 @@ void ItemType::saveSuperItemSkill(const ItemSkill* zSkill, Framework::StreamWrit
 
 
 }
 }
 
 
-Item* ItemType::createBasicItem(const char* name, float damage, float maxDamage, float durability, float maxDurability, bool eatable, bool placeable, bool equippable, bool solid, bool usable, int maxStackSize) const
+Item* ItemType::createBasicItem(const char* name, float hp, float maxHp, float durability, float maxDurability, bool eatable, bool placeable, bool equippable, bool solid, bool usable, int maxStackSize) const
 {
 {
 	Item* item = new Item(this, name);
 	Item* item = new Item(this, name);
-	item->damage = damage;
-	item->maxDamage = maxDamage;
+	item->hp = hp;
+	item->maxHp = maxHp;
 	item->durability = durability;
 	item->durability = durability;
 	item->maxDurability = maxDurability;
 	item->maxDurability = maxDurability;
 	item->eatable = eatable;
 	item->eatable = eatable;
@@ -147,7 +147,7 @@ void ItemType::saveItemSkill(const ItemSkill* zSkill, Framework::StreamWriter* z
 	saveSuperItemSkill(zSkill, zWriter);
 	saveSuperItemSkill(zSkill, zWriter);
 }
 }
 
 
-Item* ItemType::breakItem(Item* zItem) const
+Item* ItemType::breakItem(const Item* zItem) const
 {
 {
 	return 0;
 	return 0;
 }
 }

+ 2 - 2
FactoryCraft/ItemType.h

@@ -29,7 +29,7 @@ protected:
 	virtual void saveSuperItem(const Item* zItem, Framework::StreamWriter* zWriter) const;
 	virtual void saveSuperItem(const Item* zItem, Framework::StreamWriter* zWriter) const;
 	virtual void loadSuperItemSkill(ItemSkill* zSkill, Framework::StreamReader* zReader) const;
 	virtual void loadSuperItemSkill(ItemSkill* zSkill, Framework::StreamReader* zReader) const;
 	virtual void saveSuperItemSkill(const ItemSkill* zSkill, Framework::StreamWriter* zWriter) const;
 	virtual void saveSuperItemSkill(const ItemSkill* zSkill, Framework::StreamWriter* zWriter) const;
-	Item* createBasicItem(const char* name, float damage, float maxDamage, float durability, float maxDurability, bool eatable, bool placeable, bool equippable, bool solid, bool usable, int maxStackSize) const;
+	Item* createBasicItem(const char* name, float hp, float maxHp, float durability, float maxDurability, bool eatable, bool placeable, bool equippable, bool solid, bool usable, int maxStackSize) const;
 
 
 public:
 public:
 	~ItemType();
 	~ItemType();
@@ -46,6 +46,6 @@ public:
 	virtual ItemSkill* loadItemSkill(Framework::StreamReader* zReader) const;
 	virtual ItemSkill* loadItemSkill(Framework::StreamReader* zReader) const;
 	virtual void saveItemSkill(const ItemSkill* zSkill, Framework::StreamWriter* zWriter) const;
 	virtual void saveItemSkill(const ItemSkill* zSkill, Framework::StreamWriter* zWriter) const;
 	virtual Item* cloneItem(const Item* zItem) const;
 	virtual Item* cloneItem(const Item* zItem) const;
-	virtual Item* breakItem(Item* zItem) const;
+	virtual Item* breakItem(const Item* zItem) const;
 	const ModelInfo& getModel() const;
 	const ModelInfo& getModel() const;
 };
 };

+ 15 - 18
FactoryCraft/LightSources.cpp

@@ -30,10 +30,10 @@ void LightSourceItemType::saveSuperItem(const Item* zItem, Framework::StreamWrit
 	BasicBlockItemType::saveSuperItem(zItem, zWriter);
 	BasicBlockItemType::saveSuperItem(zItem, zWriter);
 }
 }
 
 
-void LightSourceItemType::initializeItem(LightSourceItem* zItem, int color, bool transparent, bool passable, float hp, float maxHP, float hardness, int toolId, float speedModifier) const
+void LightSourceItemType::initializeItem(LightSourceItem* zItem, int color, bool transparent, bool passable, float hardness, int toolId, float speedModifier) const
 {
 {
 	zItem->color = color;
 	zItem->color = color;
-	BasicBlockItemType::initializeItem(zItem, transparent, passable, hp, maxHP, hardness, toolId, speedModifier);
+	BasicBlockItemType::initializeItem(zItem, transparent, passable, hardness, toolId, speedModifier);
 }
 }
 
 
 
 
@@ -68,26 +68,23 @@ BasicLightSourceBlockType::BasicLightSourceBlockType(int typeId, int itemTypeId,
 
 
 void BasicLightSourceBlockType::createSuperBlock(Block* zBlock, Item* zItem) const
 void BasicLightSourceBlockType::createSuperBlock(Block* zBlock, Item* zItem) const
 {
 {
+	BasicLightSource* block = dynamic_cast<BasicLightSource*>(zBlock);
+	if (!block)
+		throw "BasicLightSourceBlockType::createSuperBlock was called with a block witch is not an instance of BasicLightSource";
+	block->transparent = transparent;
+	block->passable = passable;
+	block->hp = (float)getInitialMaxHP();
+	block->maxHP = (float)getInitialMaxHP();
+	block->hardness = hardness;
+	block->zTool = 0;
+	block->speedModifier = 1;
+	block->interactable = interactable;
+	block->setLight(color);
+	BlockType::createSuperBlock(zBlock, zItem);
 	if (zItem)
 	if (zItem)
 	{
 	{
-		BlockType::createSuperBlock(zBlock, zItem);
 		dynamic_cast<BasicLightSource*>(zBlock)->setLight(dynamic_cast<LightSourceItem*>(zItem)->color);
 		dynamic_cast<BasicLightSource*>(zBlock)->setLight(dynamic_cast<LightSourceItem*>(zItem)->color);
 	}
 	}
-	else
-	{
-		BasicLightSource* block = dynamic_cast<BasicLightSource*>(zBlock);
-		if (!block)
-			throw "BasicLightSourceBlockType::createSuperBlock was called with a block witch is not an instance of BasicLightSource";
-		block->transparent = transparent;
-		block->passable = passable;
-		block->hp = (float)getInitialMaxHP();
-		block->maxHP = (float)getInitialMaxHP();
-		block->hardness = hardness;
-		block->zTool = 0;
-		block->speedModifier = 1;
-		block->interactable = interactable;
-		block->setLight(color);
-	}
 }
 }
 
 
 void BasicLightSourceBlockType::loadSuperBlock(Block* zBlock, Framework::StreamReader* zReader) const
 void BasicLightSourceBlockType::loadSuperBlock(Block* zBlock, Framework::StreamReader* zReader) const

+ 1 - 1
FactoryCraft/LightSources.h

@@ -26,7 +26,7 @@ protected:
 	LightSourceItemType(int id, const char* name, const ModelInfo model);
 	LightSourceItemType(int id, const char* name, const ModelInfo model);
 	virtual void loadSuperItem(Item* zItem, Framework::StreamReader* zReader) const override;
 	virtual void loadSuperItem(Item* zItem, Framework::StreamReader* zReader) const override;
 	virtual void saveSuperItem(const Item* zItem, Framework::StreamWriter* zWriter) const override;
 	virtual void saveSuperItem(const Item* zItem, Framework::StreamWriter* zWriter) const override;
-	void initializeItem(LightSourceItem* zItem, int color, bool transparent = 1, bool passable = 1, float hp = 1, float maxHP = 1, float hardness = 0, int toolId = 0, float speedModifier = 1) const;
+	void initializeItem(LightSourceItem* zItem, int color, bool transparent = 1, bool passable = 1, float hardness = 0, int toolId = 0, float speedModifier = 1) const;
 };
 };
 
 
 class BasicLightSource : public Block
 class BasicLightSource : public Block

+ 42 - 37
FactoryCraft/Player.cpp

@@ -83,52 +83,57 @@ void Player::useItemSlot(ItemSlot* zSlot)
 		{
 		{
 			Item* item = stack->extractFromStack();
 			Item* item = stack->extractFromStack();
 			Entity::useItem(item->zItemType(), item);
 			Entity::useItem(item->zItemType(), item);
-			if (item->getDurability() > 0)
-			{ // put used item back
-				stack->addToStack(item);
-				if (!zSlot->numberOfAddableItems(stack, NO_DIRECTION))
-				{ // move other items to other space
-					ItemStack* oldItems = takeItemsOut(zSlot, zSlot->zStack()->getSize(), NO_DIRECTION);
-					addItems(zSlot, stack, NO_DIRECTION);
-					addItems(oldItems, NO_DIRECTION);
-					if (oldItems->getSize() > 0)
-					{
-						// TODO: drop remaining items
+			if (item->getHp() > 0)
+			{
+				if (item->getDurability() > 0)
+				{ // put used item back
+					stack->addToStack(item);
+					if (!zSlot->numberOfAddableItems(stack, NO_DIRECTION))
+					{ // move other items to other space
+						ItemStack* oldItems = takeItemsOut(zSlot, zSlot->zStack()->getSize(), NO_DIRECTION);
+						addItems(zSlot, stack, NO_DIRECTION);
+						addItems(oldItems, NO_DIRECTION);
+						if (oldItems->getSize() > 0)
+						{
+							// TODO: drop remaining items
+						}
 					}
 					}
+					else
+						addItems(zSlot, stack, NO_DIRECTION);
 				}
 				}
 				else
 				else
-					addItems(zSlot, stack, NO_DIRECTION);
-			}
-			else
-			{ // item is broken
-				// move other items of the same type to the slot
-				Array< ItemSlot*> fromSlots;
-				for (ItemSlot* slot : *this)
-				{
-					if (slot != zSlot)
-						fromSlots.add(slot);
-				}
-				Array<ItemSlot*> targetSlots;
-				targetSlots.add(zSlot);
-				TypeItemFilter filter(item->zItemType());
-				localTransaction(&fromSlots, &targetSlots, &filter, zSlot->getFreeSpace(), NO_DIRECTION, NO_DIRECTION);
-				// place broken item in inventory
-				const ItemType* brokenType = item->zItemType()->zBrokenItemType();
-				if (brokenType)
-				{
-					Item* broken = item->zItemType()->breakItem(item);
-					if (broken)
+				{ // item is broken
+					// move other items of the same type to the slot
+					Array< ItemSlot*> fromSlots;
+					for (ItemSlot* slot : *this)
 					{
 					{
-						stack->addToStack(broken);
-						addItems(stack, NO_DIRECTION);
-						if (stack->getSize() > 0)
+						if (slot != zSlot)
+							fromSlots.add(slot);
+					}
+					Array<ItemSlot*> targetSlots;
+					targetSlots.add(zSlot);
+					TypeItemFilter filter(item->zItemType());
+					localTransaction(&fromSlots, &targetSlots, &filter, zSlot->getFreeSpace(), NO_DIRECTION, NO_DIRECTION);
+					// place broken item in inventory
+					const ItemType* brokenType = item->zItemType()->zBrokenItemType();
+					if (brokenType)
+					{
+						Item* broken = item->zItemType()->breakItem(item);
+						if (broken)
 						{
 						{
-							// TODO: drop remaining items
+							stack->addToStack(broken);
+							addItems(stack, NO_DIRECTION);
+							if (stack->getSize() > 0)
+							{
+								// TODO: drop remaining items
+							}
 						}
 						}
 					}
 					}
+					item->release();
 				}
 				}
-				item->release();
 			}
 			}
+			else
+				item->release();
 			stack->release();
 			stack->release();
 		}
 		}
 	}
 	}

+ 9 - 5
FactoryCraft/Recipie.cpp

@@ -47,7 +47,10 @@ ShapedRecipie::ShapedRecipie(int width, int height)
 	outputAmount(0)
 	outputAmount(0)
 {
 {
 	for (int i = 0; i < width * height; i++)
 	for (int i = 0; i < width * height; i++)
+	{
 		filters.add(0);
 		filters.add(0);
+		modifiers.add(0);
+	}
 }
 }
 
 
 ShapedRecipie::~ShapedRecipie()
 ShapedRecipie::~ShapedRecipie()
@@ -56,9 +59,10 @@ ShapedRecipie::~ShapedRecipie()
 		output->release();
 		output->release();
 }
 }
 
 
-void ShapedRecipie::setIngredient(int x, int y, ItemFilter* filter)
+void ShapedRecipie::setIngredient(int x, int y, ItemFilter* filter, ItemModifier* modifier)
 {
 {
-	filters.set(filter, width * x + y);
+	filters.set(filter, width * y + x);
+	modifiers.set(modifier, width * y + x);
 }
 }
 
 
 void ShapedRecipie::setOutput(Item* item, int amount)
 void ShapedRecipie::setOutput(Item* item, int amount)
@@ -76,7 +80,7 @@ bool ShapedRecipie::testApplicability(ShapedCraftingStorage* zStorage)
 
 
 void ShapedRecipie::apply(ShapedCraftingStorage* zStorage)
 void ShapedRecipie::apply(ShapedCraftingStorage* zStorage)
 {
 {
-	zStorage->consume(filters, width, height);
+	zStorage->consume(filters, modifiers, width, height);
 	ItemStack* stack = new ItemStack(output->zItemType()->cloneItem(output), outputAmount);
 	ItemStack* stack = new ItemStack(output->zItemType()->cloneItem(output), outputAmount);
 	zStorage->addCraftingResult(stack);
 	zStorage->addCraftingResult(stack);
 	stack->release();
 	stack->release();
@@ -88,9 +92,9 @@ Framework::Array<ItemInfo> ShapedRecipie::getOutput(ShapedCraftingStorage* zStor
 	ItemInfo info;
 	ItemInfo info;
 	info.count = outputAmount;
 	info.count = outputAmount;
 	info.type = output->zItemType()->getId();
 	info.type = output->zItemType()->getId();
-	info.damage = output->getDamage();
+	info.hp = output->getHp();
 	info.durability = output->getDurability();
 	info.durability = output->getDurability();
-	info.maxDamage = output->getMaxDamage();
+	info.maxHp = output->getMaxHp();
 	info.maxDurability = output->getMaxDurability();
 	info.maxDurability = output->getMaxDurability();
 	result.add(info);
 	result.add(info);
 	return result;
 	return result;

+ 5 - 4
FactoryCraft/Recipie.h

@@ -3,7 +3,7 @@
 #include <JSON.h>
 #include <JSON.h>
 
 
 #include "ItemFilter.h"
 #include "ItemFilter.h"
-
+#include "ItemModifier.h"
 
 
 class CraftingStorage;
 class CraftingStorage;
 class ShapedCraftingStorage;
 class ShapedCraftingStorage;
@@ -12,8 +12,8 @@ struct ItemInfo
 {
 {
 	int type;
 	int type;
 	int count;
 	int count;
-	float damage;
-	float maxDamage;
+	float hp;
+	float maxHp;
 	float durability;
 	float durability;
 	float maxDurability;
 	float maxDurability;
 };
 };
@@ -38,6 +38,7 @@ class ShapedRecipie : public virtual Framework::ReferenceCounter
 {
 {
 private:
 private:
 	Framework::RCArray<ItemFilter> filters;
 	Framework::RCArray<ItemFilter> filters;
+	Framework::RCArray<ItemModifier> modifiers;
 	int width;
 	int width;
 	int height;
 	int height;
 	Item* output;
 	Item* output;
@@ -46,7 +47,7 @@ private:
 public:
 public:
 	ShapedRecipie(int width, int height);
 	ShapedRecipie(int width, int height);
 	~ShapedRecipie();
 	~ShapedRecipie();
-	void setIngredient(int x, int y, ItemFilter* filter);
+	void setIngredient(int x, int y, ItemFilter* filter, ItemModifier* modifier);
 	void setOutput(Item* item, int amount);
 	void setOutput(Item* item, int amount);
 	bool testApplicability(ShapedCraftingStorage* zStorage);
 	bool testApplicability(ShapedCraftingStorage* zStorage);
 	void apply(ShapedCraftingStorage* zStorage);
 	void apply(ShapedCraftingStorage* zStorage);

+ 17 - 1
FactoryCraft/RecipieLoader.cpp

@@ -61,7 +61,10 @@ void RecipieLoader::loadRecipie(JSONObject* zRecipie)
 			int x = (int)input->asObject()->zValue("x")->asNumber()->getNumber();
 			int x = (int)input->asObject()->zValue("x")->asNumber()->getNumber();
 			int y = (int)input->asObject()->zValue("y")->asNumber()->getNumber();
 			int y = (int)input->asObject()->zValue("y")->asNumber()->getNumber();
 			ItemFilter* filter = loadFilter(input->asObject()->zValue("filter")->asObject());
 			ItemFilter* filter = loadFilter(input->asObject()->zValue("filter")->asObject());
-			recipie->setIngredient(x, y, filter);
+			CombinedItemModifier* resultingModifier = new CombinedItemModifier();
+			for (JSONValue* modifier : *input->asObject()->zValue("modifiers")->asArray())
+				resultingModifier->addModifier(loadModifier(modifier->asObject()));
+			recipie->setIngredient(x, y, filter, resultingModifier);
 		}
 		}
 		int outputCount = (int)zRecipie->asObject()->zValue("outputCount")->asNumber()->getNumber();
 		int outputCount = (int)zRecipie->asObject()->zValue("outputCount")->asNumber()->getNumber();
 		Framework::Text outputType = zRecipie->asObject()->zValue("output")->asObject()->zValue("itemType")->asString()->getString();
 		Framework::Text outputType = zRecipie->asObject()->zValue("output")->asObject()->zValue("itemType")->asString()->getString();
@@ -154,6 +157,11 @@ void RecipieLoader::registerShapedRecipieList(const char* name)
 	shapedLists.add(new ShapedRecipieList(name));
 	shapedLists.add(new ShapedRecipieList(name));
 }
 }
 
 
+ItemModifier* RecipieLoader::loadModifier(Framework::JSON::JSONObject* zModifier)
+{
+	return new AttributeItemModifier(zModifier->zValue("attribute")->asString()->getString(), zModifier->zValue("value")->asString()->getString());
+}
+
 JSONValidator* RecipieLoader::zRecipieValidator()
 JSONValidator* RecipieLoader::zRecipieValidator()
 {
 {
 	if (validator)
 	if (validator)
@@ -183,6 +191,14 @@ JSONValidator* RecipieLoader::zRecipieValidator()
 					->withRequiredNumber("x")->whichIsGreaterOrEqual(0)->finishNumber()
 					->withRequiredNumber("x")->whichIsGreaterOrEqual(0)->finishNumber()
 					->withRequiredNumber("y")->whichIsGreaterOrEqual(0)->finishNumber()
 					->withRequiredNumber("y")->whichIsGreaterOrEqual(0)->finishNumber()
 					->withRequiredAttribute("filter", dynamic_cast<JSONValidator*>(filterValidator->getThis()))
 					->withRequiredAttribute("filter", dynamic_cast<JSONValidator*>(filterValidator->getThis()))
+					->withRequiredAttribute("modifiers",
+						JSONValidator::buildForArray()
+						->withDefault(Parser::getValue("[{\"attribute\": \"hp\", \"value\": \"=0\"}]")->asArray())
+						->addAcceptedTypeInArray(JSONValidator::buildForObject()
+							->withRequiredString("attribute")->finishString()
+							->withRequiredString("value")->finishString()
+							->finishObject())
+						->finishArray())
 					->finishObject())
 					->finishObject())
 				->finishArray())
 				->finishArray())
 			->withRequiredAttribute("output", dynamic_cast<JSONValidator*>(outputValidator->getThis()))
 			->withRequiredAttribute("output", dynamic_cast<JSONValidator*>(outputValidator->getThis()))

+ 1 - 0
FactoryCraft/RecipieLoader.h

@@ -21,5 +21,6 @@ public:
 private:
 private:
 	void loadRecipie(Framework::JSON::JSONObject* zRecipie);
 	void loadRecipie(Framework::JSON::JSONObject* zRecipie);
 	ItemFilter* loadFilter(Framework::JSON::JSONObject* zFilter);
 	ItemFilter* loadFilter(Framework::JSON::JSONObject* zFilter);
+	ItemModifier* loadModifier(Framework::JSON::JSONObject* zModifier);
 	Framework::JSON::Validator::JSONValidator* zRecipieValidator();
 	Framework::JSON::Validator::JSONValidator* zRecipieValidator();
 };
 };

+ 3 - 2
FactoryCraft/StoneTool.cpp

@@ -8,7 +8,7 @@ BrokenStoneToolItemType::BrokenStoneToolItemType()
 
 
 Item* BrokenStoneToolItemType::createItem() const
 Item* BrokenStoneToolItemType::createItem() const
 {
 {
-	return createBasicItem("Stone Tool", 0.f, 0.f, 0.f, 0.f, 0, 0, 0, 1, 0, 10);
+	return createBasicItem("Stone Tool", 100.f, 100.f, 100.f, 100.f, 0, 0, 0, 1, 0, 10);
 }
 }
 
 
 
 
@@ -38,7 +38,7 @@ void StoneToolItemType::saveSuperItemSkill(const ItemSkill* zSkill, Framework::S
 
 
 Item* StoneToolItemType::createItem() const
 Item* StoneToolItemType::createItem() const
 {
 {
-	return createBasicItem("Stone Tool", 0.f, 0.f, 10.f, 10.f, 0, 0, 0, 1, 1, 1);
+	return createBasicItem("Stone Tool", 100.f, 100.f, 100.f, 100.f, 0, 0, 0, 1, 1, 1);
 }
 }
 
 
 ItemSkill* StoneToolItemType::createDefaultItemSkill() const
 ItemSkill* StoneToolItemType::createDefaultItemSkill() const
@@ -80,6 +80,7 @@ void StoneToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
 		float damage = (1 + ((float)level / 10.f)) / (zTarget->getHardness() + 1);
 		float damage = (1 + ((float)level / 10.f)) / (zTarget->getHardness() + 1);
 		zTarget->setHP(zTarget->getHP() - damage);
 		zTarget->setHP(zTarget->getHP() - damage);
 		xp += damage / 20;
 		xp += damage / 20;
+		zUsedItem->setHp(zUsedItem->getHp() - damage / 50);
 	}
 	}
 }
 }
 
 

+ 18 - 6
FactoryCraft/WormCaveGenerator.cpp

@@ -23,12 +23,12 @@ NoiseWorm3D::NoiseWorm3D(Noise* pitch, Noise* yaw, Noise* size, Framework::Vec3<
 			defaultDir = keyPoints.get(keyPoints.getEintragAnzahl() - 1) - keyPoints.get(keyPoints.getEintragAnzahl() - 2);
 			defaultDir = keyPoints.get(keyPoints.getEintragAnzahl() - 1) - keyPoints.get(keyPoints.getEintragAnzahl() - 2);
 		}
 		}
 		float n = (float)yaw->getNoise(lastPos.x, lastPos.y, lastPos.z);
 		float n = (float)yaw->getNoise(lastPos.x, lastPos.y, lastPos.z);
-		defaultDir.rotateZ((n - 0.5) / 2.f);
+		defaultDir.rotateZ((n - 0.5f) / 2.f);
 		defaultDir.normalize();
 		defaultDir.normalize();
 		n = (float)pitch->getNoise(lastPos.x, lastPos.y, lastPos.z);
 		n = (float)pitch->getNoise(lastPos.x, lastPos.y, lastPos.z);
 		defaultDir.z = ((float)n - 0.3f) * 2.f;
 		defaultDir.z = ((float)n - 0.3f) * 2.f;
 		lastPos = lastPos + defaultDir;
 		lastPos = lastPos + defaultDir;
-		if ((Vec2<float>(lastPos.x, lastPos.y) - (Vec2<float>((float)startPos.x, (float)startPos.y))).getLengthSq() >= distant * distant)
+		if ((Vec2<float>(lastPos.x, lastPos.y) - (Vec2<float>((float)startPos.x, (float)startPos.y))).getLengthSq() >= (float)(distant * distant))
 			break;
 			break;
 		keyPoints.add(lastPos);
 		keyPoints.add(lastPos);
 		float rad = (float)size->getNoise(lastPos.x, lastPos.y, lastPos.z) * (float)(maxRad - minRad) + (float)minRad;
 		float rad = (float)size->getNoise(lastPos.x, lastPos.y, lastPos.z) * (float)(maxRad - minRad) + (float)minRad;
@@ -47,7 +47,19 @@ Framework::Punkt NoiseWorm3D::getStartChunkCenter()
 
 
 bool NoiseWorm3D::isChunkAffected(int x, int y)
 bool NoiseWorm3D::isChunkAffected(int x, int y)
 {
 {
-	return x - CHUNK_SIZE / 2 <= maxAffected.x && x + CHUNK_SIZE / 2 >= minAffected.x && y - CHUNK_SIZE / 2 <= maxAffected.y && y + CHUNK_SIZE / 2 >= minAffected.y;
+	if (x - CHUNK_SIZE / 2 <= maxAffected.x && x + CHUNK_SIZE / 2 >= minAffected.x && y - CHUNK_SIZE / 2 <= maxAffected.y && y + CHUNK_SIZE / 2 >= minAffected.y)
+	{
+		auto pi = keyPoints.begin();
+		auto si = size.begin();
+		while (pi && si)
+		{
+			if ((Vec2<float>((float)x, (float)y) - Vec2<float>(pi.val().x, pi.val().y)).getLengthSq() < (si.val() + CHUNK_SIZE / 2) * (si.val() + CHUNK_SIZE / 2))
+				return 1;
+			++pi;
+			++si;
+		}
+	}
+	return 0;
 }
 }
 
 
 bool NoiseWorm3D::isInside(int x, int y, int z)
 bool NoiseWorm3D::isInside(int x, int y, int z)
@@ -109,7 +121,7 @@ NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
 		if (p.x == x && p.y == y)
 		if (p.x == x && p.y == y)
 			return 0;
 			return 0;
 	}
 	}
-	float cNoise = wormStartNoise->getNoise(x, y, 0);
+	float cNoise = (float)wormStartNoise->getNoise(x, y, 0);
 	if (cNoise < cavePosibillity)
 	if (cNoise < cavePosibillity)
 	{
 	{
 		FastNoiseLite* noise = new FastNoiseLite(seed + x * y + y + x);
 		FastNoiseLite* noise = new FastNoiseLite(seed + x * y + y + x);
@@ -121,9 +133,9 @@ NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
 		noise->SetFrequency(0.005f);
 		noise->SetFrequency(0.005f);
 		FastNoiseWrapper* yaw = new FastNoiseWrapper(noise, seed - x * y - y - x);
 		FastNoiseWrapper* yaw = new FastNoiseWrapper(noise, seed - x * y - y - x);
 		Vec3<int> start((int)(cNoise / cavePosibillity * CHUNK_SIZE) + x - CHUNK_SIZE / 2, (int)(cNoise / cavePosibillity * CHUNK_SIZE) + y - CHUNK_SIZE / 2, (int)(cNoise / cavePosibillity * 200));
 		Vec3<int> start((int)(cNoise / cavePosibillity * CHUNK_SIZE) + x - CHUNK_SIZE / 2, (int)(cNoise / cavePosibillity * CHUNK_SIZE) + y - CHUNK_SIZE / 2, (int)(cNoise / cavePosibillity * 200));
-		noise = new FastNoiseLite(seed + x * y - y + x);
+		noise = new FastNoiseLite(seed + start.getLengthSq() + start.x + start.y + start.z);
 		noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
 		noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
-		noise->SetFrequency(0.05f);
+		noise->SetFrequency(0.005f);
 		FastNoiseWrapper* size = new FastNoiseWrapper(noise, seed + start.getLengthSq() + start.x + start.y + start.z);
 		FastNoiseWrapper* size = new FastNoiseWrapper(noise, seed + start.getLengthSq() + start.x + start.y + start.z);
 		NoiseWorm3D* worm = new NoiseWorm3D(pitch, yaw, size, start, (int)(wormStartNoise->getNoise(start.x, start.y, start.z) * (maxDistant - minDistant) + minDistant), minRadius, maxRadius);
 		NoiseWorm3D* worm = new NoiseWorm3D(pitch, yaw, size, start, (int)(wormStartNoise->getNoise(start.x, start.y, start.z) * (maxDistant - minDistant) + minDistant), minRadius, maxRadius);
 		if (cache.getEintragAnzahl() > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
 		if (cache.getEintragAnzahl() > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)