diff --git a/README.md b/README.md
index 7a1a2bd4..fff99ed8 100644
--- a/README.md
+++ b/README.md
@@ -83,8 +83,6 @@ graph TD;
     - [ ] implement bonus gained by class
     - [ ] implement magic, resist, ... stats
 
-- [ ] armor sets
-
 - [ ] crafting feature
 
 - [ ] credits
@@ -94,6 +92,7 @@ graph TD;
 -------
 ## Bugs
 
+- Objects in inventory are stacking even if there are not the same
 - FadeIn effect not working when transition [menu → game]
 - Drag and drop selection issue on item's render (items are far from mouse when picking them)
 - Sometimes current hp/mp on status HUD add a blank space before the max player's hp/mp
diff --git a/core/src/main/java/com/gdx/game/battle/BattleHUD.java b/core/src/main/java/com/gdx/game/battle/BattleHUD.java
index 901a90cf..974b4f78 100644
--- a/core/src/main/java/com/gdx/game/battle/BattleHUD.java
+++ b/core/src/main/java/com/gdx/game/battle/BattleHUD.java
@@ -24,8 +24,8 @@
 import com.gdx.game.entities.player.characterClass.ClassObserver;
 import com.gdx.game.entities.player.characterClass.tree.Node;
 import com.gdx.game.entities.player.characterClass.tree.Tree;
-import com.gdx.game.inventory.InventoryItem;
-import com.gdx.game.inventory.InventoryItemLocation;
+import com.gdx.game.inventory.item.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItemLocation;
 import com.gdx.game.inventory.InventoryObserver;
 import com.gdx.game.manager.ResourceManager;
 import com.gdx.game.map.MapManager;
diff --git a/core/src/main/java/com/gdx/game/battle/BattleInventoryUI.java b/core/src/main/java/com/gdx/game/battle/BattleInventoryUI.java
index 8c531320..045ada38 100644
--- a/core/src/main/java/com/gdx/game/battle/BattleInventoryUI.java
+++ b/core/src/main/java/com/gdx/game/battle/BattleInventoryUI.java
@@ -8,10 +8,9 @@
 import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop;
 import com.badlogic.gdx.utils.Array;
-import com.gdx.game.entities.Entity;
-import com.gdx.game.inventory.InventoryItem;
-import com.gdx.game.inventory.InventoryItemFactory;
-import com.gdx.game.inventory.InventoryItemLocation;
+import com.gdx.game.inventory.item.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItemFactory;
+import com.gdx.game.inventory.item.InventoryItemLocation;
 import com.gdx.game.inventory.InventoryObserver;
 import com.gdx.game.inventory.InventorySubject;
 import com.gdx.game.inventory.slot.InventorySlot;
diff --git a/core/src/main/java/com/gdx/game/battle/BattleState.java b/core/src/main/java/com/gdx/game/battle/BattleState.java
index c3145eb0..9233cb6b 100644
--- a/core/src/main/java/com/gdx/game/battle/BattleState.java
+++ b/core/src/main/java/com/gdx/game/battle/BattleState.java
@@ -10,6 +10,12 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.gdx.game.common.UtilityClass.calculateBonus;
+
 public class BattleState extends BattleSubject {
     private static final Logger LOGGER = LoggerFactory.getLogger(BattleState.class);
 
@@ -35,6 +41,8 @@ public BattleState() {
 
         currentPlayerAP = ProfileManager.getInstance().getProperty("currentPlayerAP", Integer.class);
         currentPlayerDP = ProfileManager.getInstance().getProperty("currentPlayerDP", Integer.class);
+
+        updateStatWithBonus("bonusSet");
     }
 
     public void resetDefaults() {
@@ -82,6 +90,27 @@ public void determineTurn() {
         Timer.schedule(determineTurn, 1);
     }
 
+    private void updateStatWithBonus(String bonusAttribute) {
+        HashMap<String, Integer> bonusMap = calculateBonus(bonusAttribute);
+        Map<String, String> mapping = Map.of(
+                EntityConfig.EntityProperties.ENTITY_PHYSICAL_ATTACK_POINTS.name(), "currentPlayerAP",
+                EntityConfig.EntityProperties.ENTITY_PHYSICAL_DEFENSE_POINTS.name(), "currentPlayerDP"
+        );
+
+        mapping.forEach((key, value) -> {
+            if (bonusMap.get(key) != null) {
+                try {
+                    Field valueField = this.getClass().getDeclaredField(value);
+                    int currentPlayerValue = valueField.getInt(this);
+                    int newPlayerValue = currentPlayerValue + bonusMap.get(key);
+                    valueField.setInt(this, newPlayerValue);
+                } catch (NoSuchFieldException | IllegalAccessException e) {
+                    throw new RuntimeException("A value in the mapping map does not exist", e);
+                }
+            }
+        });
+    }
+
     public void playerAttacks() {
         if (currentOpponent == null) {
             return;
diff --git a/core/src/main/java/com/gdx/game/common/UtilityClass.java b/core/src/main/java/com/gdx/game/common/UtilityClass.java
index fc92c3eb..ef508bc6 100644
--- a/core/src/main/java/com/gdx/game/common/UtilityClass.java
+++ b/core/src/main/java/com/gdx/game/common/UtilityClass.java
@@ -1,8 +1,16 @@
 package com.gdx.game.common;
 
+import com.badlogic.gdx.utils.Array;
+import com.gdx.game.entities.EntityBonus;
+import com.gdx.game.entities.EntityConfig;
+import com.gdx.game.profile.ProfileManager;
+
 import java.util.HashMap;
+import java.util.Hashtable;
 import java.util.Map;
 
+import static java.lang.Float.parseFloat;
+
 public class UtilityClass {
 
     public static <T, E> HashMap<E, T> mapInverter(HashMap<T, E> hashMap){
@@ -27,4 +35,36 @@ public static <T, E> Map<E, T> mapInverter(Map<T, E> hashMap){
         return newMap;
     }
 
+    public static HashMap<String, Integer> calculateBonus(String bonusProperty) {
+        final Hashtable<String, String> attributeTable = new Hashtable<>() {{
+            put(EntityConfig.EntityProperties.ENTITY_PHYSICAL_ATTACK_POINTS.name(), "currentPlayerAP");
+            put(EntityConfig.EntityProperties.ENTITY_PHYSICAL_DEFENSE_POINTS.name(), "currentPlayerDP");
+        }};
+
+        HashMap<String, Integer> bonusStatMap = new HashMap<>();
+        Array<EntityBonus> bonusArray = ProfileManager.getInstance().getProperty(bonusProperty, Array.class);
+
+        if (bonusArray == null || bonusArray.isEmpty()) {
+            return bonusStatMap;
+        }
+
+        HashMap<String, String> bonusEntityValues = new HashMap<>();
+        for (EntityBonus entityBonus : bonusArray) {
+            bonusEntityValues.put(entityBonus.getEntityProperty(), entityBonus.getValue());
+        }
+
+        for (String key : attributeTable.keySet()) {
+            float bonusValue = parseFloat(bonusEntityValues.get(key));
+            if (bonusValue > 1) {
+                bonusStatMap.put(key, (int) bonusValue);
+            } else {
+                int playerStat = ProfileManager.getInstance().getProperty(attributeTable.get(key), Integer.class);
+                int bonusStat = (int) Math.floor(playerStat * bonusValue);
+                bonusStatMap.put(key, bonusStat);
+            }
+        }
+
+        return bonusStatMap;
+    }
+
 }
diff --git a/core/src/main/java/com/gdx/game/entities/EntityBonus.java b/core/src/main/java/com/gdx/game/entities/EntityBonus.java
new file mode 100644
index 00000000..3faaa0d1
--- /dev/null
+++ b/core/src/main/java/com/gdx/game/entities/EntityBonus.java
@@ -0,0 +1,31 @@
+package com.gdx.game.entities;
+
+public class EntityBonus {
+
+    private String entityProperty;
+    private String value;
+
+    public EntityBonus() {
+    }
+
+    public EntityBonus(String entityProperty, String value) {
+        this.entityProperty = entityProperty;
+        this.value = value;
+    }
+
+    public String getEntityProperty() {
+        return entityProperty;
+    }
+
+    public void setEntityProperty(String entityProperty) {
+        this.entityProperty = entityProperty;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+}
diff --git a/core/src/main/java/com/gdx/game/entities/EntityConfig.java b/core/src/main/java/com/gdx/game/entities/EntityConfig.java
index af9eaf6b..46120cd6 100644
--- a/core/src/main/java/com/gdx/game/entities/EntityConfig.java
+++ b/core/src/main/java/com/gdx/game/entities/EntityConfig.java
@@ -3,7 +3,7 @@
 import com.badlogic.gdx.math.GridPoint2;
 import com.badlogic.gdx.utils.Array;
 import com.badlogic.gdx.utils.ObjectMap;
-import com.gdx.game.inventory.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItem;
 
 public class EntityConfig {
     private Array<AnimationConfig> animationConfig;
diff --git a/core/src/main/java/com/gdx/game/entities/player/PlayerHUD.java b/core/src/main/java/com/gdx/game/entities/player/PlayerHUD.java
index ab72412c..261e1ef9 100644
--- a/core/src/main/java/com/gdx/game/entities/player/PlayerHUD.java
+++ b/core/src/main/java/com/gdx/game/entities/player/PlayerHUD.java
@@ -32,10 +32,11 @@
 import com.gdx.game.entities.player.characterClass.ClassObserver;
 import com.gdx.game.entities.player.characterClass.tree.Node;
 import com.gdx.game.entities.player.characterClass.tree.Tree;
-import com.gdx.game.inventory.InventoryItem;
-import com.gdx.game.inventory.InventoryItemLocation;
 import com.gdx.game.inventory.InventoryObserver;
 import com.gdx.game.inventory.InventoryUI;
+import com.gdx.game.inventory.item.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItemLocation;
+import com.gdx.game.inventory.slot.InventorySlot;
 import com.gdx.game.inventory.store.StoreInventoryObserver;
 import com.gdx.game.inventory.store.StoreInventoryUI;
 import com.gdx.game.manager.ResourceManager;
@@ -48,6 +49,9 @@
 import com.gdx.game.status.StatusObserver;
 import com.gdx.game.status.StatusUI;
 
+import static com.gdx.game.inventory.InventoryUI.getInventory;
+import static com.gdx.game.inventory.InventoryUI.setBonusFromSet;
+
 public class PlayerHUD implements Screen, AudioSubject, ProfileObserver, ClassObserver, ComponentObserver, ConversationGraphObserver, BattleObserver, StoreInventoryObserver, InventoryObserver, StatusObserver {
 
     private Stage stage;
@@ -282,7 +286,7 @@ public void onNotify(ProfileManager profileManager, ProfileEvent event) {
                         itemLocations.add(new InventoryItemLocation(i, items.get(i).toString(), 1, InventoryUI.PLAYER_INVENTORY));
                     }
                     InventoryUI.populateInventory(inventoryUI.getInventorySlotTable(), itemLocations, inventoryUI.getDragAndDrop(), InventoryUI.PLAYER_INVENTORY, false);
-                    profileManager.setProperty("playerInventory", InventoryUI.getInventory(inventoryUI.getInventorySlotTable()));
+                    profileManager.setProperty("playerInventory", getInventory(inventoryUI.getInventorySlotTable()));
 
                     //start the player with some money
                     statusUI.setGoldValue(20);
@@ -297,6 +301,9 @@ public void onNotify(ProfileManager profileManager, ProfileEvent event) {
                     inventoryUI.resetEquipSlots();
                     if (equipInventory != null && equipInventory.size > 0) {
                         InventoryUI.populateInventory(inventoryUI.getEquipSlotTable(), equipInventory, inventoryUI.getDragAndDrop(), InventoryUI.PLAYER_INVENTORY, false);
+                        if (inventoryUI.isSetEquipped(equipInventory)) {
+                            setBonusFromSet(((InventorySlot) inventoryUI.getEquipSlotTable().getCells().get(1).getActor()).getTopInventoryItem());
+                        }
                     }
 
                     Array<QuestGraph> quests = profileManager.getProperty("playerQuests", Array.class);
@@ -329,8 +336,8 @@ public void onNotify(ProfileManager profileManager, ProfileEvent event) {
             }
             case SAVING_PROFILE -> {
                 profileManager.setProperty("playerQuests", questUI.getQuests());
-                profileManager.setProperty("playerInventory", InventoryUI.getInventory(inventoryUI.getInventorySlotTable()));
-                profileManager.setProperty("playerEquipInventory", InventoryUI.getInventory(inventoryUI.getEquipSlotTable()));
+                profileManager.setProperty("playerInventory", getInventory(inventoryUI.getInventorySlotTable()));
+                profileManager.setProperty("playerEquipInventory", getInventory(inventoryUI.getEquipSlotTable()));
                 if (mapManager.getPlayer() != null) {
                     profileManager.setProperty("playerCharacter", EntityFactory.EntityType.valueOf(mapManager.getPlayer().getEntityConfig().getEntityID()));
                 }
@@ -344,8 +351,6 @@ public void onNotify(ProfileManager profileManager, ProfileEvent event) {
                 profileManager.setProperty("currentPlayerHPMax", statusUI.getHPValueMax());
                 profileManager.setProperty("currentPlayerMP", statusUI.getMPValue());
                 profileManager.setProperty("currentPlayerMPMax", statusUI.getMPValueMax());
-                profileManager.setProperty("currentPlayerAP", inventoryUI.getAPVal());
-                profileManager.setProperty("currentPlayerDP", inventoryUI.getDPVal());
                 profileManager.setProperty("currentPlayerSPDP", inventoryUI.getSPDPVal());
             }
             case CLEAR_CURRENT_PROFILE -> {
@@ -364,6 +369,7 @@ public void onNotify(ProfileManager profileManager, ProfileEvent event) {
                 profileManager.setProperty("currentPlayerDP", 0);
                 profileManager.setProperty("currentPlayerSPDP", 0);
                 profileManager.setProperty("currentTime", 0);
+                profileManager.setProperty("bonusSet", null);
             }
             default -> {
             }
@@ -421,7 +427,7 @@ public void onNotify(ConversationGraph graph, ConversationCommandEvent event) {
                     break;
                 }
 
-                Array<InventoryItemLocation> inventory =  InventoryUI.getInventory(inventoryUI.getInventorySlotTable());
+                Array<InventoryItemLocation> inventory =  getInventory(inventoryUI.getInventorySlotTable());
                 storeInventoryUI.loadPlayerInventory(inventory);
 
                 Array<InventoryItem.ItemTypeID> items  = selectedEntity.getEntityConfig().getInventory();
diff --git a/core/src/main/java/com/gdx/game/entities/player/characterClass/tree/Tree.java b/core/src/main/java/com/gdx/game/entities/player/characterClass/tree/Tree.java
index eae27891..c06f16be 100644
--- a/core/src/main/java/com/gdx/game/entities/player/characterClass/tree/Tree.java
+++ b/core/src/main/java/com/gdx/game/entities/player/characterClass/tree/Tree.java
@@ -2,6 +2,7 @@
 
 import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.utils.Json;
+import com.gdx.game.entities.EntityConfig;
 import com.gdx.game.profile.ProfileManager;
 
 import java.util.*;
@@ -112,10 +113,10 @@ public Node checkForClassUpgrade(String currentClassId, int currentPlayerCharact
         List<Node> nodes = findToWhichClassesUpgrade(currentClassId);
 
         if (nodes != null && nodes.size() == 2) {
-            int AP0 = Integer.parseInt(nodes.get(0).getRequirements().get("ENTITY_PHYSICAL_ATTACK_POINTS"));
-            int DP0 = Integer.parseInt(nodes.get(0).getRequirements().get("ENTITY_PHYSICAL_DEFENSE_POINTS"));
-            int AP1 = Integer.parseInt(nodes.get(1).getRequirements().get("ENTITY_PHYSICAL_ATTACK_POINTS"));
-            int DP1 = Integer.parseInt(nodes.get(1).getRequirements().get("ENTITY_PHYSICAL_DEFENSE_POINTS"));
+            int AP0 = Integer.parseInt(nodes.get(0).getRequirements().get(EntityConfig.EntityProperties.ENTITY_PHYSICAL_ATTACK_POINTS.name()));
+            int DP0 = Integer.parseInt(nodes.get(0).getRequirements().get(EntityConfig.EntityProperties.ENTITY_PHYSICAL_DEFENSE_POINTS.name()));
+            int AP1 = Integer.parseInt(nodes.get(1).getRequirements().get(EntityConfig.EntityProperties.ENTITY_PHYSICAL_ATTACK_POINTS.name()));
+            int DP1 = Integer.parseInt(nodes.get(1).getRequirements().get(EntityConfig.EntityProperties.ENTITY_PHYSICAL_DEFENSE_POINTS.name()));
 
             if (currentPlayerCharacterAP >= AP0 && currentPlayerCharacterDP >= DP0) {
                 return nodes.get(0);
diff --git a/core/src/main/java/com/gdx/game/inventory/InventoryUI.java b/core/src/main/java/com/gdx/game/inventory/InventoryUI.java
index fa48f3d9..92030d0b 100644
--- a/core/src/main/java/com/gdx/game/inventory/InventoryUI.java
+++ b/core/src/main/java/com/gdx/game/inventory/InventoryUI.java
@@ -12,7 +12,13 @@
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop;
 import com.badlogic.gdx.utils.Align;
 import com.badlogic.gdx.utils.Array;
-import com.gdx.game.entities.Entity;
+import com.gdx.game.entities.EntityBonus;
+import com.gdx.game.entities.EntityConfig;
+import com.gdx.game.inventory.item.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItemFactory;
+import com.gdx.game.inventory.item.InventoryItemLocation;
+import com.gdx.game.inventory.set.EquipmentSet;
+import com.gdx.game.inventory.set.EquipmentSetFactory;
 import com.gdx.game.inventory.slot.InventorySlot;
 import com.gdx.game.inventory.slot.InventorySlotObserver;
 import com.gdx.game.inventory.slot.InventorySlotSource;
@@ -22,6 +28,11 @@
 import com.gdx.game.manager.ResourceManager;
 import com.gdx.game.profile.ProfileManager;
 
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.gdx.game.common.UtilityClass.calculateBonus;
 import static com.gdx.game.component.Component.MESSAGE_TOKEN;
 import static com.gdx.game.manager.ResourceManager.ITEMS_TEXTURE_ATLAS;
 import static com.gdx.game.manager.ResourceManager.STATUS_UI_TEXTURE_ATLAS;
@@ -39,6 +50,8 @@ public class InventoryUI extends Window implements InventorySubject, InventorySl
 
     private Label classValLabel;
     private String classVal;
+    private Label setValLabel;
+    private String setVal;
     private Label DPValLabel;
     private int DPVal;
     private Label APValLabel;
@@ -80,6 +93,9 @@ public InventoryUI() {
         Label classLabel = new Label("Class: ", ResourceManager.skin);
         classValLabel = new Label(classVal, ResourceManager.skin);
 
+        Label setLabel = new Label("Set: ", ResourceManager.skin);
+        setValLabel = new Label(setVal, ResourceManager.skin);
+
         Label DPLabel = new Label("Defense: ", ResourceManager.skin);
         DPValLabel = new Label(String.valueOf(DPVal), ResourceManager.skin);
 
@@ -93,6 +109,10 @@ public InventoryUI() {
         labelTable.add(classLabel).align(Align.left);
         labelTable.add(classValLabel).align(Align.center);
         labelTable.row();
+        labelTable.add(setLabel).align(Align.left);
+        labelTable.add(setValLabel).align(Align.center);
+        labelTable.row();
+        labelTable.row();
         labelTable.row();
         labelTable.add(DPLabel).align(Align.left);
         labelTable.add(DPValLabel).align(Align.center);
@@ -231,12 +251,14 @@ public void touchUp (InputEvent event, float x, float y, int pointer, int button
     }
 
     public void resetEquipSlots() {
+        ProfileManager.getInstance().setProperty("bonusSet", null);
         classVal = ProfileManager.getInstance().getProperty("characterClass", String.class);
         APVal = ProfileManager.getInstance().getProperty("currentPlayerCharacterAP", Integer.class);
         DPVal = ProfileManager.getInstance().getProperty("currentPlayerCharacterDP", Integer.class);
         SPDPVal = ProfileManager.getInstance().getProperty("currentPlayerCharacterSPDP", Integer.class);
 
         classValLabel.setText(String.valueOf(classVal));
+        setValLabel.setText("");
 
         DPValLabel.setText(String.valueOf(DPVal));
         notify(String.valueOf(DPVal), InventoryObserver.InventoryEvent.UPDATED_DP);
@@ -455,6 +477,65 @@ public Array<Actor> getInventoryActors() {
         return inventoryActors;
     }
 
+    public boolean isSetEquipped(Array<InventoryItemLocation> equipItems) {
+        if (equipItems.isEmpty() || equipItems.size != 5) {
+            return false;
+        }
+
+        InventoryItem firstItem = InventoryItemFactory.getInstance().getInventoryItem(InventoryItem.ItemTypeID.valueOf(equipItems.get(0).getItemTypeAtLocation()));
+        String firstItemSetID = firstItem.getItemSetID().name();
+
+        for (int i = 1; i < equipItems.size - 1; i++) {
+            InventoryItem currentItem = InventoryItemFactory.getInstance().getInventoryItem(InventoryItem.ItemTypeID.valueOf(equipItems.get(i).getItemTypeAtLocation()));
+            String currentItemSetID = String.valueOf(currentItem.getItemSetID());
+            if (!firstItemSetID.equals(currentItemSetID)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static void setBonusFromSet(InventoryItem item) {
+        EquipmentSet set = EquipmentSetFactory.getInstance().getEquipmentSet(item.getItemSetID());
+        HashMap<String, String> bonusMap = set.getBonus();
+        Array<EntityBonus> bonusArray = new Array<>();
+
+        for (Map.Entry<String, String> entry : bonusMap.entrySet()) {
+            EntityBonus entityBonus = new EntityBonus(entry.getKey(), entry.getValue());
+            bonusArray.add(entityBonus);
+        }
+
+        ProfileManager.getInstance().setProperty("bonusSet", bonusArray);
+    }
+
+    private void updateValuesWithBonus(String bonusAttribute, boolean isAdd) {
+        HashMap<String, Integer> bonusMap = calculateBonus(bonusAttribute);
+
+        Map<String, String[]> updates = Map.of(
+                EntityConfig.EntityProperties.ENTITY_PHYSICAL_ATTACK_POINTS.name(), new String[]{"APVal", "APValLabel"},
+                EntityConfig.EntityProperties.ENTITY_PHYSICAL_DEFENSE_POINTS.name(), new String[]{"DPVal", "DPValLabel"}
+        );
+
+        updates.forEach((key, fields) -> {
+            Integer value = bonusMap.get(key);
+            if (value != null) {
+                try {
+                    Field propertyField = this.getClass().getDeclaredField(fields[0]);
+                    Field labelField = this.getClass().getDeclaredField(fields[1]);
+
+                    int currentValue = propertyField.getInt(this);
+                    int newValue = isAdd ? currentValue + value : currentValue - value;
+                    propertyField.setInt(this, newValue);
+
+                    Label label = (Label) labelField.get(this);
+                    label.setText(String.valueOf(newValue));
+                } catch (NoSuchFieldException | IllegalAccessException e) {
+                    throw new RuntimeException("A value in the update stat map does not exist", e);
+                }
+            }
+        });
+    }
+
     @Override
     public void onNotify(InventorySlot slot, SlotEvent event) {
         switch (event) {
@@ -463,6 +544,13 @@ public void onNotify(InventorySlot slot, SlotEvent event) {
                 if (addItem == null) {
                     return;
                 }
+                boolean isSetEquipped = isSetEquipped(getInventory(equipSlots));
+                if (!isSetEquipped) {
+                    setValLabel.setText("");
+                    updateValuesWithBonus("bonusSet", false);
+                    ProfileManager.getInstance().setProperty("bonusSet", null);
+                }
+
                 if (addItem.isInventoryItemOffensive()) {
                     APVal += addItem.getItemUseTypeValue();
                     APValLabel.setText(String.valueOf(APVal));
@@ -481,12 +569,21 @@ public void onNotify(InventorySlot slot, SlotEvent event) {
 
                     ProfileManager.getInstance().setProperty("currentPlayerDP", DPVal);
                 }
+                if (isSetEquipped) {
+                    setVal = InventoryItemFactory.getInstance().getInventoryItem(InventoryItem.ItemTypeID.valueOf(getInventory(equipSlots).get(0).getItemTypeAtLocation())).getItemSetID().name();
+                    setValLabel.setText(setVal);
+
+                    setBonusFromSet(addItem);
+                    updateValuesWithBonus("bonusSet", true);
+                }
             }
             case REMOVED_ITEM -> {
                 InventoryItem removeItem = slot.getTopInventoryItem();
                 if (removeItem == null) {
                     return;
                 }
+                updateValuesWithBonus("bonusSet", false);
+
                 if (removeItem.isInventoryItemOffensive()) {
                     APVal -= removeItem.getItemUseTypeValue();
                     APValLabel.setText(String.valueOf(APVal));
@@ -505,6 +602,8 @@ public void onNotify(InventorySlot slot, SlotEvent event) {
 
                     ProfileManager.getInstance().setProperty("currentPlayerDP", DPVal);
                 }
+                setValLabel.setText("");
+                ProfileManager.getInstance().setProperty("bonusSet", null);
             }
             default -> {
             }
diff --git a/core/src/main/java/com/gdx/game/inventory/InventoryItem.java b/core/src/main/java/com/gdx/game/inventory/item/InventoryItem.java
similarity index 95%
rename from core/src/main/java/com/gdx/game/inventory/InventoryItem.java
rename to core/src/main/java/com/gdx/game/inventory/item/InventoryItem.java
index abb061cb..f2208b4c 100644
--- a/core/src/main/java/com/gdx/game/inventory/InventoryItem.java
+++ b/core/src/main/java/com/gdx/game/inventory/item/InventoryItem.java
@@ -1,4 +1,4 @@
-package com.gdx.game.inventory;
+package com.gdx.game.inventory.item;
 
 import com.badlogic.gdx.graphics.Color;
 import com.badlogic.gdx.graphics.g2d.TextureRegion;
@@ -87,11 +87,16 @@ public Color getColor() {
         }
     }
 
+    public enum ItemSetID {
+        PEASANT_SET
+    }
+
     private int itemAttributes;
     private int itemUseType;
     private int itemUseTypeValue;
     private ItemTypeID itemTypeID;
     private ItemRarity itemRarity;
+    private ItemSetID itemSetID;
     private String itemShortDescription;
     private int itemValue;
 
@@ -116,6 +121,7 @@ public InventoryItem(InventoryItem inventoryItem) {
         this.itemUseType = inventoryItem.getItemUseType();
         this.itemUseTypeValue = inventoryItem.getItemUseTypeValue();
         this.itemRarity = inventoryItem.getItemRarity();
+        this.itemSetID = inventoryItem.getItemSetID();
         this.itemShortDescription = inventoryItem.getItemShortDescription();
         this.itemValue = inventoryItem.getItemValue();
     }
@@ -168,6 +174,14 @@ public void setItemRarity(ItemRarity itemRarity) {
         this.itemRarity = itemRarity;
     }
 
+    public ItemSetID getItemSetID() {
+        return itemSetID;
+    }
+
+    public void setItemSetID(ItemSetID itemSetID) {
+        this.itemSetID = itemSetID;
+    }
+
     public String getItemShortDescription() {
         return itemShortDescription;
     }
diff --git a/core/src/main/java/com/gdx/game/inventory/InventoryItemFactory.java b/core/src/main/java/com/gdx/game/inventory/item/InventoryItemFactory.java
similarity index 95%
rename from core/src/main/java/com/gdx/game/inventory/InventoryItemFactory.java
rename to core/src/main/java/com/gdx/game/inventory/item/InventoryItemFactory.java
index 439c82e6..c13d23b7 100644
--- a/core/src/main/java/com/gdx/game/inventory/InventoryItemFactory.java
+++ b/core/src/main/java/com/gdx/game/inventory/item/InventoryItemFactory.java
@@ -1,4 +1,4 @@
-package com.gdx.game.inventory;
+package com.gdx.game.inventory.item;
 
 
 import com.badlogic.gdx.Gdx;
@@ -6,7 +6,7 @@
 import com.badlogic.gdx.utils.Json;
 import com.badlogic.gdx.utils.JsonValue;
 import com.badlogic.gdx.utils.Scaling;
-import com.gdx.game.inventory.InventoryItem.ItemTypeID;
+import com.gdx.game.inventory.item.InventoryItem.ItemTypeID;
 
 import java.util.ArrayList;
 import java.util.Hashtable;
diff --git a/core/src/main/java/com/gdx/game/inventory/InventoryItemLocation.java b/core/src/main/java/com/gdx/game/inventory/item/InventoryItemLocation.java
similarity index 97%
rename from core/src/main/java/com/gdx/game/inventory/InventoryItemLocation.java
rename to core/src/main/java/com/gdx/game/inventory/item/InventoryItemLocation.java
index d7573376..cf95af98 100644
--- a/core/src/main/java/com/gdx/game/inventory/InventoryItemLocation.java
+++ b/core/src/main/java/com/gdx/game/inventory/item/InventoryItemLocation.java
@@ -1,4 +1,4 @@
-package com.gdx.game.inventory;
+package com.gdx.game.inventory.item;
 
 public class InventoryItemLocation {
     private int locationIndex;
diff --git a/core/src/main/java/com/gdx/game/inventory/set/EquipmentSet.java b/core/src/main/java/com/gdx/game/inventory/set/EquipmentSet.java
new file mode 100644
index 00000000..c4f07107
--- /dev/null
+++ b/core/src/main/java/com/gdx/game/inventory/set/EquipmentSet.java
@@ -0,0 +1,45 @@
+package com.gdx.game.inventory.set;
+
+import com.gdx.game.inventory.item.InventoryItem;
+
+import java.util.HashMap;
+
+public class EquipmentSet {
+
+    private InventoryItem.ItemSetID itemSetID;
+    private String itemSetDescription;
+    private HashMap<String, String> bonus = new HashMap<>();
+
+    public EquipmentSet() {
+    }
+
+    public EquipmentSet(EquipmentSet equipmentSet) {
+        this.itemSetID = equipmentSet.getItemSetID();
+        this.itemSetDescription = equipmentSet.getItemSetDescription();
+        this.bonus = equipmentSet.getBonus();
+    }
+
+    public InventoryItem.ItemSetID getItemSetID() {
+        return itemSetID;
+    }
+
+    public void setItemSetID(InventoryItem.ItemSetID itemSetID) {
+        this.itemSetID = itemSetID;
+    }
+
+    public String getItemSetDescription() {
+        return itemSetDescription;
+    }
+
+    public void setItemSetDescription(String itemSetDescription) {
+        this.itemSetDescription = itemSetDescription;
+    }
+
+    public HashMap<String, String> getBonus() {
+        return bonus;
+    }
+
+    public void setBonus(HashMap<String, String> bonus) {
+        this.bonus = bonus;
+    }
+}
diff --git a/core/src/main/java/com/gdx/game/inventory/set/EquipmentSetFactory.java b/core/src/main/java/com/gdx/game/inventory/set/EquipmentSetFactory.java
new file mode 100644
index 00000000..168157ad
--- /dev/null
+++ b/core/src/main/java/com/gdx/game/inventory/set/EquipmentSetFactory.java
@@ -0,0 +1,39 @@
+package com.gdx.game.inventory.set;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.utils.Json;
+import com.badlogic.gdx.utils.JsonValue;
+import com.gdx.game.inventory.item.InventoryItem;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+public class EquipmentSetFactory {
+
+    private Json json = new Json();
+    private static final String ITEM_SET = "scripts/equipment_sets.json";
+    private static EquipmentSetFactory instance = null;
+    private Hashtable<InventoryItem.ItemSetID, EquipmentSet> equipSetList;
+
+    public static EquipmentSetFactory getInstance() {
+        if (instance == null) {
+            instance = new EquipmentSetFactory();
+        }
+
+        return instance;
+    }
+
+    private EquipmentSetFactory() {
+        ArrayList<JsonValue> list = json.fromJson(ArrayList.class, Gdx.files.internal(ITEM_SET));
+        equipSetList = new Hashtable<>();
+
+        for(JsonValue jsonVal : list) {
+            EquipmentSet equipSet = json.readValue(EquipmentSet.class, jsonVal);
+            equipSetList.put(equipSet.getItemSetID(), equipSet);
+        }
+    }
+
+    public EquipmentSet getEquipmentSet(InventoryItem.ItemSetID equipmentType) {
+        return new EquipmentSet(equipSetList.get(equipmentType));
+    }
+}
diff --git a/core/src/main/java/com/gdx/game/inventory/slot/InventorySlot.java b/core/src/main/java/com/gdx/game/inventory/slot/InventorySlot.java
index c55c1650..6822fae6 100644
--- a/core/src/main/java/com/gdx/game/inventory/slot/InventorySlot.java
+++ b/core/src/main/java/com/gdx/game/inventory/slot/InventorySlot.java
@@ -8,7 +8,7 @@
 import com.badlogic.gdx.utils.Align;
 import com.badlogic.gdx.utils.Array;
 import com.badlogic.gdx.utils.SnapshotArray;
-import com.gdx.game.inventory.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItem;
 
 import static com.gdx.game.manager.ResourceManager.STATUS_UI_SKIN;
 import static com.gdx.game.manager.ResourceManager.STATUS_UI_TEXTURE_ATLAS;
diff --git a/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotSource.java b/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotSource.java
index 5497f019..870cbfe0 100644
--- a/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotSource.java
+++ b/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotSource.java
@@ -2,11 +2,14 @@
 
 import com.badlogic.gdx.scenes.scene2d.Actor;
 import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop;
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop.Payload;
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop.Source;
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop.Target;
 
+import static com.gdx.game.inventory.InventoryUI.getInventory;
+
 public class InventorySlotSource extends Source {
 
     private DragAndDrop dragAndDrop;
@@ -34,13 +37,13 @@ public Payload dragStart(InputEvent event, float x, float y, int pointer) {
             sourceSlot = source;
         }
 
-    sourceSlot.decrementItemCount(true);
+        sourceSlot.decrementItemCount(true);
 
-    payload.setDragActor(getActor());
-    dragAndDrop.setDragActorPosition(-x, -y + getActor().getHeight());
+        payload.setDragActor(getActor());
+        dragAndDrop.setDragActorPosition(-x, -y + getActor().getHeight());
 
-    return payload;
-}
+        return payload;
+    }
 
     @Override
     public void dragStop (InputEvent event, float x, float y, int pointer, Payload payload, Target target) {
diff --git a/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotTarget.java b/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotTarget.java
index da565b01..1a7d43e8 100644
--- a/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotTarget.java
+++ b/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotTarget.java
@@ -3,7 +3,7 @@
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop.Payload;
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop.Source;
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop.Target;
-import com.gdx.game.inventory.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItem;
 
 public class InventorySlotTarget extends Target {
 
diff --git a/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotTooltip.java b/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotTooltip.java
index 3b9b165b..81744938 100644
--- a/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotTooltip.java
+++ b/core/src/main/java/com/gdx/game/inventory/slot/InventorySlotTooltip.java
@@ -3,7 +3,7 @@
 import com.badlogic.gdx.scenes.scene2d.ui.Label;
 import com.badlogic.gdx.scenes.scene2d.ui.Skin;
 import com.badlogic.gdx.scenes.scene2d.ui.Window;
-import com.gdx.game.inventory.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItem;
 
 public class InventorySlotTooltip extends Window {
 
diff --git a/core/src/main/java/com/gdx/game/inventory/store/StoreInventoryUI.java b/core/src/main/java/com/gdx/game/inventory/store/StoreInventoryUI.java
index eb1d6ff7..1844ebf9 100644
--- a/core/src/main/java/com/gdx/game/inventory/store/StoreInventoryUI.java
+++ b/core/src/main/java/com/gdx/game/inventory/store/StoreInventoryUI.java
@@ -14,7 +14,7 @@
 import com.badlogic.gdx.utils.Align;
 import com.badlogic.gdx.utils.Array;
 import com.badlogic.gdx.utils.Json;
-import com.gdx.game.inventory.InventoryItemLocation;
+import com.gdx.game.inventory.item.InventoryItemLocation;
 import com.gdx.game.inventory.slot.InventorySlot;
 import com.gdx.game.inventory.slot.InventorySlotObserver;
 import com.gdx.game.inventory.slot.InventorySlotTarget;
diff --git a/core/src/main/java/com/gdx/game/screen/BattleScreen.java b/core/src/main/java/com/gdx/game/screen/BattleScreen.java
index 8f80d17c..963841c0 100644
--- a/core/src/main/java/com/gdx/game/screen/BattleScreen.java
+++ b/core/src/main/java/com/gdx/game/screen/BattleScreen.java
@@ -14,7 +14,7 @@
 import com.gdx.game.battle.BattleState;
 import com.gdx.game.entities.Entity;
 import com.gdx.game.entities.player.PlayerHUD;
-import com.gdx.game.inventory.InventoryItemLocation;
+import com.gdx.game.inventory.item.InventoryItemLocation;
 import com.gdx.game.inventory.InventoryObserver;
 import com.gdx.game.inventory.InventoryUI;
 import com.gdx.game.manager.ResourceManager;
diff --git a/core/src/main/resources/scripts/equipment_sets.json b/core/src/main/resources/scripts/equipment_sets.json
new file mode 100644
index 00000000..9b492b7c
--- /dev/null
+++ b/core/src/main/resources/scripts/equipment_sets.json
@@ -0,0 +1,16 @@
+[
+	{
+		itemSetID: PEASANT_SET
+		itemSetDescription: Increase physical attack by 10%
+		bonus: {
+			ENTITY_PHYSICAL_ATTACK_POINTS: {
+				class: java.lang.String
+				value: 0.1
+			}
+			ENTITY_PHYSICAL_DEFENSE_POINTS: {
+				class: java.lang.String
+				value: 0.1
+			}
+		}
+	}
+]
\ No newline at end of file
diff --git a/core/src/main/resources/scripts/inventory_items.json b/core/src/main/resources/scripts/inventory_items.json
index fd9b9cd8..5937b238 100644
--- a/core/src/main/resources/scripts/inventory_items.json
+++ b/core/src/main/resources/scripts/inventory_items.json
@@ -14,6 +14,7 @@
 		itemUseTypeValue: 10
 		itemTypeID: SHIELD02
 		itemRarity: COMMON
+		itemSetID: PEASANT_SET
 		itemShortDescription: A wooden shield fit for a peasant
 		itemValue: 25
 	},
@@ -77,6 +78,7 @@
 		itemUseTypeValue: 10
 		itemTypeID: ARMOR04
 		itemRarity: COMMON
+		itemSetID: PEASANT_SET
 		itemShortDescription: Broken mail armor fit for a peasant
 		itemValue: 25
 	},
@@ -113,6 +115,7 @@
 		itemUseTypeValue: 10
 		itemTypeID: BOOTS03
 		itemRarity: COMMON
+		itemSetID: PEASANT_SET
 		itemShortDescription: Leather boots fit for a peasant
 		itemValue: 25
 	},
@@ -176,6 +179,7 @@
 		itemUseTypeValue: 10
 		itemTypeID: HELMET05
 		itemRarity: COMMON
+		itemSetID: PEASANT_SET
 		itemShortDescription: A leather helmet fit for a peasant
 		itemValue: 25
 	},
@@ -230,6 +234,7 @@
 		itemUseTypeValue: 10
 		itemTypeID: WEAPON01
 		itemRarity: COMMON
+		itemSetID: PEASANT_SET
 		itemShortDescription: A copper sword of a peasant
 		itemValue: 25
 	},
diff --git a/core/src/test/java/com/gdx/game/battle/BattleHUDTest.java b/core/src/test/java/com/gdx/game/battle/BattleHUDTest.java
index ef8ea36c..f847fbb5 100644
--- a/core/src/test/java/com/gdx/game/battle/BattleHUDTest.java
+++ b/core/src/test/java/com/gdx/game/battle/BattleHUDTest.java
@@ -11,11 +11,12 @@
 import com.gdx.game.GdxRunner;
 import com.gdx.game.animation.AnimatedImage;
 import com.gdx.game.entities.Entity;
+import com.gdx.game.entities.EntityBonus;
 import com.gdx.game.entities.EntityConfig;
 import com.gdx.game.entities.EntityFactory;
-import com.gdx.game.inventory.InventoryItem;
-import com.gdx.game.inventory.InventoryItemFactory;
-import com.gdx.game.inventory.InventoryItemLocation;
+import com.gdx.game.inventory.item.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItemFactory;
+import com.gdx.game.inventory.item.InventoryItemLocation;
 import com.gdx.game.inventory.InventoryObserver;
 import com.gdx.game.manager.ResourceManager;
 import com.gdx.game.map.MapManager;
@@ -68,6 +69,9 @@ void init() {
         profileManager.setProperty("currentPlayerCharacterAP", 5);
         profileManager.setProperty("currentPlayerCharacterDP", 5);
         profileManager.setProperty("currentPlayerCharacterSPDP", 10);
+        EntityBonus entityBonusAtk = new EntityBonus(EntityConfig.EntityProperties.ENTITY_PHYSICAL_ATTACK_POINTS.name(), "0.3");
+        EntityBonus entityBonusDef = new EntityBonus(EntityConfig.EntityProperties.ENTITY_PHYSICAL_DEFENSE_POINTS.name(), "0.1");
+        profileManager.setProperty("bonusSet", new Array<>(new EntityBonus[]{entityBonusAtk, entityBonusDef}));
         new ResourceManager();
     }
 
diff --git a/core/src/test/java/com/gdx/game/battle/BattleStateTest.java b/core/src/test/java/com/gdx/game/battle/BattleStateTest.java
index 0be97b4f..ad0f8a7e 100644
--- a/core/src/test/java/com/gdx/game/battle/BattleStateTest.java
+++ b/core/src/test/java/com/gdx/game/battle/BattleStateTest.java
@@ -2,8 +2,10 @@
 
 import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.utils.Array;
 import com.gdx.game.GdxRunner;
 import com.gdx.game.entities.Entity;
+import com.gdx.game.entities.EntityBonus;
 import com.gdx.game.entities.EntityConfig;
 import com.gdx.game.entities.EntityFactory;
 import com.gdx.game.entities.npc.NPCGraphicsComponent;
@@ -47,6 +49,9 @@ void init() {
         profileManager.setProperty("currentPlayerDP", 5);
         profileManager.setProperty("currentPlayerMP", 5);
         profileManager.setProperty("currentPlayerHP", 20);
+        EntityBonus entityBonusAtk = new EntityBonus(EntityConfig.EntityProperties.ENTITY_PHYSICAL_ATTACK_POINTS.name(), "0.3");
+        EntityBonus entityBonusDef = new EntityBonus(EntityConfig.EntityProperties.ENTITY_PHYSICAL_DEFENSE_POINTS.name(), "0.1");
+        profileManager.setProperty("bonusSet", new Array<>(new EntityBonus[]{entityBonusAtk, entityBonusDef}));
     }
 
     @AfterEach
@@ -67,7 +72,7 @@ void playerAttack_doNotKill() {
 
         battleState.getPlayerAttackCalculationTimer().run();
 
-        assertThat(enemy.getEntityConfig().getPropertyValue(EntityConfig.EntityProperties.ENTITY_HEALTH_POINTS.toString())).isLessThanOrEqualTo("19");
+        assertThat(enemy.getEntityConfig().getPropertyValue(EntityConfig.EntityProperties.ENTITY_HEALTH_POINTS.toString())).isLessThanOrEqualTo("18");
         verify(battleState).notify(enemy, BattleObserver.BattleEvent.OPPONENT_HIT_DAMAGE);
         verify(battleState).notify(enemy, BattleObserver.BattleEvent.PLAYER_TURN_DONE);
         verify(battleState, never()).notify(enemy, BattleObserver.BattleEvent.OPPONENT_DEFEATED);
@@ -108,7 +113,7 @@ void opponentAttack() {
 
         battleState.getOpponentAttackCalculationTimer().run();
 
-        assertThat(player.getEntityConfig().getPropertyValue(EntityConfig.EntityProperties.ENTITY_HEALTH_POINTS.toString())).isLessThanOrEqualTo("19");
+        assertThat(player.getEntityConfig().getPropertyValue(EntityConfig.EntityProperties.ENTITY_HEALTH_POINTS.toString())).isLessThanOrEqualTo("18");
         verify(battleState).notify(player, BattleObserver.BattleEvent.PLAYER_HIT_DAMAGE);
         verify(battleState).notify(enemy, BattleObserver.BattleEvent.OPPONENT_TURN_DONE);
     }
diff --git a/core/src/test/java/com/gdx/game/battle/BattleUITest.java b/core/src/test/java/com/gdx/game/battle/BattleUITest.java
index a9aa8b18..f7cbcac4 100644
--- a/core/src/test/java/com/gdx/game/battle/BattleUITest.java
+++ b/core/src/test/java/com/gdx/game/battle/BattleUITest.java
@@ -2,7 +2,10 @@
 
 import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.utils.Array;
 import com.gdx.game.GdxRunner;
+import com.gdx.game.entities.EntityBonus;
+import com.gdx.game.entities.EntityConfig;
 import com.gdx.game.manager.ResourceManager;
 import com.gdx.game.profile.ProfileManager;
 import org.junit.jupiter.api.BeforeEach;
@@ -27,6 +30,9 @@ public void testBattleUI_ShouldSucceed() {
         ProfileManager profileManager = ProfileManager.getInstance();
         profileManager.setProperty("currentPlayerAP", 5);
         profileManager.setProperty("currentPlayerDP", 5);
+        EntityBonus entityBonusAtk = new EntityBonus(EntityConfig.EntityProperties.ENTITY_PHYSICAL_ATTACK_POINTS.name(), "0.3");
+        EntityBonus entityBonusDef = new EntityBonus(EntityConfig.EntityProperties.ENTITY_PHYSICAL_DEFENSE_POINTS.name(), "0.1");
+        profileManager.setProperty("bonusSet", new Array<>(new EntityBonus[]{entityBonusAtk, entityBonusDef}));
 
         BattleState battleState = new BattleState();
         BattleInventoryUI battleInventoryUI = new BattleInventoryUI();
diff --git a/core/src/test/java/com/gdx/game/entities/player/PlayerHUDTest.java b/core/src/test/java/com/gdx/game/entities/player/PlayerHUDTest.java
index b83e5eba..0e6dc0e0 100644
--- a/core/src/test/java/com/gdx/game/entities/player/PlayerHUDTest.java
+++ b/core/src/test/java/com/gdx/game/entities/player/PlayerHUDTest.java
@@ -16,8 +16,8 @@
 import com.gdx.game.entities.Entity;
 import com.gdx.game.entities.EntityFactory;
 import com.gdx.game.entities.player.characterClass.ClassObserver;
-import com.gdx.game.inventory.InventoryItem;
-import com.gdx.game.inventory.InventoryItemFactory;
+import com.gdx.game.inventory.item.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItemFactory;
 import com.gdx.game.inventory.InventoryObserver;
 import com.gdx.game.inventory.store.StoreInventoryObserver;
 import com.gdx.game.manager.ResourceManager;
diff --git a/core/src/test/java/com/gdx/game/inventory/InventoryItemFactoryTest.java b/core/src/test/java/com/gdx/game/inventory/InventoryItemFactoryTest.java
index a7d5d449..da7502ef 100644
--- a/core/src/test/java/com/gdx/game/inventory/InventoryItemFactoryTest.java
+++ b/core/src/test/java/com/gdx/game/inventory/InventoryItemFactoryTest.java
@@ -3,8 +3,8 @@
 import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.graphics.GL20;
 import com.gdx.game.GdxRunner;
-import com.gdx.game.inventory.InventoryItem;
-import com.gdx.game.inventory.InventoryItemFactory;
+import com.gdx.game.inventory.item.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItemFactory;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
diff --git a/core/src/test/java/com/gdx/game/inventory/InventoryItemLocationTest.java b/core/src/test/java/com/gdx/game/inventory/InventoryItemLocationTest.java
index 4f39311d..6dd1b2e8 100644
--- a/core/src/test/java/com/gdx/game/inventory/InventoryItemLocationTest.java
+++ b/core/src/test/java/com/gdx/game/inventory/InventoryItemLocationTest.java
@@ -3,7 +3,7 @@
 import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.graphics.GL20;
 import com.gdx.game.GdxRunner;
-import com.gdx.game.inventory.InventoryItemLocation;
+import com.gdx.game.inventory.item.InventoryItemLocation;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
diff --git a/core/src/test/java/com/gdx/game/inventory/InventoryItemTest.java b/core/src/test/java/com/gdx/game/inventory/InventoryItemTest.java
index 99358d75..b4503093 100644
--- a/core/src/test/java/com/gdx/game/inventory/InventoryItemTest.java
+++ b/core/src/test/java/com/gdx/game/inventory/InventoryItemTest.java
@@ -3,8 +3,8 @@
 import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.graphics.GL20;
 import com.gdx.game.GdxRunner;
-import com.gdx.game.inventory.InventoryItem;
-import com.gdx.game.inventory.InventoryItemFactory;
+import com.gdx.game.inventory.item.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItemFactory;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
diff --git a/core/src/test/java/com/gdx/game/inventory/InventoryUITest.java b/core/src/test/java/com/gdx/game/inventory/InventoryUITest.java
index 98818eca..4782519e 100644
--- a/core/src/test/java/com/gdx/game/inventory/InventoryUITest.java
+++ b/core/src/test/java/com/gdx/game/inventory/InventoryUITest.java
@@ -2,36 +2,177 @@
 
 import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.utils.Array;
 import com.gdx.game.GdxRunner;
+import com.gdx.game.entities.EntityConfig;
+import com.gdx.game.entities.EntityFactory;
+import com.gdx.game.inventory.item.InventoryItem;
+import com.gdx.game.inventory.item.InventoryItemLocation;
+import com.gdx.game.inventory.slot.InventorySlot;
+import com.gdx.game.inventory.slot.InventorySlotObserver;
 import com.gdx.game.manager.ResourceManager;
 import com.gdx.game.profile.ProfileManager;
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.MockedConstruction;
 
+import java.util.HashMap;
+import java.util.stream.Stream;
+
+import static com.gdx.game.common.UtilityClass.calculateBonus;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 
 @ExtendWith(GdxRunner.class)
 public class InventoryUITest {
 
+    private MockedConstruction<ShapeRenderer> mockShapeRenderer;
+    private MockedConstruction<SpriteBatch> mockSpriteBatch;
+
+    private static final int PLAYER_AP = 15;
+    private static final int PLAYER_DP = 15;
+
     @BeforeEach
     void init() {
         Gdx.gl = mock(GL20.class);
         Gdx.gl20 = mock(GL20.class);
+        mockShapeRenderer = mockConstruction(ShapeRenderer.class);
+        mockSpriteBatch = mockConstruction(SpriteBatch.class);
         new ResourceManager();
+        ProfileManager profileManager = ProfileManager.getInstance();
+        profileManager.setProperty("playerCharacter", EntityFactory.EntityType.WARRIOR);
+        profileManager.setProperty("currentPlayerCharacterAP", PLAYER_AP);
+        profileManager.setProperty("currentPlayerCharacterDP", PLAYER_DP);
+        profileManager.setProperty("currentPlayerCharacterSPDP", 10);
+    }
+
+    @AfterEach
+    void end() {
+        mockShapeRenderer.close();
+        mockSpriteBatch.close();
     }
 
     @Test
     public void testInventoryUI_ShouldSucceed() {
-        ProfileManager profileManager = ProfileManager.getInstance();
-        profileManager.setProperty("currentPlayerCharacterAP", 5);
-        profileManager.setProperty("currentPlayerCharacterDP", 5);
-        profileManager.setProperty("currentPlayerCharacterSPDP", 5);
-
         InventoryUI inventoryUI = new InventoryUI();
 
         assertThat(inventoryUI).isNotNull();
         assertThat(inventoryUI.getDragAndDrop()).isNotNull();
     }
+
+    @ParameterizedTest
+    @MethodSource("itemEventData")
+    public void add_item_event(InventoryItem item, int playerStat, String profileSave, InventoryObserver.InventoryEvent inventoryEvent) {
+        InventorySlot inventorySlot = new InventorySlot();
+        inventorySlot.add(item);
+
+        InventoryUI inventoryUI = spy(new InventoryUI());
+        Table equipSlotTable = inventoryUI.getEquipSlotTable();
+        inventoryUI.onNotify(inventorySlot, InventorySlotObserver.SlotEvent.ADDED_ITEM);
+
+        verify(inventoryUI, times(1)).notify(String.valueOf(playerStat + item.getItemUseTypeValue()), inventoryEvent);
+        assertEquals(playerStat + item.getItemUseTypeValue(), ProfileManager.getInstance().getProperty(profileSave, Integer.class));
+        verify(inventoryUI, times(1)).isSetEquipped(InventoryUI.getInventory(equipSlotTable));
+    }
+
+    @ParameterizedTest
+    @MethodSource("itemEventData")
+    public void remove_item_event(InventoryItem item, int playerStat, String profileSave, InventoryObserver.InventoryEvent inventoryEvent) {
+        InventorySlot inventorySlot = new InventorySlot();
+        inventorySlot.add(item);
+
+        InventoryUI inventoryUI = spy(new InventoryUI());
+        inventoryUI.onNotify(inventorySlot, InventorySlotObserver.SlotEvent.REMOVED_ITEM);
+
+        verify(inventoryUI, times(1)).notify(String.valueOf(playerStat - item.getItemUseTypeValue()), inventoryEvent);
+        assertEquals(playerStat - item.getItemUseTypeValue(), ProfileManager.getInstance().getProperty(profileSave, Integer.class));
+    }
+
+    private static Stream<Arguments> itemEventData() {
+        return Stream.of(
+                Arguments.of(getInventoryItem(8), PLAYER_AP, "currentPlayerAP", InventoryObserver.InventoryEvent.UPDATED_AP),
+                Arguments.of(getInventoryItem(128), PLAYER_DP, "currentPlayerDP", InventoryObserver.InventoryEvent.UPDATED_DP)
+        );
+    }
+
+    private static InventoryItem getInventoryItem(int itemUseType) {
+        InventoryItem item = new InventoryItem();
+        item.setItemAttributes(2);
+        item.setItemUseType(itemUseType);
+        item.setItemUseTypeValue(10);
+        item.setItemTypeID(InventoryItem.ItemTypeID.WEAPON01);
+        item.setItemSetID(InventoryItem.ItemSetID.PEASANT_SET);
+        return item;
+    }
+
+    @ParameterizedTest
+    @MethodSource("itemSetData")
+    public void should_return_if_set_equipped(Array<InventoryItemLocation> equipSlots, boolean expectedResult) {
+        InventoryUI inventoryUI = new InventoryUI();
+        boolean result = inventoryUI.isSetEquipped(equipSlots);
+
+        assertEquals(expectedResult, result);
+    }
+
+    private static Stream<Arguments> itemSetData() {
+        return Stream.of(
+                Arguments.of(getInventoryItemLocations(), true),
+                Arguments.of(getInventoryItemLocationsWithoutHelmet(), false),
+                Arguments.of(getInventoryItemLocationsWithDifferentHelmet(), false)
+        );
+    }
+
+    private static Array<InventoryItemLocation> getInventoryItemLocations() {
+        InventoryItemLocation itemHelmet = new InventoryItemLocation(1, "HELMET05", 1, "Player_Inventory");
+        InventoryItemLocation itemWeapon = new InventoryItemLocation(2, "WEAPON01", 1, "Player_Inventory");
+        InventoryItemLocation itemArmor = new InventoryItemLocation(3, "ARMOR04", 1, "Player_Inventory");
+        InventoryItemLocation itemShield = new InventoryItemLocation(4, "SHIELD02", 1, "Player_Inventory");
+        InventoryItemLocation itemBoots = new InventoryItemLocation(5, "BOOTS03", 1, "Player_Inventory");
+
+        Array<InventoryItemLocation> equipSlots = new Array<>();
+        equipSlots.add(itemHelmet);
+        equipSlots.add(itemWeapon);
+        equipSlots.add(itemArmor);
+        equipSlots.add(itemShield);
+        equipSlots.add(itemBoots);
+        return equipSlots;
+    }
+
+    private static Array<InventoryItemLocation> getInventoryItemLocationsWithoutHelmet() {
+        Array<InventoryItemLocation> equipSlots = getInventoryItemLocations();
+        equipSlots.removeIndex(0);
+        return equipSlots;
+    }
+
+    private static Array<InventoryItemLocation> getInventoryItemLocationsWithDifferentHelmet() {
+        Array<InventoryItemLocation> equipSlots = getInventoryItemLocations();
+        InventoryItemLocation itemHelmet = new InventoryItemLocation(1, "HELMET03", 1, "Player_Inventory");
+        equipSlots.add(itemHelmet);
+        return equipSlots;
+    }
+
+    @Test
+    public void should_calculate_bonus_from_set() {
+        ProfileManager.getInstance().setProperty("currentPlayerAP", 10);
+        ProfileManager.getInstance().setProperty("currentPlayerDP", 25);
+        InventoryUI.setBonusFromSet(getInventoryItem(8));
+
+        HashMap<String, Integer> bonusMap = calculateBonus("bonusSet");
+
+        assertEquals(1, bonusMap.get(EntityConfig.EntityProperties.ENTITY_PHYSICAL_ATTACK_POINTS.name()));
+        assertEquals(2, bonusMap.get(EntityConfig.EntityProperties.ENTITY_PHYSICAL_DEFENSE_POINTS.name()));
+    }
 }