浏览代码

Reorganized artifact-related classes

- files now generally contain only 1 class (except for tightly coupled
classes)
- files are now located in lib/entities/artifact directory
- removed excessive includes

No changes to functionality
Ivan Savenko 5 月之前
父节点
当前提交
f70ad2c15b
共有 96 个文件被更改,包括 1666 次插入1454 次删除
  1. 2 1
      AI/Nullkiller/AIGateway.cpp
  2. 1 0
      AI/Nullkiller/AIUtility.cpp
  3. 2 1
      AI/Nullkiller/Engine/PriorityEvaluator.cpp
  4. 2 1
      AI/Nullkiller/Goals/AbstractGoal.cpp
  5. 1 0
      AI/VCAI/AIUtility.cpp
  6. 2 1
      AI/VCAI/Goals/AbstractGoal.cpp
  7. 6 5
      AI/VCAI/MapObjectsEvaluator.cpp
  8. 2 1
      AI/VCAI/VCAI.cpp
  9. 0 1
      CCallback.cpp
  10. 2 1
      client/ArtifactsUIController.cpp
  11. 0 2
      client/UIHelper.cpp
  12. 1 0
      client/battle/BattleWindow.cpp
  13. 0 1
      client/lobby/OptionsTab.cpp
  14. 1 2
      client/mainmenu/CCampaignScreen.cpp
  15. 0 1
      client/widgets/CArtifactsOfHeroAltar.cpp
  16. 0 2
      client/widgets/CArtifactsOfHeroAltar.h
  17. 2 1
      client/widgets/CArtifactsOfHeroBackpack.cpp
  18. 3 1
      client/widgets/CArtifactsOfHeroBase.cpp
  19. 1 0
      client/widgets/CArtifactsOfHeroMarket.cpp
  20. 2 3
      client/widgets/CComponent.cpp
  21. 2 1
      client/widgets/CComponentHolder.cpp
  22. 1 1
      client/widgets/CGarrisonInt.cpp
  23. 1 0
      client/widgets/markets/CAltarArtifacts.cpp
  24. 5 1
      client/widgets/markets/CAltarArtifacts.h
  25. 1 0
      client/widgets/markets/CArtifactsBuying.cpp
  26. 1 1
      client/widgets/markets/CArtifactsSelling.cpp
  27. 1 0
      client/widgets/markets/TradePanels.cpp
  28. 1 1
      client/windows/CCastleInterface.cpp
  29. 1 1
      client/windows/CCreatureWindow.cpp
  30. 1 2
      client/windows/CHeroWindow.cpp
  31. 0 1
      client/windows/CQuestLog.cpp
  32. 2 1
      client/windows/CWindowWithArtifacts.cpp
  33. 0 1085
      lib/CArtHandler.cpp
  34. 0 180
      lib/CArtHandler.h
  35. 0 1
      lib/CCreatureSet.cpp
  36. 1 2
      lib/CCreatureSet.h
  37. 16 7
      lib/CMakeLists.txt
  38. 1 1
      lib/GameLibrary.cpp
  39. 4 3
      lib/IGameCallback.cpp
  40. 1 0
      lib/battle/BattleInfo.cpp
  41. 0 1
      lib/bonuses/Bonus.cpp
  42. 0 1
      lib/bonuses/Limiters.cpp
  43. 1 1
      lib/constants/EntityIdentifiers.cpp
  44. 30 0
      lib/entities/artifact/ArtBearer.h
  45. 42 0
      lib/entities/artifact/ArtSlotInfo.cpp
  46. 49 0
      lib/entities/artifact/ArtSlotInfo.h
  47. 11 6
      lib/entities/artifact/ArtifactUtils.cpp
  48. 1 6
      lib/entities/artifact/ArtifactUtils.h
  49. 424 0
      lib/entities/artifact/CArtHandler.cpp
  50. 54 0
      lib/entities/artifact/CArtHandler.h
  51. 314 0
      lib/entities/artifact/CArtifact.cpp
  52. 123 0
      lib/entities/artifact/CArtifact.h
  53. 36 0
      lib/entities/artifact/CArtifactFittingSet.cpp
  54. 35 0
      lib/entities/artifact/CArtifactFittingSet.h
  55. 4 5
      lib/entities/artifact/CArtifactInstance.cpp
  56. 0 0
      lib/entities/artifact/CArtifactInstance.h
  57. 377 0
      lib/entities/artifact/CArtifactSet.cpp
  58. 6 48
      lib/entities/artifact/CArtifactSet.h
  59. 26 0
      lib/entities/artifact/EArtifactClass.h
  60. 8 7
      lib/gameState/CGameState.cpp
  61. 2 1
      lib/gameState/CGameStateCampaign.cpp
  62. 2 2
      lib/json/JsonRandom.cpp
  63. 2 1
      lib/mapObjects/CGHeroInstance.cpp
  64. 0 1
      lib/mapObjects/CGHeroInstance.h
  65. 0 1
      lib/mapObjects/CGMarket.h
  66. 1 1
      lib/mapObjects/CQuest.cpp
  67. 1 1
      lib/mapObjects/IMarket.cpp
  68. 1 1
      lib/mapObjects/IMarket.h
  69. 7 6
      lib/mapObjects/MiscObjects.cpp
  70. 1 1
      lib/mapping/CMap.cpp
  71. 1 1
      lib/mapping/MapFormatH3M.cpp
  72. 1 1
      lib/mapping/MapFormatJson.cpp
  73. 1 1
      lib/modding/ContentTypeHandler.cpp
  74. 3 26
      lib/networkPacks/NetPacksLib.cpp
  75. 1 1
      lib/rewardable/Limiter.cpp
  76. 2 2
      lib/rmg/CMapGenerator.cpp
  77. 1 0
      lib/rmg/modificators/QuestArtifactPlacer.cpp
  78. 0 1
      lib/rmg/modificators/TreasurePlacer.cpp
  79. 1 0
      lib/serializer/RegisterTypes.h
  80. 1 1
      lib/texts/MetaString.cpp
  81. 1 1
      mapeditor/campaigneditor/scenarioproperties.cpp
  82. 1 1
      mapeditor/campaigneditor/startingbonus.cpp
  83. 3 1
      mapeditor/inspector/artifactwidget.cpp
  84. 5 1
      mapeditor/inspector/artifactwidget.h
  85. 2 1
      mapeditor/inspector/heroartifactswidget.cpp
  86. 1 0
      mapeditor/inspector/heroartifactswidget.h
  87. 0 2
      mapeditor/inspector/inspector.cpp
  88. 1 1
      mapeditor/inspector/questwidget.cpp
  89. 2 1
      mapeditor/inspector/rewardswidget.cpp
  90. 1 1
      mapeditor/mapcontroller.cpp
  91. 1 1
      mapeditor/mapsettings/mapsettings.cpp
  92. 1 0
      mapeditor/mapsettings/victoryconditions.cpp
  93. 3 2
      server/CGameHandler.cpp
  94. 2 1
      server/battles/BattleResultProcessor.cpp
  95. 1 0
      server/processors/PlayerMessageProcessor.cpp
  96. 1 1
      test/entity/CArtifactTest.cpp

+ 2 - 1
AI/Nullkiller/AIGateway.cpp

@@ -9,10 +9,11 @@
  */
 #include "StdInc.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/AsyncRunner.h"
 #include "../../lib/UnlockGuard.h"
 #include "../../lib/StartInfo.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/entities/building/CBuilding.h"
 #include "../../lib/mapObjects/MapObjects.h"
 #include "../../lib/mapObjects/ObjectTemplate.h"

+ 1 - 0
AI/Nullkiller/AIUtility.cpp

@@ -14,6 +14,7 @@
 
 #include "../../lib/UnlockGuard.h"
 #include "../../lib/CConfigHandler.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/mapObjects/MapObjects.h"
 #include "../../lib/mapObjects/CQuest.h"
 #include "../../lib/mapping/CMapDefines.h"

+ 2 - 1
AI/Nullkiller/Engine/PriorityEvaluator.cpp

@@ -11,6 +11,7 @@
 #include <limits>
 
 #include "Nullkiller.h"
+#include "../../../lib/entities/artifact/CArtifact.h"
 #include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
 #include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
 #include "../../../lib/mapObjects/CGResource.h"
@@ -268,7 +269,7 @@ uint64_t RewardEvaluator::getArmyReward(
 			{
 				for(auto artID : info.reward.artifacts)
 				{
-					const auto * art = dynamic_cast<const CArtifact *>(LIBRARY->artifacts()->getById(artID));
+					const auto * art = artID.toArtifact();
 
 					rewardValue += evaluateArtifactArmyValue(art);
 				}

+ 2 - 1
AI/Nullkiller/Goals/AbstractGoal.cpp

@@ -11,6 +11,7 @@
 #include "AbstractGoal.h"
 #include "../AIGateway.h"
 #include "../../../lib/constants/StringConstants.h"
+#include "../../../lib/entities/artifact/CArtifact.h"
 
 namespace NKAI
 {
@@ -55,7 +56,7 @@ std::string AbstractGoal::toString() const
 		desc = "GATHER TROOPS";
 		break;
 	case GET_ART_TYPE:
-		desc = "GET ARTIFACT OF TYPE " + LIBRARY->artifacts()->getByIndex(aid)->getNameTranslated();
+		desc = "GET ARTIFACT OF TYPE " + ArtifactID(aid).toEntity(LIBRARY)->getNameTranslated();
 		break;
 	case DIG_AT_TILE:
 		desc = "DIG AT TILE " + tile.toString();

+ 1 - 0
AI/VCAI/AIUtility.cpp

@@ -15,6 +15,7 @@
 
 #include "../../lib/UnlockGuard.h"
 #include "../../lib/CConfigHandler.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/mapObjects/CGTownInstance.h"
 #include "../../lib/mapObjects/CQuest.h"
 #include "../../lib/mapping/CMapDefines.h"

+ 2 - 1
AI/VCAI/Goals/AbstractGoal.cpp

@@ -15,6 +15,7 @@
 #include "../ResourceManager.h"
 #include "../BuildingManager.h"
 #include "../../../lib/constants/StringConstants.h"
+#include "../../../lib/entities/artifact/CArtifact.h"
 
 using namespace Goals;
 
@@ -85,7 +86,7 @@ std::string AbstractGoal::name() const //TODO: virtualize
 	}
 	break;
 	case GET_ART_TYPE:
-		desc = "GET ARTIFACT OF TYPE " + LIBRARY->artifacts()->getByIndex(aid)->getNameTranslated();
+		desc = "GET ARTIFACT OF TYPE " + ArtifactID(aid).toEntity(LIBRARY)->getNameTranslated();
 		break;
 	case VISIT_TILE:
 		desc = "VISIT TILE " + tile.toString();

+ 6 - 5
AI/VCAI/MapObjectsEvaluator.cpp

@@ -12,6 +12,7 @@
 #include "../../lib/GameConstants.h"
 #include "../../lib/GameLibrary.h"
 #include "../../lib/CCreatureHandler.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/mapObjects/CompoundMapObjectID.h"
 #include "../../lib/mapObjectConstructors/AObjectTypeHandler.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
@@ -94,15 +95,15 @@ std::optional<int> MapObjectsEvaluator::getObjectValue(const CGObjectInstance *
 		auto artifactObject = dynamic_cast<const CGArtifact *>(obj);
 		switch(artifactObject->getArtifactInstance()->getType()->aClass)
 		{
-		case CArtifact::EartClass::ART_TREASURE:
+		case EArtifactClass::ART_TREASURE:
 			return 2000;
-		case CArtifact::EartClass::ART_MINOR:
+		case EArtifactClass::ART_MINOR:
 			return 5000;
-		case CArtifact::EartClass::ART_MAJOR:
+		case EArtifactClass::ART_MAJOR:
 			return 10000;
-		case CArtifact::EartClass::ART_RELIC:
+		case EArtifactClass::ART_RELIC:
 			return 20000;
-		case CArtifact::EartClass::ART_SPECIAL:
+		case EArtifactClass::ART_SPECIAL:
 			return 20000;
 		default:
 			return 0; //invalid artifact class

+ 2 - 1
AI/VCAI/VCAI.cpp

@@ -15,7 +15,6 @@
 #include "Goals/Goals.h"
 #include "Goals/CompleteQuest.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/AsyncRunner.h"
 #include "../../lib/CThreadHelper.h"
 #include "../../lib/UnlockGuard.h"
@@ -29,6 +28,8 @@
 #include "../../lib/bonuses/Limiters.h"
 #include "../../lib/bonuses/Updaters.h"
 #include "../../lib/bonuses/Propagators.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/entities/building/CBuilding.h"
 #include "../../lib/mapObjects/CQuest.h"
 #include "../../lib/networkPacks/PacksForClient.h"

+ 0 - 1
CCallback.cpp

@@ -18,7 +18,6 @@
 #include "lib/mapObjects/CGHeroInstance.h"
 #include "lib/mapObjects/CGTownInstance.h"
 #include "lib/texts/CGeneralTextHandler.h"
-#include "lib/CArtHandler.h"
 #include "lib/GameConstants.h"
 #include "lib/CPlayerState.h"
 #include "lib/UnlockGuard.h"

+ 2 - 1
client/ArtifactsUIController.cpp

@@ -19,8 +19,9 @@
 #include "windows/CWindowWithArtifacts.h"
 
 #include "../CCallback.h"
-#include "../lib/ArtifactUtils.h"
 #include "../lib/GameLibrary.h"
+#include "../lib/entities/artifact/ArtifactUtils.h"
+#include "../lib/entities/artifact/CArtifact.h"
 #include "../lib/mapObjects/CGHeroInstance.h"
 #include "../lib/texts/CGeneralTextHandler.h"
 

+ 0 - 2
client/UIHelper.cpp

@@ -13,8 +13,6 @@
 
 #include "widgets/CComponent.h"
 
-#include "../lib/CArtHandler.h"
-#include "../lib/CArtifactInstance.h"
 #include "../lib/mapObjects/CGHeroInstance.h"
 #include "../lib/networkPacks/ArtifactLocation.h"
 #include "../lib/CRandomGenerator.h"

+ 1 - 0
client/battle/BattleWindow.cpp

@@ -42,6 +42,7 @@
 #include "../../lib/GameLibrary.h"
 #include "../../lib/StartInfo.h"
 #include "../../lib/battle/BattleInfo.h"
+#include "../../lib/entities/artifact/CArtHandler.h"
 #include "../../lib/filesystem/ResourcePath.h"
 #include "../../lib/gameState/InfoAboutArmy.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"

+ 0 - 1
client/lobby/OptionsTab.cpp

@@ -44,7 +44,6 @@
 #include "../../lib/filesystem/Filesystem.h"
 #include "../../lib/networkPacks/PacksForLobby.h"
 #include "../../lib/texts/CGeneralTextHandler.h"
-#include "../../lib/CArtHandler.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/mapping/CMapInfo.h"
 #include "../../lib/mapping/CMapHeader.h"

+ 1 - 2
client/mainmenu/CCampaignScreen.cpp

@@ -29,7 +29,6 @@
 #include "../windows/InfoWindows.h"
 #include "../windows/CWindowObject.h"
 
-#include "../../lib/CArtHandler.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/CCreatureHandler.h"
 #include "../../lib/CSkillHandler.h"
@@ -265,4 +264,4 @@ void CCampaignScreen::updateCampaignButtons(const JsonNode & parentConfig)
 	}
 
 	redraw();
-}
+}

+ 0 - 1
client/widgets/CArtifactsOfHeroAltar.cpp

@@ -15,7 +15,6 @@
 
 #include "../../CCallback.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/networkPacks/ArtifactLocation.h"
 

+ 0 - 2
client/widgets/CArtifactsOfHeroAltar.h

@@ -11,8 +11,6 @@
 
 #include "CArtifactsOfHeroBase.h"
 
-#include "../../lib/CArtHandler.h"
-
 class CArtifactsOfHeroAltar : public CArtifactsOfHeroBase
 {
 public:

+ 2 - 1
client/widgets/CArtifactsOfHeroBackpack.cpp

@@ -18,7 +18,8 @@
 #include "ObjectLists.h"
 
 #include "../CPlayerInterface.h"
-#include "../../lib/ArtifactUtils.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/networkPacks/ArtifactLocation.h"
 

+ 3 - 1
client/widgets/CArtifactsOfHeroBase.cpp

@@ -19,7 +19,9 @@
 #include "../CPlayerInterface.h"
 
 #include "../../CCallback.h"
-#include "../../lib/ArtifactUtils.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtifact.h"
+#include "../../lib/entities/artifact/CArtifactFittingSet.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/networkPacks/ArtifactLocation.h"
 

+ 1 - 0
client/widgets/CArtifactsOfHeroMarket.cpp

@@ -10,6 +10,7 @@
 #include "StdInc.h"
 #include "CArtifactsOfHeroMarket.h"
 
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 
 CArtifactsOfHeroMarket::CArtifactsOfHeroMarket(const Point & position, const int selectionWidth)

+ 2 - 3
client/widgets/CComponent.cpp

@@ -24,7 +24,8 @@
 #include "../windows/InfoWindows.h"
 #include "../widgets/TextControls.h"
 
-#include "../../lib/ArtifactUtils.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtHandler.h"
 #include "../../lib/entities/building/CBuilding.h"
 #include "../../lib/entities/faction/CFaction.h"
 #include "../../lib/entities/faction/CTown.h"
@@ -34,8 +35,6 @@
 #include "../../lib/CCreatureHandler.h"
 #include "../../lib/CSkillHandler.h"
 #include "../../lib/texts/CGeneralTextHandler.h"
-#include "../../lib/CArtHandler.h"
-#include "../../lib/CArtifactInstance.h"
 #include "../../lib/GameLibrary.h"
 
 #include <vcmi/spells/Service.h>

+ 2 - 1
client/widgets/CComponentHolder.cpp

@@ -24,10 +24,11 @@
 
 #include "../../CCallback.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/CSkillHandler.h"
 #include "../../lib/GameLibrary.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/networkPacks/ArtifactLocation.h"
 #include "../../lib/texts/CGeneralTextHandler.h"

+ 1 - 1
client/widgets/CGarrisonInt.cpp

@@ -25,12 +25,12 @@
 
 #include "../../CCallback.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/texts/CGeneralTextHandler.h"
 #include "../../lib/texts/TextOperations.h"
 #include "../../lib/CCreatureHandler.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/GameLibrary.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/networkPacks/ArtifactLocation.h"
 #include "../../lib/gameState/CGameState.h"

+ 1 - 0
client/widgets/markets/CAltarArtifacts.cpp

@@ -22,6 +22,7 @@
 #include "../../../CCallback.h"
 
 #include "../../../lib/GameLibrary.h"
+#include "../../../lib/entities/artifact/CArtifact.h"
 #include "../../../lib/networkPacks/ArtifactLocation.h"
 #include "../../../lib/texts/CGeneralTextHandler.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"

+ 5 - 1
client/widgets/markets/CAltarArtifacts.h

@@ -9,8 +9,12 @@
  */
 #pragma once
 
-#include "../CArtifactsOfHeroAltar.h"
 #include "CMarketBase.h"
+#include "../CArtifactsOfHeroAltar.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+class CArtifactSet;
+VCMI_LIB_NAMESPACE_END
 
 class CAltarArtifacts : public CExperienceAltar
 {

+ 1 - 0
client/widgets/markets/CArtifactsBuying.cpp

@@ -21,6 +21,7 @@
 #include "../../../CCallback.h"
 
 #include "../../../lib/GameLibrary.h"
+#include "../../../lib/entities/artifact/CArtHandler.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"
 #include "../../../lib/mapObjects/IMarket.h"
 #include "../../../lib/texts/CGeneralTextHandler.h"

+ 1 - 1
client/widgets/markets/CArtifactsSelling.cpp

@@ -21,8 +21,8 @@
 
 #include "../../../CCallback.h"
 
-#include "../../../lib/CArtifactInstance.h"
 #include "../../../lib/GameLibrary.h"
+#include "../../../lib/entities/artifact/CArtifact.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"
 #include "../../../lib/mapObjects/IMarket.h"
 #include "../../../lib/texts/CGeneralTextHandler.h"

+ 1 - 0
client/widgets/markets/TradePanels.cpp

@@ -21,6 +21,7 @@
 #include "../../../CCallback.h"
 
 #include "../../../lib/GameLibrary.h"
+#include "../../../lib/entities/artifact/CArtHandler.h"
 #include "../../../lib/texts/CGeneralTextHandler.h"
 #include "../../../lib/mapObjects/CGHeroInstance.h"
 

+ 1 - 1
client/windows/CCastleInterface.cpp

@@ -45,7 +45,6 @@
 #include "../adventureMap/CResDataBar.h"
 
 #include "../../CCallback.h"
-#include "../../lib/CArtHandler.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/CSoundBase.h"
 #include "../../lib/CCreatureHandler.h"
@@ -57,6 +56,7 @@
 #include "../../lib/gameState/UpgradeInfo.h"
 #include "../../lib/StartInfo.h"
 #include "../../lib/campaign/CampaignState.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/entities/building/CBuilding.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapObjects/CGTownInstance.h"

+ 1 - 1
client/windows/CCreatureWindow.cpp

@@ -30,12 +30,12 @@
 
 #include "../../CCallback.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/CBonusTypeHandler.h"
 #include "../../lib/CStack.h"
 #include "../../lib/GameLibrary.h"
 #include "../../lib/IGameSettings.h"
 #include "../../lib/bonuses/Propagators.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
 #include "../../lib/entities/hero/CHeroHandler.h"
 #include "../../lib/gameState/CGameState.h"
 #include "../../lib/gameState/UpgradeInfo.h"

+ 1 - 2
client/windows/CHeroWindow.cpp

@@ -32,11 +32,10 @@
 
 #include "../../CCallback.h"
 
-#include "../lib/ArtifactUtils.h"
-#include "../lib/CArtHandler.h"
 #include "../lib/CConfigHandler.h"
 #include "../lib/CSkillHandler.h"
 #include "../lib/GameLibrary.h"
+#include "../lib/entities/artifact/ArtifactUtils.h"
 #include "../lib/entities/hero/CHeroHandler.h"
 #include "../lib/mapObjects/CGHeroInstance.h"
 #include "../lib/networkPacks/ArtifactLocation.h"

+ 0 - 1
client/windows/CQuestLog.cpp

@@ -25,7 +25,6 @@
 
 #include "../../CCallback.h"
 
-#include "../../lib/CArtHandler.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/GameLibrary.h"
 #include "../../lib/gameState/QuestInfo.h"

+ 2 - 1
client/windows/CWindowWithArtifacts.cpp

@@ -27,9 +27,10 @@
 
 #include "../CPlayerInterface.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/GameLibrary.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/networkPacks/ArtifactLocation.h"
 #include "../../lib/texts/CGeneralTextHandler.h"

+ 0 - 1085
lib/CArtHandler.cpp

@@ -1,1085 +0,0 @@
-/*
- * CArtHandler.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-
-#include "StdInc.h"
-
-#include "ArtifactUtils.h"
-#include "ExceptionsCommon.h"
-#include "IGameSettings.h"
-#include "mapObjects/MapObjects.h"
-#include "constants/StringConstants.h"
-#include "json/JsonBonus.h"
-#include "mapObjectConstructors/AObjectTypeHandler.h"
-#include "mapObjectConstructors/CObjectClassesHandler.h"
-#include "gameState/CGameState.h"
-#include "mapping/CMap.h"
-#include "serializer/JsonSerializeFormat.h"
-#include "texts/CGeneralTextHandler.h"
-#include "texts/CLegacyConfigParser.h"
-
-// Note: list must match entries in ArtTraits.txt
-#define ART_POS_LIST    \
-	ART_POS(SPELLBOOK)  \
-	ART_POS(MACH4)      \
-	ART_POS(MACH3)      \
-	ART_POS(MACH2)      \
-	ART_POS(MACH1)      \
-	ART_POS(MISC5)      \
-	ART_POS(MISC4)      \
-	ART_POS(MISC3)      \
-	ART_POS(MISC2)      \
-	ART_POS(MISC1)      \
-	ART_POS(FEET)       \
-	ART_POS(LEFT_RING)  \
-	ART_POS(RIGHT_RING) \
-	ART_POS(TORSO)      \
-	ART_POS(LEFT_HAND)  \
-	ART_POS(RIGHT_HAND) \
-	ART_POS(NECK)       \
-	ART_POS(SHOULDERS)  \
-	ART_POS(HEAD)
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-bool CCombinedArtifact::isCombined() const
-{
-	return !(constituents.empty());
-}
-
-const std::vector<const CArtifact*> & CCombinedArtifact::getConstituents() const
-{
-	return constituents;
-}
-
-const std::set<const CArtifact*> & CCombinedArtifact::getPartOf() const
-{
-	return partOf;
-}
-
-void CCombinedArtifact::setFused(bool isFused)
-{
-	fused = isFused;
-}
-
-bool CCombinedArtifact::isFused() const
-{
-	return fused;
-}
-
-bool CCombinedArtifact::hasParts() const
-{
-	return isCombined() && !isFused();
-}
-
-bool CScrollArtifact::isScroll() const
-{
-	return static_cast<const CArtifact*>(this)->getId() == ArtifactID::SPELL_SCROLL;
-}
-
-bool CGrowingArtifact::isGrowing() const
-{
-	return !bonusesPerLevel.empty() || !thresholdBonuses.empty();
-}
-
-std::vector <std::pair<ui16, Bonus>> & CGrowingArtifact::getBonusesPerLevel()
-{
-	return bonusesPerLevel;
-}
-
-const std::vector <std::pair<ui16, Bonus>> & CGrowingArtifact::getBonusesPerLevel() const
-{
-	return bonusesPerLevel;
-}
-
-std::vector <std::pair<ui16, Bonus>> & CGrowingArtifact::getThresholdBonuses()
-{
-	return thresholdBonuses;
-}
-
-const std::vector <std::pair<ui16, Bonus>> & CGrowingArtifact::getThresholdBonuses() const
-{
-	return thresholdBonuses;
-}
-
-int32_t CArtifact::getIndex() const
-{
-	return id.toEnum();
-}
-
-int32_t CArtifact::getIconIndex() const
-{
-	return iconIndex;
-}
-
-std::string CArtifact::getJsonKey() const
-{
-	return modScope + ':' + identifier;
-}
-
-std::string CArtifact::getModScope() const
-{
-	return modScope;
-}
-
-void CArtifact::registerIcons(const IconRegistar & cb) const
-{
-	cb(getIconIndex(), 0, "ARTIFACT", image);
-	cb(getIconIndex(), 0, "ARTIFACTLARGE", large);
-}
-
-ArtifactID CArtifact::getId() const
-{
-	return id;
-}
-
-const IBonusBearer * CArtifact::getBonusBearer() const
-{
-	return this;
-}
-
-std::string CArtifact::getDescriptionTranslated() const
-{
-	return LIBRARY->generaltexth->translate(getDescriptionTextID());
-}
-
-std::string CArtifact::getEventTranslated() const
-{
-	return LIBRARY->generaltexth->translate(getEventTextID());
-}
-
-std::string CArtifact::getNameTranslated() const
-{
-	return LIBRARY->generaltexth->translate(getNameTextID());
-}
-
-std::string CArtifact::getDescriptionTextID() const
-{
-	return TextIdentifier("artifact", modScope, identifier, "description").get();
-}
-
-std::string CArtifact::getEventTextID() const
-{
-	return TextIdentifier("artifact", modScope, identifier, "event").get();
-}
-
-std::string CArtifact::getNameTextID() const
-{
-	return TextIdentifier("artifact", modScope, identifier, "name").get();
-}
-
-uint32_t CArtifact::getPrice() const
-{
-	return price;
-}
-
-CreatureID CArtifact::getWarMachine() const
-{
-	return warMachine;
-}
-
-bool CArtifact::isBig() const
-{
-	return warMachine != CreatureID::NONE;
-}
-
-bool CArtifact::isTradable() const
-{
-	switch(id.toEnum())
-	{
-	case ArtifactID::SPELLBOOK:
-		return false;
-	default:
-		return !isBig();
-	}
-}
-
-bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) const
-{
-	auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool
-	{
-		if(artSet->bearerType() == ArtBearer::HERO && ArtifactUtils::isSlotBackpack(slot))
-		{
-			if(isBig() || (!assumeDestRemoved && !ArtifactUtils::isBackpackFreeSlots(artSet)))
-				return false;
-			return true;
-		}
-
-		if(!vstd::contains(possibleSlots.at(artSet->bearerType()), slot))
-			return false;
-
-		return artSet->isPositionFree(slot, assumeDestRemoved);
-	};
-
-	auto artCanBePutAt = [this, simpleArtCanBePutAt](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool
-	{
-		if(hasParts())
-		{
-			if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved))
-				return false;
-			if(ArtifactUtils::isSlotBackpack(slot))
-				return true;
-
-			CArtifactFittingSet fittingSet(artSet->getCallback(), artSet->bearerType());
-			fittingSet.artifactsWorn = artSet->artifactsWorn;
-			if(assumeDestRemoved)
-				fittingSet.removeArtifact(slot);
-
-			for(const auto art : constituents)
-			{
-				auto possibleSlot = ArtifactUtils::getArtAnyPosition(&fittingSet, art->getId());
-				if(ArtifactUtils::isSlotEquipment(possibleSlot))
-				{
-					fittingSet.lockSlot(possibleSlot);
-				}
-				else
-				{
-					return false;
-				}
-			}
-			return true;
-		}
-		else
-		{
-			return simpleArtCanBePutAt(artSet, slot, assumeDestRemoved);
-		}
-	};
-
-	if(slot == ArtifactPosition::TRANSITION_POS)
-		return true;
-
-	if(slot == ArtifactPosition::FIRST_AVAILABLE)
-	{
-		for(const auto & slot : possibleSlots.at(artSet->bearerType()))
-		{
-			if(artCanBePutAt(artSet, slot, assumeDestRemoved))
-				return true;
-		}
-		return artCanBePutAt(artSet, ArtifactPosition::BACKPACK_START, assumeDestRemoved);
-	}
-	else if(ArtifactUtils::isSlotBackpack(slot))
-	{
-		return artCanBePutAt(artSet, ArtifactPosition::BACKPACK_START, assumeDestRemoved);
-	}
-	else
-	{
-		return artCanBePutAt(artSet, slot, assumeDestRemoved);
-	}
-}
-
-CArtifact::CArtifact()
-	: iconIndex(ArtifactID::NONE),
-	price(0)
-{
-	setNodeType(ARTIFACT);
-	possibleSlots[ArtBearer::HERO]; //we want to generate map entry even if it will be empty
-	possibleSlots[ArtBearer::CREATURE]; //we want to generate map entry even if it will be empty
-	possibleSlots[ArtBearer::COMMANDER];
-	possibleSlots[ArtBearer::ALTAR];
-}
-
-//This destructor should be placed here to avoid side effects
-CArtifact::~CArtifact() = default;
-
-int CArtifact::getArtClassSerial() const
-{
-	if(id == ArtifactID::SPELL_SCROLL)
-		return 4;
-	switch(aClass)
-	{
-	case ART_TREASURE:
-		return 0;
-	case ART_MINOR:
-		return 1;
-	case ART_MAJOR:
-		return 2;
-	case ART_RELIC:
-		return 3;
-	case ART_SPECIAL:
-		return 5;
-	}
-
-	return -1;
-}
-
-std::string CArtifact::nodeName() const
-{
-	return "Artifact: " + getNameTranslated();
-}
-
-void CArtifact::addNewBonus(const std::shared_ptr<Bonus>& b)
-{
-	b->source = BonusSource::ARTIFACT;
-	b->duration = BonusDuration::PERMANENT;
-	b->description.appendTextID(getNameTextID());
-	b->description.appendRawString(" %+d");
-	CBonusSystemNode::addNewBonus(b);
-}
-
-const std::map<ArtBearer::ArtBearer, std::vector<ArtifactPosition>> & CArtifact::getPossibleSlots() const
-{
-	return possibleSlots;
-}
-
-void CArtifact::updateFrom(const JsonNode& data)
-{
-	//TODO:CArtifact::updateFrom
-}
-
-void CArtifact::setImage(int32_t iconIndex, std::string image, std::string large)
-{
-	this->iconIndex = iconIndex;
-	this->image = image;
-	this->large = large;
-}
-
-CArtHandler::~CArtHandler() = default;
-
-std::vector<JsonNode> CArtHandler::loadLegacyData()
-{
-	size_t dataSize = LIBRARY->engineSettings()->getInteger(EGameSettings::TEXTS_ARTIFACT);
-
-	objects.resize(dataSize);
-	std::vector<JsonNode> h3Data;
-	h3Data.reserve(dataSize);
-
-	#define ART_POS(x) #x ,
-	const std::vector<std::string> artSlots = { ART_POS_LIST };
-	#undef ART_POS
-
-	static const std::map<char, std::string> classes =
-		{{'S',"SPECIAL"}, {'T',"TREASURE"},{'N',"MINOR"},{'J',"MAJOR"},{'R',"RELIC"},};
-
-	CLegacyConfigParser parser(TextPath::builtin("DATA/ARTRAITS.TXT"));
-	CLegacyConfigParser events(TextPath::builtin("DATA/ARTEVENT.TXT"));
-
-	parser.endLine(); // header
-	parser.endLine();
-
-	for (size_t i = 0; i < dataSize; i++)
-	{
-		JsonNode artData;
-
-		artData["text"]["name"].String() = parser.readString();
-		artData["text"]["event"].String() = events.readString();
-		artData["value"].Float() = parser.readNumber();
-
-		for(const auto & artSlot : artSlots)
-		{
-			if(parser.readString() == "x")
-			{
-				artData["slot"].Vector().emplace_back(artSlot);
-			}
-		}
-
-		std::string artClass = parser.readString();
-
-		if (classes.count(artClass[0]))
-			artData["class"].String() = classes.at(artClass[0]);
-		else
-			throw DataLoadingException("File ARTRAITS.TXT is invalid or corrupted! Please reinstall Heroes III data files");
-		artData["text"]["description"].String() = parser.readString();
-
-		parser.endLine();
-		events.endLine();
-		h3Data.push_back(artData);
-	}
-	return h3Data;
-}
-
-void CArtHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
-{
-	auto object = loadFromJson(scope, data, name, objects.size());
-
-	object->iconIndex = object->getIndex() + 5;
-
-	objects.emplace_back(object);
-
-	registerObject(scope, "artifact", name, object->id.getNum());
-}
-
-void CArtHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
-{
-	auto object = loadFromJson(scope, data, name, index);
-
-	object->iconIndex = object->getIndex();
-
-	assert(objects[index] == nullptr); // ensure that this id was not loaded before
-	objects[index] = object;
-
-	registerObject(scope, "artifact", name, object->id.getNum());
-}
-
-const std::vector<std::string> & CArtHandler::getTypeNames() const
-{
-	static const std::vector<std::string> typeNames = { "artifact" };
-	return typeNames;
-}
-
-std::shared_ptr<CArtifact> CArtHandler::loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index)
-{
-	assert(identifier.find(':') == std::string::npos);
-	assert(!scope.empty());
-
-	auto art = std::make_shared<CArtifact>();
-	if(!node["growing"].isNull())
-	{
-		for(auto bonus : node["growing"]["bonusesPerLevel"].Vector())
-		{
-			art->bonusesPerLevel.emplace_back(static_cast<ui16>(bonus["level"].Float()), Bonus());
-			JsonUtils::parseBonus(bonus["bonus"], &art->bonusesPerLevel.back().second);
-		}
-		for(auto bonus : node["growing"]["thresholdBonuses"].Vector())
-		{
-			art->thresholdBonuses.emplace_back(static_cast<ui16>(bonus["level"].Float()), Bonus());
-			JsonUtils::parseBonus(bonus["bonus"], &art->thresholdBonuses.back().second);
-		}
-	}
-	art->id = ArtifactID(index);
-	art->identifier = identifier;
-	art->modScope = scope;
-
-	const JsonNode & text = node["text"];
-
-	LIBRARY->generaltexth->registerString(scope, art->getNameTextID(), text["name"]);
-	LIBRARY->generaltexth->registerString(scope, art->getDescriptionTextID(), text["description"]);
-	LIBRARY->generaltexth->registerString(scope, art->getEventTextID(), text["event"]);
-
-	const JsonNode & graphics = node["graphics"];
-	art->image = graphics["image"].String();
-
-	if(!graphics["large"].isNull())
-		art->large = graphics["large"].String();
-	else
-		art->large = art->image;
-
-	art->advMapDef = graphics["map"].String();
-
-	art->price = static_cast<ui32>(node["value"].Float());
-	art->onlyOnWaterMap = node["onlyOnWaterMap"].Bool();
-
-	loadSlots(art.get(), node);
-	loadClass(art.get(), node);
-	loadType(art.get(), node);
-	loadComponents(art.get(), node);
-
-	for(const auto & b : node["bonuses"].Vector())
-	{
-		auto bonus = JsonUtils::parseBonus(b);
-		art->addNewBonus(bonus);
-	}
-
-	const JsonNode & warMachine = node["warMachine"];
-	if(!warMachine.isNull())
-	{
-		LIBRARY->identifiers()->requestIdentifier("creature", warMachine, [=](si32 id)
-		{
-			art->warMachine = CreatureID(id);
-
-			//this assumes that creature object is stored before registration
-			LIBRARY->creh->objects.at(id)->warMachine = art->id;
-		});
-	}
-
-	LIBRARY->identifiers()->requestIdentifier(scope, "object", "artifact", [=](si32 index)
-	{
-		JsonNode conf;
-		conf.setModScope(scope);
-
-		LIBRARY->objtypeh->loadSubObject(art->identifier, conf, Obj::ARTIFACT, art->getIndex());
-
-		if(!art->advMapDef.empty())
-		{
-			JsonNode templ;
-			templ["animation"].String() = art->advMapDef;
-			templ.setModScope(scope);
-
-			// add new template.
-			// Necessary for objects added via mods that don't have any templates in H3
-			LIBRARY->objtypeh->getHandlerFor(Obj::ARTIFACT, art->getIndex())->addTemplate(templ);
-		}
-	});
-
-	if(art->isTradable())
-		art->possibleSlots.at(ArtBearer::ALTAR).push_back(ArtifactPosition::ALTAR);
-
-	return art;
-}
-
-int32_t ArtifactPositionBase::decode(const std::string & slotName)
-{
-#define ART_POS(x) { #x, ArtifactPosition::x },
-	static const std::map<std::string, ArtifactPosition> artifactPositionMap = { ART_POS_LIST };
-#undef ART_POS
-	auto it = artifactPositionMap.find (slotName);
-	if (it != artifactPositionMap.end())
-		return it->second;
-	else
-		return PRE_FIRST;
-}
-
-void CArtHandler::addSlot(CArtifact * art, const std::string & slotID) const
-{
-	static const std::vector<ArtifactPosition> miscSlots =
-	{
-		ArtifactPosition::MISC1, ArtifactPosition::MISC2, ArtifactPosition::MISC3, ArtifactPosition::MISC4, ArtifactPosition::MISC5
-	};
-
-	static const std::vector<ArtifactPosition> ringSlots =
-	{
-		ArtifactPosition::RIGHT_RING, ArtifactPosition::LEFT_RING
-	};
-
-	if (slotID == "MISC")
-	{
-		vstd::concatenate(art->possibleSlots[ArtBearer::HERO], miscSlots);
-	}
-	else if (slotID == "RING")
-	{
-		vstd::concatenate(art->possibleSlots[ArtBearer::HERO], ringSlots);
-	}
-	else
-	{
-		auto slot = ArtifactPosition::decode(slotID);
-		if (slot != ArtifactPosition::PRE_FIRST)
-			art->possibleSlots[ArtBearer::HERO].push_back(slot);
-	}
-}
-
-void CArtHandler::loadSlots(CArtifact * art, const JsonNode & node) const
-{
-	if (!node["slot"].isNull()) //we assume non-hero slots are irrelevant?
-	{
-		if (node["slot"].getType() == JsonNode::JsonType::DATA_STRING)
-			addSlot(art, node["slot"].String());
-		else
-		{
-			for (const JsonNode & slot : node["slot"].Vector())
-				addSlot(art, slot.String());
-		}
-		std::sort(art->possibleSlots.at(ArtBearer::HERO).begin(), art->possibleSlots.at(ArtBearer::HERO).end());
-	}
-}
-
-CArtifact::EartClass CArtHandler::stringToClass(const std::string & className)
-{
-	static const std::map<std::string, CArtifact::EartClass> artifactClassMap =
-	{
-		{"TREASURE", CArtifact::ART_TREASURE},
-		{"MINOR", CArtifact::ART_MINOR},
-		{"MAJOR", CArtifact::ART_MAJOR},
-		{"RELIC", CArtifact::ART_RELIC},
-		{"SPECIAL", CArtifact::ART_SPECIAL}
-	};
-
-	auto it = artifactClassMap.find (className);
-	if (it != artifactClassMap.end())
-		return it->second;
-
-	logMod->warn("Warning! Artifact rarity %s not recognized!", className);
-	return CArtifact::ART_SPECIAL;
-}
-
-void CArtHandler::loadClass(CArtifact * art, const JsonNode & node) const
-{
-	art->aClass = stringToClass(node["class"].String());
-}
-
-void CArtHandler::loadType(CArtifact * art, const JsonNode & node) const
-{
-#define ART_BEARER(x) { #x, ArtBearer::x },
-	static const std::map<std::string, int> artifactBearerMap = { ART_BEARER_LIST };
-#undef ART_BEARER
-
-	for (const JsonNode & b : node["type"].Vector())
-	{
-		auto it = artifactBearerMap.find (b.String());
-		if (it != artifactBearerMap.end())
-		{
-			int bearerType = it->second;
-			switch (bearerType)
-			{
-				case ArtBearer::HERO://TODO: allow arts having several possible bearers
-					break;
-				case ArtBearer::COMMANDER:
-					makeItCommanderArt (art); //original artifacts should have only one bearer type
-					break;
-				case ArtBearer::CREATURE:
-					makeItCreatureArt (art);
-					break;
-			}
-		}
-		else
-			logMod->warn("Warning! Artifact type %s not recognized!", b.String());
-	}
-}
-
-void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node)
-{
-	if(!node["components"].isNull())
-	{
-		for(const auto & component : node["components"].Vector())
-		{
-			LIBRARY->identifiers()->requestIdentifier("artifact", component, [this, art](int32_t id)
-			{
-				// when this code is called both combinational art as well as component are loaded
-				// so it is safe to access any of them
-				art->constituents.push_back(ArtifactID(id).toArtifact());
-				objects[id]->partOf.insert(art);
-			});
-		}
-	}
-	if(!node["fusedComponents"].isNull())
-		art->setFused(node["fusedComponents"].Bool());
-}
-
-void CArtHandler::makeItCreatureArt(CArtifact * a, bool onlyCreature)
-{
-	if (onlyCreature)
-	{
-		a->possibleSlots[ArtBearer::HERO].clear();
-		a->possibleSlots[ArtBearer::COMMANDER].clear();
-	}
-	a->possibleSlots[ArtBearer::CREATURE].push_back(ArtifactPosition::CREATURE_SLOT);
-}
-
-void CArtHandler::makeItCommanderArt(CArtifact * a, bool onlyCommander)
-{
-	if (onlyCommander)
-	{
-		a->possibleSlots[ArtBearer::HERO].clear();
-		a->possibleSlots[ArtBearer::CREATURE].clear();
-	}
-	for(const auto & slot : ArtifactUtils::commanderSlots())
-		a->possibleSlots[ArtBearer::COMMANDER].push_back(ArtifactPosition(slot));
-}
-
-bool CArtHandler::legalArtifact(const ArtifactID & id) const
-{
-	auto art = id.toArtifact();
-	//assert ( (!art->constituents) || art->constituents->size() ); //artifacts is not combined or has some components
-
-	if(art->isCombined())
-		return false; //no combo artifacts spawning
-
-	if(art->aClass < CArtifact::ART_TREASURE || art->aClass > CArtifact::ART_RELIC)
-		return false; // invalid class
-
-	if(art->possibleSlots.count(ArtBearer::HERO) && !art->possibleSlots.at(ArtBearer::HERO).empty())
-		return true;
-
-	if(art->possibleSlots.count(ArtBearer::CREATURE) && !art->possibleSlots.at(ArtBearer::CREATURE).empty() && LIBRARY->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_ARTIFACT))
-		return true;
-
-	if(art->possibleSlots.count(ArtBearer::COMMANDER) && !art->possibleSlots.at(ArtBearer::COMMANDER).empty() && LIBRARY->engineSettings()->getBoolean(EGameSettings::MODULE_COMMANDERS))
-		return true;
-
-	return false;
-}
-
-std::set<ArtifactID> CArtHandler::getDefaultAllowed() const
-{
-	std::set<ArtifactID> allowedArtifacts;
-
-	for (const auto & artifact : objects)
-	{
-		if (!artifact->isCombined())
-			allowedArtifacts.insert(artifact->getId());
-	}
-	return allowedArtifacts;
-}
-
-void CArtHandler::afterLoadFinalization()
-{
-	//All artifacts have their id, so we can properly update their bonuses' source ids.
-	for(auto &art : objects)
-	{
-		for(auto &bonus : art->getExportedBonusList())
-		{
-			assert(bonus->source == BonusSource::ARTIFACT);
-			bonus->sid = BonusSourceID(art->id);
-		}
-		art->nodeHasChanged();
-	}
-}
-
-const CArtifactInstance * CArtifactSet::getArt(const ArtifactPosition & pos, bool excludeLocked) const
-{
-	if(const ArtSlotInfo * si = getSlot(pos))
-	{
-		if(si->getArt() && (!excludeLocked || !si->locked))
-			return si->getArt();
-	}
-	return nullptr;
-}
-
-ArtifactInstanceID CArtifactSet::getArtID(const ArtifactPosition & pos, bool excludeLocked) const
-{
-	if(const ArtSlotInfo * si = getSlot(pos))
-	{
-		if(si->getArt() && (!excludeLocked || !si->locked))
-			return si->getArt()->getId();
-	}
-	return {};
-}
-
-ArtifactPosition CArtifactSet::getArtPos(const ArtifactID & aid, bool onlyWorn, bool allowLocked) const
-{
-	for(const auto & [slot, slotInfo] : artifactsWorn)
-	{
-		if(slotInfo.getArt()->getTypeId() == aid && (allowLocked || !slotInfo.locked))
-			return slot;
-	}
-	if(!onlyWorn)
-	{
-		size_t backpackPositionIdx = ArtifactPosition::BACKPACK_START;
-		for(const auto & artInfo : artifactsInBackpack)
-		{
-			const auto art = artInfo.getArt();
-			if(art && art->getType()->getId() == aid)
-				return ArtifactPosition(backpackPositionIdx);
-			backpackPositionIdx++;
-		}
-	}
-	return ArtifactPosition::PRE_FIRST;
-}
-
-const CArtifactInstance * CArtifactSet::getArtByInstanceId(const ArtifactInstanceID & artInstId) const
-{
-	for(const auto & i : artifactsWorn)
-		if(i.second.getArt()->getId() == artInstId)
-			return i.second.getArt();
-
-	for(const auto & i : artifactsInBackpack)
-		if(i.getArt()->getId() == artInstId)
-			return i.getArt();
-
-	return nullptr;
-}
-
-ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance * artInst) const
-{
-	if(artInst)
-	{
-		for(const auto & slot : artInst->getType()->getPossibleSlots().at(bearerType()))
-			if(getArt(slot) == artInst)
-				return slot;
-
-		ArtifactPosition backpackSlot = ArtifactPosition::BACKPACK_START;
-		for(auto & slotInfo : artifactsInBackpack)
-		{
-			if(slotInfo.getArt() == artInst)
-				return backpackSlot;
-			backpackSlot = ArtifactPosition(backpackSlot + 1);
-		}
-	}
-	return ArtifactPosition::PRE_FIRST;
-}
-
-bool CArtifactSet::hasArt(const ArtifactID & aid, bool onlyWorn, bool searchCombinedParts) const
-{
-	if(searchCombinedParts && getCombinedArtWithPart(aid))
-		return true;
-	if(getArtPos(aid, onlyWorn, searchCombinedParts) != ArtifactPosition::PRE_FIRST)
-		return true;
-	return false;
-}
-
-CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(const ArtifactPosition & slot, const CArtifactInstance * art)
-{
-	ArtPlacementMap resArtPlacement;
-	const auto putToSlot = [this](const ArtifactPosition & targetSlot, const CArtifactInstance * targetArt, bool locked)
-	{
-		ArtSlotInfo newSlot(targetArt, locked);
-
-		if(targetSlot == ArtifactPosition::TRANSITION_POS)
-		{
-			artifactsTransitionPos = newSlot;
-		}
-		else if(ArtifactUtils::isSlotEquipment(targetSlot))
-		{
-			artifactsWorn.insert_or_assign(targetSlot, newSlot);
-		}
-		else
-		{
-			auto position = artifactsInBackpack.begin() + targetSlot - ArtifactPosition::BACKPACK_START;
-			artifactsInBackpack.insert(position, newSlot);
-		}
-	};
-
-	putToSlot(slot, art, false);
-	if(art->getType()->isCombined() && ArtifactUtils::isSlotEquipment(slot))
-	{
-		const CArtifactInstance * mainPart = nullptr;
-		for(const auto & part : art->getPartsInfo())
-			if(vstd::contains(part.getArtifact()->getType()->getPossibleSlots().at(bearerType()), slot)
-				&& (part.slot == ArtifactPosition::PRE_FIRST))
-			{
-				mainPart = part.getArtifact();
-				break;
-			}
-		
-		for(const auto & part : art->getPartsInfo())
-		{
-			if(part.getArtifact() != mainPart)
-			{
-				auto partSlot = part.slot;
-				if(!part.getArtifact()->getType()->canBePutAt(this, partSlot))
-					partSlot = ArtifactUtils::getArtAnyPosition(this, part.getArtifact()->getTypeId());
-
-				assert(ArtifactUtils::isSlotEquipment(partSlot));
-				putToSlot(partSlot, part.getArtifact(), true);
-				resArtPlacement.emplace(part.getArtifact(), partSlot);
-			}
-			else
-			{
-				resArtPlacement.emplace(part.getArtifact(), part.slot);
-			}
-		}
-	}
-	return resArtPlacement;
-}
-
-CArtifactSet::CArtifactSet(IGameCallback * cb)
-	:artifactsTransitionPos(cb)
-{}
-
-void CArtifactSet::removeArtifact(const ArtifactPosition & slot)
-{
-	const auto eraseArtSlot = [this](const ArtifactPosition & slotForErase)
-	{
-		if(slotForErase == ArtifactPosition::TRANSITION_POS)
-		{
-			artifactsTransitionPos.artifactID = {};
-		}
-		else if(ArtifactUtils::isSlotBackpack(slotForErase))
-		{
-			auto backpackSlot = ArtifactPosition(slotForErase - ArtifactPosition::BACKPACK_START);
-
-			assert(artifactsInBackpack.begin() + backpackSlot < artifactsInBackpack.end());
-			artifactsInBackpack.erase(artifactsInBackpack.begin() + backpackSlot);
-		}
-		else
-		{
-			artifactsWorn.erase(slotForErase);
-		}
-	};
-
-	if(const auto art = getArt(slot, false))
-	{
-		if(art->isCombined())
-		{
-			for(const auto & part : art->getPartsInfo())
-			{
-				if(part.slot != ArtifactPosition::PRE_FIRST)
-				{
-					assert(getArt(part.slot, false));
-					assert(getArt(part.slot, false) == part.getArtifact());
-				}
-				eraseArtSlot(part.slot);
-			}
-		}
-		eraseArtSlot(slot);
-	}
-}
-
-const CArtifactInstance * CArtifactSet::getCombinedArtWithPart(const ArtifactID & partId) const
-{
-	for(const auto & slot : artifactsInBackpack)
-	{
-		auto art = slot.getArt();
-		if(art->isCombined())
-		{
-			for(auto & ci : art->getPartsInfo())
-			{
-				if(ci.getArtifact()->getTypeId() == partId)
-					return art;
-			}
-		}
-	}
-	return nullptr;
-}
-
-const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const
-{
-	if(pos == ArtifactPosition::TRANSITION_POS)
-		return &artifactsTransitionPos;
-	if(vstd::contains(artifactsWorn, pos))
-		return &artifactsWorn.at(pos);
-	if(ArtifactUtils::isSlotBackpack(pos))
-	{
-		auto backpackPos = pos - ArtifactPosition::BACKPACK_START;
-		if(backpackPos < 0 || backpackPos >= artifactsInBackpack.size())
-			return nullptr;
-		else
-			return &artifactsInBackpack[backpackPos];
-	}
-
-	return nullptr;
-}
-
-void CArtifactSet::lockSlot(const ArtifactPosition & pos)
-{
-	if(pos == ArtifactPosition::TRANSITION_POS)
-		artifactsTransitionPos.locked = true;
-	else if(ArtifactUtils::isSlotEquipment(pos))
-		artifactsWorn.at(pos).locked = true;
-	else
-	{
-		assert(artifactsInBackpack.size() > pos - ArtifactPosition::BACKPACK_START);
-		(artifactsInBackpack.begin() + pos - ArtifactPosition::BACKPACK_START)->locked = true;
-	}
-}
-
-bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck) const
-{
-	if(bearerType() == ArtBearer::ALTAR)
-		return artifactsInBackpack.size() < GameConstants::ALTAR_ARTIFACTS_SLOTS;
-
-	if(const ArtSlotInfo *s = getSlot(pos))
-		return (onlyLockCheck || !s->getArt()) && !s->locked;
-
-	return true; //no slot means not used
-}
-
-void CArtifactSet::artDeserializationFix(CGameState & gs, CBonusSystemNode *node)
-{
-	for(auto & elem : artifactsWorn)
-		if(elem.second.artifactID.hasValue() && !elem.second.locked)
-			node->attachToSource(*gs.getArtInstance(elem.second.artifactID));
-}
-
-void CArtifactSet::serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map)
-{
-	//todo: creature and commander artifacts
-	if(handler.saving && artifactsInBackpack.empty() && artifactsWorn.empty())
-		return;
-
-	if(!handler.saving)
-	{
-		artifactsInBackpack.clear();
-		artifactsWorn.clear();
-	}
-
-	auto s = handler.enterStruct(fieldName);
-
-	switch(bearerType())
-	{
-	case ArtBearer::HERO:
-		serializeJsonHero(handler, map);
-		break;
-	case ArtBearer::CREATURE:
-		serializeJsonCreature(handler);
-		break;
-	case ArtBearer::COMMANDER:
-		serializeJsonCommander(handler);
-		break;
-	default:
-		assert(false);
-		break;
-	}
-}
-
-void CArtifactSet::serializeJsonHero(JsonSerializeFormat & handler, CMap * map)
-{
-	for(const auto & slot : ArtifactUtils::allWornSlots())
-	{
-		serializeJsonSlot(handler, slot, map);
-	}
-
-	std::vector<ArtifactID> backpackTemp;
-
-	if(handler.saving)
-	{
-		backpackTemp.reserve(artifactsInBackpack.size());
-		for(const ArtSlotInfo & info : artifactsInBackpack)
-			backpackTemp.push_back(info.getArt()->getTypeId());
-	}
-	handler.serializeIdArray(NArtifactPosition::backpack, backpackTemp);
-	if(!handler.saving)
-	{
-		for(const ArtifactID & artifactID : backpackTemp)
-		{
-			auto * artifact = map->createArtifact(artifactID);
-			auto slot = ArtifactPosition::BACKPACK_START + artifactsInBackpack.size();
-			if(artifact->getType()->canBePutAt(this, slot))
-			{
-				auto artsMap = putArtifact(slot, artifact);
-				artifact->addPlacementMap(artsMap);
-			}
-		}
-	}
-}
-
-void CArtifactSet::serializeJsonCreature(JsonSerializeFormat & handler)
-{
-	logGlobal->error("CArtifactSet::serializeJsonCreature not implemented");
-}
-
-void CArtifactSet::serializeJsonCommander(JsonSerializeFormat & handler)
-{
-	logGlobal->error("CArtifactSet::serializeJsonCommander not implemented");
-}
-
-void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const ArtifactPosition & slot, CMap * map)
-{
-	ArtifactID artifactID;
-
-	if(handler.saving)
-	{
-		const ArtSlotInfo * info = getSlot(slot);
-
-		if(info != nullptr && !info->locked)
-		{
-			artifactID = info->getArt()->getTypeId();
-			handler.serializeId(NArtifactPosition::namesHero[slot.num], artifactID, ArtifactID::NONE);
-		}
-	}
-	else
-	{
-		handler.serializeId(NArtifactPosition::namesHero[slot.num], artifactID, ArtifactID::NONE);
-
-		if(artifactID != ArtifactID::NONE)
-		{
-			auto * artifact = map->createArtifact(artifactID.toEnum());
-
-			if(artifact->getType()->canBePutAt(this, slot))
-			{
-				auto artsMap = putArtifact(slot, artifact);
-				artifact->addPlacementMap(artsMap);
-			}
-			else
-			{
-				logGlobal->debug("Artifact can't be put at the specified location."); //TODO add more debugging information
-			}
-		}
-	}
-}
-
-CArtifactFittingSet::CArtifactFittingSet(IGameCallback *cb, ArtBearer::ArtBearer bearer)
-	: CArtifactSet(cb)
-	, GameCallbackHolder(cb)
-	, bearer(bearer)
-{
-}
-
-CArtifactFittingSet::CArtifactFittingSet(const CArtifactSet & artSet)
-	: CArtifactFittingSet(artSet.getCallback(), artSet.bearerType())
-{
-	artifactsWorn = artSet.artifactsWorn;
-	artifactsInBackpack = artSet.artifactsInBackpack;
-	artifactsTransitionPos = artSet.artifactsTransitionPos;
-}
-
-ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const
-{
-	return this->bearer;
-}
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 180
lib/CArtHandler.h

@@ -1,180 +0,0 @@
-/*
- * CArtHandler.h, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#pragma once
-
-#include <vcmi/Artifact.h>
-#include <vcmi/ArtifactService.h>
-
-#include "bonuses/Bonus.h"
-#include "bonuses/CBonusSystemNode.h"
-#include "IHandlerBase.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-class CArtHandler;
-class CGHeroInstance;
-class CMap;
-class CGameState;
-class CArtifactSet;
-class CArtifactInstance;
-class JsonSerializeFormat;
-
-#define ART_BEARER_LIST \
-	ART_BEARER(HERO)\
-	ART_BEARER(CREATURE)\
-	ART_BEARER(COMMANDER)\
-	ART_BEARER(ALTAR)
-
-namespace ArtBearer
-{
-	enum ArtBearer
-	{
-#define ART_BEARER(x) x,
-		ART_BEARER_LIST
-#undef ART_BEARER
-	};
-}
-
-class DLL_LINKAGE CCombinedArtifact
-{
-protected:
-	CCombinedArtifact() : fused(false) {};
-
-	std::vector<const CArtifact*> constituents; // Artifacts IDs a combined artifact consists of, or nullptr.
-	std::set<const CArtifact*> partOf; // Reverse map of constituents - combined arts that include this art
-	bool fused;
-
-public:
-	bool isCombined() const;
-	const std::vector<const CArtifact*> & getConstituents() const;
-	const std::set<const CArtifact*> & getPartOf() const;
-	void setFused(bool isFused);
-	bool isFused() const;
-	bool hasParts() const;
-};
-
-class DLL_LINKAGE CScrollArtifact
-{
-protected:
-	CScrollArtifact() = default;
-public:
-	bool isScroll() const;
-};
-
-class DLL_LINKAGE CGrowingArtifact
-{
-protected:
-	CGrowingArtifact() = default;
-
-	std::vector <std::pair<ui16, Bonus>> bonusesPerLevel; // Bonus given each n levels
-	std::vector <std::pair<ui16, Bonus>> thresholdBonuses; // After certain level they will be added once
-public:
-	bool isGrowing() const;
-
-	std::vector <std::pair<ui16, Bonus>> & getBonusesPerLevel();
-	const std::vector <std::pair<ui16, Bonus>> & getBonusesPerLevel() const;
-	std::vector <std::pair<ui16, Bonus>> & getThresholdBonuses();
-	const std::vector <std::pair<ui16, Bonus>> & getThresholdBonuses() const;
-};
-
-// Container for artifacts. Not for instances.
-class DLL_LINKAGE CArtifact
-	: public Artifact, public CBonusSystemNode, public CCombinedArtifact, public CScrollArtifact, public CGrowingArtifact
-{
-	ArtifactID id;
-	std::string image;
-	std::string large; // big image for custom artifacts, used in drag & drop
-	std::string advMapDef; // used for adventure map object
-	std::string modScope;
-	std::string identifier;
-	int32_t iconIndex;
-	uint32_t price;
-	CreatureID warMachine;
-	// Bearer Type => ids of slots where artifact can be placed
-	std::map<ArtBearer::ArtBearer, std::vector<ArtifactPosition>> possibleSlots;
-
-public:
-	enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes
-
-	EartClass aClass = ART_SPECIAL;
-	bool onlyOnWaterMap;
-
-	int32_t getIndex() const override;
-	int32_t getIconIndex() const override;
-	std::string getJsonKey() const override;
-	std::string getModScope() const override;
-	void registerIcons(const IconRegistar & cb) const override;
-	ArtifactID getId() const override;
-	const IBonusBearer * getBonusBearer() const override;
-
-	std::string getDescriptionTranslated() const override;
-	std::string getEventTranslated() const override;
-	std::string getNameTranslated() const override;
-
-	std::string getDescriptionTextID() const override;
-	std::string getEventTextID() const override;
-	std::string getNameTextID() const override;
-
-	uint32_t getPrice() const override;
-	CreatureID getWarMachine() const override;
-	bool isBig() const override;
-	bool isTradable() const override;
-
-	int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
-	std::string nodeName() const override;
-	void addNewBonus(const std::shared_ptr<Bonus>& b) override;
-	const std::map<ArtBearer::ArtBearer, std::vector<ArtifactPosition>> & getPossibleSlots() const;
-
-	virtual bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE,
-		bool assumeDestRemoved = false) const;
-	void updateFrom(const JsonNode & data);
-	// Is used for testing purposes only
-	void setImage(int32_t iconIndex, std::string image, std::string large);
-
-	CArtifact();
-	~CArtifact();
-
-	friend class CArtHandler;
-};
-
-class DLL_LINKAGE CArtHandler : public CHandlerBase<ArtifactID, Artifact, CArtifact, ArtifactService>
-{
-public:
-	void addBonuses(CArtifact *art, const JsonNode &bonusList);
-
-	static CArtifact::EartClass stringToClass(const std::string & className); //TODO: rework EartClass to make this a constructor
-
-	bool legalArtifact(const ArtifactID & id) const;
-	static void makeItCreatureArt(CArtifact * a, bool onlyCreature = true);
-	static void makeItCommanderArt(CArtifact * a, bool onlyCommander = true);
-
-	~CArtHandler();
-
-	std::vector<JsonNode> loadLegacyData() override;
-
-	void loadObject(std::string scope, std::string name, const JsonNode & data) override;
-	void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
-	void afterLoadFinalization() override;
-
-	std::set<ArtifactID> getDefaultAllowed() const;
-
-protected:
-	const std::vector<std::string> & getTypeNames() const override;
-	std::shared_ptr<CArtifact> loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index) override;
-
-private:
-	void addSlot(CArtifact * art, const std::string & slotID) const;
-	void loadSlots(CArtifact * art, const JsonNode & node) const;
-	void loadClass(CArtifact * art, const JsonNode & node) const;
-	void loadType(CArtifact * art, const JsonNode & node) const;
-	void loadComponents(CArtifact * art, const JsonNode & node);
-};
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 1
lib/CCreatureSet.cpp

@@ -10,7 +10,6 @@
 #include "StdInc.h"
 #include "CCreatureSet.h"
 
-#include "ArtifactUtils.h"
 #include "CConfigHandler.h"
 #include "CCreatureHandler.h"
 #include "GameLibrary.h"

+ 1 - 2
lib/CCreatureSet.h

@@ -9,8 +9,6 @@
  */
 #pragma once
 
-#include "CArtifactSet.h"
-#include "CArtifactInstance.h"
 #include "CCreatureHandler.h"
 #include "GameCallbackHolder.h"
 #include "GameConstants.h"
@@ -19,6 +17,7 @@
 #include "bonuses/CBonusSystemNode.h"
 #include "serializer/Serializeable.h"
 #include "mapObjects/CGObjectInstance.h"
+#include "entities/artifact/CArtifactSet.h"
 
 #include <vcmi/Entity.h>
 

+ 16 - 7
lib/CMakeLists.txt

@@ -83,6 +83,13 @@ set(lib_MAIN_SRCS
 
 	constants/EntityIdentifiers.cpp
 
+	entities/artifact/ArtifactUtils.cpp
+	entities/artifact/ArtSlotInfo.cpp
+	entities/artifact/CArtHandler.cpp
+	entities/artifact/CArtifact.cpp
+	entities/artifact/CArtifactFittingSet.cpp
+	entities/artifact/CArtifactInstance.cpp
+	entities/artifact/CArtifactSet.cpp
 	entities/building/CBuilding.cpp
 	entities/building/CBuildingHandler.cpp
 	entities/faction/CFaction.cpp
@@ -266,12 +273,9 @@ set(lib_MAIN_SRCS
 	texts/MetaString.cpp
 	texts/TextLocalizationContainer.cpp
 
-	ArtifactUtils.cpp
 	BasicTypes.cpp
 	BattleFieldHandler.cpp
 	CAndroidVMHelper.cpp
-	CArtHandler.cpp
-	CArtifactInstance.cpp
 	CBonusTypeHandler.cpp
 	CCreatureHandler.cpp
 	CCreatureSet.cpp
@@ -459,6 +463,15 @@ set(lib_MAIN_HEADERS
 	constants/NumericConstants.h
 	constants/StringConstants.h
 
+	entities/artifact/ArtBearer.h
+	entities/artifact/ArtifactUtils.h
+	entities/artifact/ArtSlotInfo.h
+	entities/artifact/CArtHandler.h
+	entities/artifact/CArtifact.h
+	entities/artifact/CArtifactInstance.h
+	entities/artifact/CArtifactFittingSet.h
+	entities/artifact/CArtifactSet.h
+	entities/artifact/EArtifactClass.h
 	entities/building/CBuilding.h
 	entities/building/CBuildingHandler.h
 	entities/building/TownFortifications.h
@@ -686,13 +699,9 @@ set(lib_MAIN_HEADERS
 	texts/TextLocalizationContainer.h
 
 	AI_Base.h
-	ArtifactUtils.h
 	AsyncRunner.h
 	BattleFieldHandler.h
 	CAndroidVMHelper.h
-	CArtHandler.h
-	CArtifactInstance.h
-	CArtifactSet.h
 	CBonusTypeHandler.h
 	CCreatureHandler.h
 	CCreatureSet.h

+ 1 - 1
lib/GameLibrary.cpp

@@ -11,7 +11,6 @@
 #include "StdInc.h"
 #include "GameLibrary.h"
 
-#include "CArtHandler.h"
 #include "CBonusTypeHandler.h"
 #include "CCreatureHandler.h"
 #include "CConfigHandler.h"
@@ -21,6 +20,7 @@
 #include "spells/CSpellHandler.h"
 #include "spells/effects/Registry.h"
 #include "CSkillHandler.h"
+#include "entities/artifact/CArtHandler.h"
 #include "entities/faction/CTownHandler.h"
 #include "entities/hero/CHeroClassHandler.h"
 #include "entities/hero/CHeroHandler.h"

+ 4 - 3
lib/IGameCallback.cpp

@@ -18,6 +18,7 @@
 #include "bonuses/Limiters.h"
 #include "bonuses/Propagators.h"
 #include "bonuses/Updaters.h"
+#include "entities/artifact/CArtifact.h"
 #include "entities/building/CBuilding.h"
 #include "entities/hero/CHero.h"
 #include "networkPacks/ArtifactLocation.h"
@@ -151,11 +152,11 @@ void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3> & tiles, std:
 void CPrivilegedInfoCallback::pickAllowedArtsSet(std::vector<ArtifactID> & out, vstd::RNG & rand)
 {
 	for (int j = 0; j < 3 ; j++)
-		out.push_back(gameState().pickRandomArtifact(rand, CArtifact::ART_TREASURE));
+		out.push_back(gameState().pickRandomArtifact(rand, EArtifactClass::ART_TREASURE));
 	for (int j = 0; j < 3 ; j++)
-		out.push_back(gameState().pickRandomArtifact(rand, CArtifact::ART_MINOR));
+		out.push_back(gameState().pickRandomArtifact(rand, EArtifactClass::ART_MINOR));
 
-	out.push_back(gameState().pickRandomArtifact(rand, CArtifact::ART_MAJOR));
+	out.push_back(gameState().pickRandomArtifact(rand, EArtifactClass::ART_MAJOR));
 }
 
 void CPrivilegedInfoCallback::getAllowedSpells(std::vector<SpellID> & out, std::optional<ui16> level)

+ 1 - 0
lib/battle/BattleInfo.cpp

@@ -15,6 +15,7 @@
 #include "bonuses/Limiters.h"
 #include "bonuses/Updaters.h"
 #include "../CStack.h"
+#include "../entities/artifact/CArtifact.h"
 #include "../entities/building/TownFortifications.h"
 #include "../filesystem/Filesystem.h"
 #include "../GameLibrary.h"

+ 0 - 1
lib/bonuses/Bonus.cpp

@@ -14,7 +14,6 @@
 #include "Updaters.h"
 #include "Propagators.h"
 
-#include "../CArtHandler.h"
 #include "../CCreatureHandler.h"
 #include "../CCreatureSet.h"
 #include "../CSkillHandler.h"

+ 0 - 1
lib/bonuses/Limiters.cpp

@@ -21,7 +21,6 @@
 #include "../texts/CGeneralTextHandler.h"
 #include "../CSkillHandler.h"
 #include "../CStack.h"
-#include "../CArtHandler.h"
 #include "../TerrainHandler.h"
 #include "../constants/StringConstants.h"
 #include "../battle/BattleInfo.h"

+ 1 - 1
lib/constants/EntityIdentifiers.cpp

@@ -29,10 +29,10 @@
 #include "modding/IdentifierStorage.h"
 #include "modding/ModScope.h"
 #include "GameLibrary.h"
-#include "CArtHandler.h"//todo: remove
 #include "CCreatureHandler.h"//todo: remove
 #include "spells/CSpellHandler.h" //todo: remove
 #include "CSkillHandler.h"//todo: remove
+#include "entities/artifact/CArtifact.h"
 #include "entities/faction/CFaction.h"
 #include "entities/hero/CHero.h"
 #include "entities/hero/CHeroClass.h"

+ 30 - 0
lib/entities/artifact/ArtBearer.h

@@ -0,0 +1,30 @@
+/*
+ * ArtBearer.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+#define ART_BEARER_LIST \
+ART_BEARER(HERO)\
+	ART_BEARER(CREATURE)\
+	ART_BEARER(COMMANDER)\
+	ART_BEARER(ALTAR)
+
+namespace ArtBearer
+{
+	enum ArtBearer
+	{
+#define ART_BEARER(x) x,
+		ART_BEARER_LIST
+#undef ART_BEARER
+	};
+}
+
+VCMI_LIB_NAMESPACE_END

+ 42 - 0
lib/entities/artifact/ArtSlotInfo.cpp

@@ -0,0 +1,42 @@
+/*
+ * ArtSlotInfo.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#include "StdInc.h"
+#include "ArtSlotInfo.h"
+
+#include "../../IGameCallback.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+ArtSlotInfo::ArtSlotInfo(IGameCallback * cb)
+	: GameCallbackHolder(cb)
+{
+}
+
+ArtSlotInfo::ArtSlotInfo(const CArtifactInstance * artifact, bool locked)
+	: GameCallbackHolder(artifact->cb)
+	, artifactID(artifact->getId())
+	, locked(locked)
+{
+}
+
+const CArtifactInstance * ArtSlotInfo::getArt() const
+{
+	if(!artifactID.hasValue())
+		return nullptr;
+	return cb->getArtInstance(artifactID);
+}
+
+ArtifactInstanceID ArtSlotInfo::getID() const
+{
+	return artifactID;
+}
+
+VCMI_LIB_NAMESPACE_END

+ 49 - 0
lib/entities/artifact/ArtSlotInfo.h

@@ -0,0 +1,49 @@
+/*
+ * ArtSlotInfo.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "CArtifactInstance.h"
+
+#include "../../constants/EntityIdentifiers.h"
+#include "../../GameCallbackHolder.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+struct DLL_LINKAGE ArtSlotInfo : public GameCallbackHolder
+{
+	ArtifactInstanceID artifactID;
+	bool locked = false; //if locked, then artifact points to the combined artifact
+
+	explicit ArtSlotInfo(IGameCallback * cb);
+	ArtSlotInfo(const CArtifactInstance * artifact, bool locked);
+
+	const CArtifactInstance * getArt() const;
+	ArtifactInstanceID getID() const;
+
+	template<typename Handler>
+	void serialize(Handler & h)
+	{
+		if(h.saving || h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
+		{
+			h & artifactID;
+		}
+		else
+		{
+			std::shared_ptr<CArtifactInstance> pointer;
+			h & pointer;
+			if(pointer->getId() == ArtifactInstanceID())
+				CArtifactInstance::saveCompatibilityFixArtifactID(pointer);
+			artifactID = pointer->getId();
+		}
+		h & locked;
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 11 - 6
lib/ArtifactUtils.cpp → lib/entities/artifact/ArtifactUtils.cpp

@@ -8,13 +8,18 @@
  *
  */
 
+#include "StdInc.h"
 #include "ArtifactUtils.h"
 
-#include "CArtHandler.h"
-#include "IGameSettings.h"
-#include "spells/CSpellHandler.h"
-#include "GameLibrary.h"
-#include "mapObjects/CGHeroInstance.h"
+#include "ArtBearer.h"
+#include "CArtifact.h"
+#include "CArtifactFittingSet.h"
+
+#include "../../IGameSettings.h"
+#include "../../GameLibrary.h"
+#include "../../mapObjects/CGHeroInstance.h"
+
+#include <vcmi/spells/Spell.h>
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -234,7 +239,7 @@ DLL_LINKAGE void ArtifactUtils::insertScrrollSpellName(std::string & description
 	if(nameStart != std::string::npos && nameEnd != std::string::npos)
 	{
 		if(sid.getNum() >= 0)
-			description = description.replace(nameStart, nameEnd - nameStart + 1, sid.toEntity(LIBRARY->spells())->getNameTranslated());
+			description = description.replace(nameStart, nameEnd - nameStart + 1, sid.toEntity(LIBRARY)->getNameTranslated());
 		else
 			description = description.erase(nameStart, nameEnd - nameStart + 2); // erase "[spell name] " - including space
 	}

+ 1 - 6
lib/ArtifactUtils.h → lib/entities/artifact/ArtifactUtils.h

@@ -9,17 +9,12 @@
  */
 #pragma once
 
-#include "StdInc.h"
-
-#include "GameConstants.h"
+#include "../../constants/EntityIdentifiers.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class CArtHandler;
-class CArtifact;
 class CGHeroInstance;
 class CArtifactSet;
-class CArtifactInstance;
 struct ArtSlotInfo;
 
 namespace ArtifactUtils

+ 424 - 0
lib/entities/artifact/CArtHandler.cpp

@@ -0,0 +1,424 @@
+/*
+ * CArtHandler.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#include "StdInc.h"
+
+#include "CArtHandler.h"
+
+#include "ArtifactUtils.h"
+
+#include "../../CCreatureHandler.h"
+#include "../../ExceptionsCommon.h"
+#include "../../GameLibrary.h"
+#include "../../IGameSettings.h"
+#include "../../json/JsonBonus.h"
+
+#include "../../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../../mapObjectConstructors/CObjectClassesHandler.h"
+#include "../../modding/IdentifierStorage.h"
+#include "../../texts/CGeneralTextHandler.h"
+#include "../../texts/CLegacyConfigParser.h"
+
+// Note: list must match entries in ArtTraits.txt
+#define ART_POS_LIST    \
+	ART_POS(SPELLBOOK)  \
+	ART_POS(MACH4)      \
+	ART_POS(MACH3)      \
+	ART_POS(MACH2)      \
+	ART_POS(MACH1)      \
+	ART_POS(MISC5)      \
+	ART_POS(MISC4)      \
+	ART_POS(MISC3)      \
+	ART_POS(MISC2)      \
+	ART_POS(MISC1)      \
+	ART_POS(FEET)       \
+	ART_POS(LEFT_RING)  \
+	ART_POS(RIGHT_RING) \
+	ART_POS(TORSO)      \
+	ART_POS(LEFT_HAND)  \
+	ART_POS(RIGHT_HAND) \
+	ART_POS(NECK)       \
+	ART_POS(SHOULDERS)  \
+	ART_POS(HEAD)
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+CArtHandler::~CArtHandler() = default;
+
+std::vector<JsonNode> CArtHandler::loadLegacyData()
+{
+	size_t dataSize = LIBRARY->engineSettings()->getInteger(EGameSettings::TEXTS_ARTIFACT);
+
+	objects.resize(dataSize);
+	std::vector<JsonNode> h3Data;
+	h3Data.reserve(dataSize);
+
+	#define ART_POS(x) #x ,
+	const std::vector<std::string> artSlots = { ART_POS_LIST };
+	#undef ART_POS
+
+	static const std::map<char, std::string> classes =
+		{{'S',"SPECIAL"}, {'T',"TREASURE"},{'N',"MINOR"},{'J',"MAJOR"},{'R',"RELIC"},};
+
+	CLegacyConfigParser parser(TextPath::builtin("DATA/ARTRAITS.TXT"));
+	CLegacyConfigParser events(TextPath::builtin("DATA/ARTEVENT.TXT"));
+
+	parser.endLine(); // header
+	parser.endLine();
+
+	for (size_t i = 0; i < dataSize; i++)
+	{
+		JsonNode artData;
+
+		artData["text"]["name"].String() = parser.readString();
+		artData["text"]["event"].String() = events.readString();
+		artData["value"].Float() = parser.readNumber();
+
+		for(const auto & artSlot : artSlots)
+		{
+			if(parser.readString() == "x")
+			{
+				artData["slot"].Vector().emplace_back(artSlot);
+			}
+		}
+
+		std::string artClass = parser.readString();
+
+		if (classes.count(artClass[0]))
+			artData["class"].String() = classes.at(artClass[0]);
+		else
+			throw DataLoadingException("File ARTRAITS.TXT is invalid or corrupted! Please reinstall Heroes III data files");
+		artData["text"]["description"].String() = parser.readString();
+
+		parser.endLine();
+		events.endLine();
+		h3Data.push_back(artData);
+	}
+	return h3Data;
+}
+
+void CArtHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
+{
+	auto object = loadFromJson(scope, data, name, objects.size());
+
+	object->iconIndex = object->getIndex() + 5;
+
+	objects.emplace_back(object);
+
+	registerObject(scope, "artifact", name, object->id.getNum());
+}
+
+void CArtHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
+{
+	auto object = loadFromJson(scope, data, name, index);
+
+	object->iconIndex = object->getIndex();
+
+	assert(objects[index] == nullptr); // ensure that this id was not loaded before
+	objects[index] = object;
+
+	registerObject(scope, "artifact", name, object->id.getNum());
+}
+
+const std::vector<std::string> & CArtHandler::getTypeNames() const
+{
+	static const std::vector<std::string> typeNames = { "artifact" };
+	return typeNames;
+}
+
+std::shared_ptr<CArtifact> CArtHandler::loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index)
+{
+	assert(identifier.find(':') == std::string::npos);
+	assert(!scope.empty());
+
+	auto art = std::make_shared<CArtifact>();
+	if(!node["growing"].isNull())
+	{
+		for(auto bonus : node["growing"]["bonusesPerLevel"].Vector())
+		{
+			art->bonusesPerLevel.emplace_back(static_cast<ui16>(bonus["level"].Float()), Bonus());
+			JsonUtils::parseBonus(bonus["bonus"], &art->bonusesPerLevel.back().second);
+		}
+		for(auto bonus : node["growing"]["thresholdBonuses"].Vector())
+		{
+			art->thresholdBonuses.emplace_back(static_cast<ui16>(bonus["level"].Float()), Bonus());
+			JsonUtils::parseBonus(bonus["bonus"], &art->thresholdBonuses.back().second);
+		}
+	}
+	art->id = ArtifactID(index);
+	art->identifier = identifier;
+	art->modScope = scope;
+
+	const JsonNode & text = node["text"];
+
+	LIBRARY->generaltexth->registerString(scope, art->getNameTextID(), text["name"]);
+	LIBRARY->generaltexth->registerString(scope, art->getDescriptionTextID(), text["description"]);
+	LIBRARY->generaltexth->registerString(scope, art->getEventTextID(), text["event"]);
+
+	const JsonNode & graphics = node["graphics"];
+	art->image = graphics["image"].String();
+
+	if(!graphics["large"].isNull())
+		art->large = graphics["large"].String();
+	else
+		art->large = art->image;
+
+	art->advMapDef = graphics["map"].String();
+
+	art->price = static_cast<ui32>(node["value"].Float());
+	art->onlyOnWaterMap = node["onlyOnWaterMap"].Bool();
+
+	loadSlots(art.get(), node);
+	loadClass(art.get(), node);
+	loadType(art.get(), node);
+	loadComponents(art.get(), node);
+
+	for(const auto & b : node["bonuses"].Vector())
+	{
+		auto bonus = JsonUtils::parseBonus(b);
+		art->addNewBonus(bonus);
+	}
+
+	const JsonNode & warMachine = node["warMachine"];
+	if(!warMachine.isNull())
+	{
+		LIBRARY->identifiers()->requestIdentifier("creature", warMachine, [=](si32 id)
+		{
+			art->warMachine = CreatureID(id);
+
+			//this assumes that creature object is stored before registration
+			LIBRARY->creh->objects.at(id)->warMachine = art->id;
+		});
+	}
+
+	LIBRARY->identifiers()->requestIdentifier(scope, "object", "artifact", [=](si32 index)
+	{
+		JsonNode conf;
+		conf.setModScope(scope);
+
+		LIBRARY->objtypeh->loadSubObject(art->identifier, conf, Obj::ARTIFACT, art->getIndex());
+
+		if(!art->advMapDef.empty())
+		{
+			JsonNode templ;
+			templ["animation"].String() = art->advMapDef;
+			templ.setModScope(scope);
+
+			// add new template.
+			// Necessary for objects added via mods that don't have any templates in H3
+			LIBRARY->objtypeh->getHandlerFor(Obj::ARTIFACT, art->getIndex())->addTemplate(templ);
+		}
+	});
+
+	if(art->isTradable())
+		art->possibleSlots.at(ArtBearer::ALTAR).push_back(ArtifactPosition::ALTAR);
+
+	return art;
+}
+
+int32_t ArtifactPositionBase::decode(const std::string & slotName)
+{
+#define ART_POS(x) { #x, ArtifactPosition::x },
+	static const std::map<std::string, ArtifactPosition> artifactPositionMap = { ART_POS_LIST };
+#undef ART_POS
+	auto it = artifactPositionMap.find (slotName);
+	if (it != artifactPositionMap.end())
+		return it->second;
+	else
+		return PRE_FIRST;
+}
+
+void CArtHandler::addSlot(CArtifact * art, const std::string & slotID) const
+{
+	static const std::vector<ArtifactPosition> miscSlots =
+	{
+		ArtifactPosition::MISC1, ArtifactPosition::MISC2, ArtifactPosition::MISC3, ArtifactPosition::MISC4, ArtifactPosition::MISC5
+	};
+
+	static const std::vector<ArtifactPosition> ringSlots =
+	{
+		ArtifactPosition::RIGHT_RING, ArtifactPosition::LEFT_RING
+	};
+
+	if (slotID == "MISC")
+	{
+		vstd::concatenate(art->possibleSlots[ArtBearer::HERO], miscSlots);
+	}
+	else if (slotID == "RING")
+	{
+		vstd::concatenate(art->possibleSlots[ArtBearer::HERO], ringSlots);
+	}
+	else
+	{
+		auto slot = ArtifactPosition::decode(slotID);
+		if (slot != ArtifactPosition::PRE_FIRST)
+			art->possibleSlots[ArtBearer::HERO].push_back(slot);
+	}
+}
+
+void CArtHandler::loadSlots(CArtifact * art, const JsonNode & node) const
+{
+	if (!node["slot"].isNull()) //we assume non-hero slots are irrelevant?
+	{
+		if (node["slot"].getType() == JsonNode::JsonType::DATA_STRING)
+			addSlot(art, node["slot"].String());
+		else
+		{
+			for (const JsonNode & slot : node["slot"].Vector())
+				addSlot(art, slot.String());
+		}
+		std::sort(art->possibleSlots.at(ArtBearer::HERO).begin(), art->possibleSlots.at(ArtBearer::HERO).end());
+	}
+}
+
+EArtifactClass::Type CArtHandler::stringToClass(const std::string & className)
+{
+	static const std::map<std::string, EArtifactClass::Type> artifactClassMap =
+	{
+		{"TREASURE", EArtifactClass::ART_TREASURE},
+		{"MINOR", EArtifactClass::ART_MINOR},
+		{"MAJOR", EArtifactClass::ART_MAJOR},
+		{"RELIC", EArtifactClass::ART_RELIC},
+		{"SPECIAL", EArtifactClass::ART_SPECIAL}
+	};
+
+	auto it = artifactClassMap.find (className);
+	if (it != artifactClassMap.end())
+		return it->second;
+
+	logMod->warn("Warning! Artifact rarity %s not recognized!", className);
+	return EArtifactClass::ART_SPECIAL;
+}
+
+void CArtHandler::loadClass(CArtifact * art, const JsonNode & node) const
+{
+	art->aClass = stringToClass(node["class"].String());
+}
+
+void CArtHandler::loadType(CArtifact * art, const JsonNode & node) const
+{
+#define ART_BEARER(x) { #x, ArtBearer::x },
+	static const std::map<std::string, int> artifactBearerMap = { ART_BEARER_LIST };
+#undef ART_BEARER
+
+	for (const JsonNode & b : node["type"].Vector())
+	{
+		auto it = artifactBearerMap.find (b.String());
+		if (it != artifactBearerMap.end())
+		{
+			int bearerType = it->second;
+			switch (bearerType)
+			{
+				case ArtBearer::HERO://TODO: allow arts having several possible bearers
+					break;
+				case ArtBearer::COMMANDER:
+					makeItCommanderArt (art); //original artifacts should have only one bearer type
+					break;
+				case ArtBearer::CREATURE:
+					makeItCreatureArt (art);
+					break;
+			}
+		}
+		else
+			logMod->warn("Warning! Artifact type %s not recognized!", b.String());
+	}
+}
+
+void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node)
+{
+	if(!node["components"].isNull())
+	{
+		for(const auto & component : node["components"].Vector())
+		{
+			LIBRARY->identifiers()->requestIdentifier("artifact", component, [this, art](int32_t id)
+			{
+				// when this code is called both combinational art as well as component are loaded
+				// so it is safe to access any of them
+				art->constituents.push_back(ArtifactID(id).toArtifact());
+				objects[id]->partOf.insert(art);
+			});
+		}
+	}
+	if(!node["fusedComponents"].isNull())
+		art->setFused(node["fusedComponents"].Bool());
+}
+
+void CArtHandler::makeItCreatureArt(CArtifact * a, bool onlyCreature)
+{
+	if (onlyCreature)
+	{
+		a->possibleSlots[ArtBearer::HERO].clear();
+		a->possibleSlots[ArtBearer::COMMANDER].clear();
+	}
+	a->possibleSlots[ArtBearer::CREATURE].push_back(ArtifactPosition::CREATURE_SLOT);
+}
+
+void CArtHandler::makeItCommanderArt(CArtifact * a, bool onlyCommander)
+{
+	if (onlyCommander)
+	{
+		a->possibleSlots[ArtBearer::HERO].clear();
+		a->possibleSlots[ArtBearer::CREATURE].clear();
+	}
+	for(const auto & slot : ArtifactUtils::commanderSlots())
+		a->possibleSlots[ArtBearer::COMMANDER].push_back(ArtifactPosition(slot));
+}
+
+bool CArtHandler::legalArtifact(const ArtifactID & id) const
+{
+	auto art = id.toArtifact();
+	//assert ( (!art->constituents) || art->constituents->size() ); //artifacts is not combined or has some components
+
+	if(art->isCombined())
+		return false; //no combo artifacts spawning
+
+	if(art->aClass < EArtifactClass::ART_TREASURE || art->aClass > EArtifactClass::ART_RELIC)
+		return false; // invalid class
+
+	if(art->possibleSlots.count(ArtBearer::HERO) && !art->possibleSlots.at(ArtBearer::HERO).empty())
+		return true;
+
+	if(art->possibleSlots.count(ArtBearer::CREATURE) && !art->possibleSlots.at(ArtBearer::CREATURE).empty() && LIBRARY->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_ARTIFACT))
+		return true;
+
+	if(art->possibleSlots.count(ArtBearer::COMMANDER) && !art->possibleSlots.at(ArtBearer::COMMANDER).empty() && LIBRARY->engineSettings()->getBoolean(EGameSettings::MODULE_COMMANDERS))
+		return true;
+
+	return false;
+}
+
+std::set<ArtifactID> CArtHandler::getDefaultAllowed() const
+{
+	std::set<ArtifactID> allowedArtifacts;
+
+	for (const auto & artifact : objects)
+	{
+		if (!artifact->isCombined())
+			allowedArtifacts.insert(artifact->getId());
+	}
+	return allowedArtifacts;
+}
+
+void CArtHandler::afterLoadFinalization()
+{
+	//All artifacts have their id, so we can properly update their bonuses' source ids.
+	for(auto &art : objects)
+	{
+		for(auto &bonus : art->getExportedBonusList())
+		{
+			assert(bonus->source == BonusSource::ARTIFACT);
+			bonus->sid = BonusSourceID(art->id);
+		}
+		art->nodeHasChanged();
+	}
+}
+
+
+VCMI_LIB_NAMESPACE_END

+ 54 - 0
lib/entities/artifact/CArtHandler.h

@@ -0,0 +1,54 @@
+/*
+ * CArtHandler.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "CArtifact.h"
+#include "EArtifactClass.h"
+#include "IHandlerBase.h"
+
+#include <vcmi/Artifact.h>
+#include <vcmi/ArtifactService.h>
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class DLL_LINKAGE CArtHandler : public CHandlerBase<ArtifactID, Artifact, CArtifact, ArtifactService>
+{
+public:
+	void addBonuses(CArtifact * art, const JsonNode & bonusList);
+
+	static EArtifactClass::Type stringToClass(const std::string & className); //TODO: rework EartClass to make this a constructor
+
+	bool legalArtifact(const ArtifactID & id) const;
+	static void makeItCreatureArt(CArtifact * a, bool onlyCreature = true);
+	static void makeItCommanderArt(CArtifact * a, bool onlyCommander = true);
+
+	~CArtHandler();
+
+	std::vector<JsonNode> loadLegacyData() override;
+
+	void loadObject(std::string scope, std::string name, const JsonNode & data) override;
+	void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
+	void afterLoadFinalization() override;
+
+	std::set<ArtifactID> getDefaultAllowed() const;
+
+protected:
+	const std::vector<std::string> & getTypeNames() const override;
+	std::shared_ptr<CArtifact> loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index) override;
+
+private:
+	void addSlot(CArtifact * art, const std::string & slotID) const;
+	void loadSlots(CArtifact * art, const JsonNode & node) const;
+	void loadClass(CArtifact * art, const JsonNode & node) const;
+	void loadType(CArtifact * art, const JsonNode & node) const;
+	void loadComponents(CArtifact * art, const JsonNode & node);
+};
+
+VCMI_LIB_NAMESPACE_END

+ 314 - 0
lib/entities/artifact/CArtifact.cpp

@@ -0,0 +1,314 @@
+/*
+ * CArtifact.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#include "StdInc.h"
+#include "CArtifact.h"
+
+#include "ArtifactUtils.h"
+#include "CArtifactFittingSet.h"
+
+#include "../../texts/CGeneralTextHandler.h"
+#include "../../GameLibrary.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+bool CCombinedArtifact::isCombined() const
+{
+	return !(constituents.empty());
+}
+
+const std::vector<const CArtifact*> & CCombinedArtifact::getConstituents() const
+{
+	return constituents;
+}
+
+const std::set<const CArtifact*> & CCombinedArtifact::getPartOf() const
+{
+	return partOf;
+}
+
+void CCombinedArtifact::setFused(bool isFused)
+{
+	fused = isFused;
+}
+
+bool CCombinedArtifact::isFused() const
+{
+	return fused;
+}
+
+bool CCombinedArtifact::hasParts() const
+{
+	return isCombined() && !isFused();
+}
+
+bool CScrollArtifact::isScroll() const
+{
+	return static_cast<const CArtifact*>(this)->getId() == ArtifactID::SPELL_SCROLL;
+}
+
+bool CGrowingArtifact::isGrowing() const
+{
+	return !bonusesPerLevel.empty() || !thresholdBonuses.empty();
+}
+
+std::vector <std::pair<ui16, Bonus>> & CGrowingArtifact::getBonusesPerLevel()
+{
+	return bonusesPerLevel;
+}
+
+const std::vector <std::pair<ui16, Bonus>> & CGrowingArtifact::getBonusesPerLevel() const
+{
+	return bonusesPerLevel;
+}
+
+std::vector <std::pair<ui16, Bonus>> & CGrowingArtifact::getThresholdBonuses()
+{
+	return thresholdBonuses;
+}
+
+const std::vector <std::pair<ui16, Bonus>> & CGrowingArtifact::getThresholdBonuses() const
+{
+	return thresholdBonuses;
+}
+
+int32_t CArtifact::getIndex() const
+{
+	return id.toEnum();
+}
+
+int32_t CArtifact::getIconIndex() const
+{
+	return iconIndex;
+}
+
+std::string CArtifact::getJsonKey() const
+{
+	return modScope + ':' + identifier;
+}
+
+std::string CArtifact::getModScope() const
+{
+	return modScope;
+}
+
+void CArtifact::registerIcons(const IconRegistar & cb) const
+{
+	cb(getIconIndex(), 0, "ARTIFACT", image);
+	cb(getIconIndex(), 0, "ARTIFACTLARGE", large);
+}
+
+ArtifactID CArtifact::getId() const
+{
+	return id;
+}
+
+const IBonusBearer * CArtifact::getBonusBearer() const
+{
+	return this;
+}
+
+std::string CArtifact::getDescriptionTranslated() const
+{
+	return LIBRARY->generaltexth->translate(getDescriptionTextID());
+}
+
+std::string CArtifact::getEventTranslated() const
+{
+	return LIBRARY->generaltexth->translate(getEventTextID());
+}
+
+std::string CArtifact::getNameTranslated() const
+{
+	return LIBRARY->generaltexth->translate(getNameTextID());
+}
+
+std::string CArtifact::getDescriptionTextID() const
+{
+	return TextIdentifier("artifact", modScope, identifier, "description").get();
+}
+
+std::string CArtifact::getEventTextID() const
+{
+	return TextIdentifier("artifact", modScope, identifier, "event").get();
+}
+
+std::string CArtifact::getNameTextID() const
+{
+	return TextIdentifier("artifact", modScope, identifier, "name").get();
+}
+
+uint32_t CArtifact::getPrice() const
+{
+	return price;
+}
+
+CreatureID CArtifact::getWarMachine() const
+{
+	return warMachine;
+}
+
+bool CArtifact::isBig() const
+{
+	return warMachine != CreatureID::NONE;
+}
+
+bool CArtifact::isTradable() const
+{
+	switch(id.toEnum())
+	{
+		case ArtifactID::SPELLBOOK:
+			return false;
+		default:
+			return !isBig();
+	}
+}
+
+bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) const
+{
+	auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool
+	{
+		if(artSet->bearerType() == ArtBearer::HERO && ArtifactUtils::isSlotBackpack(slot))
+		{
+			if(isBig() || (!assumeDestRemoved && !ArtifactUtils::isBackpackFreeSlots(artSet)))
+				return false;
+			return true;
+		}
+
+		if(!vstd::contains(possibleSlots.at(artSet->bearerType()), slot))
+			return false;
+
+		return artSet->isPositionFree(slot, assumeDestRemoved);
+	};
+
+	auto artCanBePutAt = [this, simpleArtCanBePutAt](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool
+	{
+		if(hasParts())
+		{
+			if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved))
+				return false;
+			if(ArtifactUtils::isSlotBackpack(slot))
+				return true;
+
+			CArtifactFittingSet fittingSet(artSet->getCallback(), artSet->bearerType());
+			fittingSet.artifactsWorn = artSet->artifactsWorn;
+			if(assumeDestRemoved)
+				fittingSet.removeArtifact(slot);
+
+			for(const auto art : constituents)
+			{
+				auto possibleSlot = ArtifactUtils::getArtAnyPosition(&fittingSet, art->getId());
+				if(ArtifactUtils::isSlotEquipment(possibleSlot))
+				{
+					fittingSet.lockSlot(possibleSlot);
+				}
+				else
+				{
+					return false;
+				}
+			}
+			return true;
+		}
+		else
+		{
+			return simpleArtCanBePutAt(artSet, slot, assumeDestRemoved);
+		}
+	};
+
+	if(slot == ArtifactPosition::TRANSITION_POS)
+		return true;
+
+	if(slot == ArtifactPosition::FIRST_AVAILABLE)
+	{
+		for(const auto & slot : possibleSlots.at(artSet->bearerType()))
+		{
+			if(artCanBePutAt(artSet, slot, assumeDestRemoved))
+				return true;
+		}
+		return artCanBePutAt(artSet, ArtifactPosition::BACKPACK_START, assumeDestRemoved);
+	}
+	else if(ArtifactUtils::isSlotBackpack(slot))
+	{
+		return artCanBePutAt(artSet, ArtifactPosition::BACKPACK_START, assumeDestRemoved);
+	}
+	else
+	{
+		return artCanBePutAt(artSet, slot, assumeDestRemoved);
+	}
+}
+
+CArtifact::CArtifact()
+	: iconIndex(ArtifactID::NONE),
+	price(0)
+{
+	setNodeType(ARTIFACT);
+	possibleSlots[ArtBearer::HERO]; //we want to generate map entry even if it will be empty
+	possibleSlots[ArtBearer::CREATURE]; //we want to generate map entry even if it will be empty
+	possibleSlots[ArtBearer::COMMANDER];
+	possibleSlots[ArtBearer::ALTAR];
+}
+
+//This destructor should be placed here to avoid side effects
+CArtifact::~CArtifact() = default;
+
+int CArtifact::getArtClassSerial() const
+{
+	if(id == ArtifactID::SPELL_SCROLL)
+		return 4;
+	switch(aClass)
+	{
+		case EArtifactClass::ART_TREASURE:
+			return 0;
+		case EArtifactClass::ART_MINOR:
+			return 1;
+		case EArtifactClass::ART_MAJOR:
+			return 2;
+		case EArtifactClass::ART_RELIC:
+			return 3;
+		case EArtifactClass::ART_SPECIAL:
+			return 5;
+	}
+
+	return -1;
+}
+
+std::string CArtifact::nodeName() const
+{
+	return "Artifact: " + getNameTranslated();
+}
+
+void CArtifact::addNewBonus(const std::shared_ptr<Bonus>& b)
+{
+	b->source = BonusSource::ARTIFACT;
+	b->duration = BonusDuration::PERMANENT;
+	b->description.appendTextID(getNameTextID());
+	b->description.appendRawString(" %+d");
+	CBonusSystemNode::addNewBonus(b);
+}
+
+const std::map<ArtBearer::ArtBearer, std::vector<ArtifactPosition>> & CArtifact::getPossibleSlots() const
+{
+	return possibleSlots;
+}
+
+void CArtifact::updateFrom(const JsonNode& data)
+{
+	//TODO:CArtifact::updateFrom
+}
+
+void CArtifact::setImage(int32_t iconIndex, std::string image, std::string large)
+{
+	this->iconIndex = iconIndex;
+	this->image = image;
+	this->large = large;
+}
+
+
+VCMI_LIB_NAMESPACE_END

+ 123 - 0
lib/entities/artifact/CArtifact.h

@@ -0,0 +1,123 @@
+/*
+ * CArtifact.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "ArtBearer.h"
+#include "EArtifactClass.h"
+
+#include "../../bonuses/CBonusSystemNode.h"
+
+#include <vcmi/Artifact.h>
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class CArtifactSet;
+
+class DLL_LINKAGE CCombinedArtifact
+{
+protected:
+	CCombinedArtifact()
+		: fused(false){};
+
+	std::vector<const CArtifact *> constituents; // Artifacts IDs a combined artifact consists of, or nullptr.
+	std::set<const CArtifact *> partOf; // Reverse map of constituents - combined arts that include this art
+	bool fused;
+
+public:
+	bool isCombined() const;
+	const std::vector<const CArtifact *> & getConstituents() const;
+	const std::set<const CArtifact *> & getPartOf() const;
+	void setFused(bool isFused);
+	bool isFused() const;
+	bool hasParts() const;
+};
+
+class DLL_LINKAGE CScrollArtifact
+{
+protected:
+	CScrollArtifact() = default;
+
+public:
+	bool isScroll() const;
+};
+
+class DLL_LINKAGE CGrowingArtifact
+{
+protected:
+	CGrowingArtifact() = default;
+
+	std::vector<std::pair<ui16, Bonus>> bonusesPerLevel; // Bonus given each n levels
+	std::vector<std::pair<ui16, Bonus>> thresholdBonuses; // After certain level they will be added once
+public:
+	bool isGrowing() const;
+
+	std::vector<std::pair<ui16, Bonus>> & getBonusesPerLevel();
+	const std::vector<std::pair<ui16, Bonus>> & getBonusesPerLevel() const;
+	std::vector<std::pair<ui16, Bonus>> & getThresholdBonuses();
+	const std::vector<std::pair<ui16, Bonus>> & getThresholdBonuses() const;
+};
+
+// Container for artifacts. Not for instances.
+class DLL_LINKAGE CArtifact final : public Artifact, public CBonusSystemNode, public CCombinedArtifact, public CScrollArtifact, public CGrowingArtifact
+{
+	ArtifactID id;
+	std::string image;
+	std::string large; // big image for custom artifacts, used in drag & drop
+	std::string advMapDef; // used for adventure map object
+	std::string modScope;
+	std::string identifier;
+	int32_t iconIndex;
+	uint32_t price;
+	CreatureID warMachine;
+	// Bearer Type => ids of slots where artifact can be placed
+	std::map<ArtBearer::ArtBearer, std::vector<ArtifactPosition>> possibleSlots;
+
+public:
+	EArtifactClass::Type aClass = EArtifactClass::ART_SPECIAL;
+	bool onlyOnWaterMap;
+
+	int32_t getIndex() const override;
+	int32_t getIconIndex() const override;
+	std::string getJsonKey() const override;
+	std::string getModScope() const override;
+	void registerIcons(const IconRegistar & cb) const override;
+	ArtifactID getId() const override;
+	const IBonusBearer * getBonusBearer() const override;
+
+	std::string getDescriptionTranslated() const override;
+	std::string getEventTranslated() const override;
+	std::string getNameTranslated() const override;
+
+	std::string getDescriptionTextID() const override;
+	std::string getEventTextID() const override;
+	std::string getNameTextID() const override;
+
+	uint32_t getPrice() const override;
+	CreatureID getWarMachine() const override;
+	bool isBig() const override;
+	bool isTradable() const override;
+
+	int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
+	std::string nodeName() const override;
+	void addNewBonus(const std::shared_ptr<Bonus> & b) override;
+	const std::map<ArtBearer::ArtBearer, std::vector<ArtifactPosition>> & getPossibleSlots() const;
+
+	virtual bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE, bool assumeDestRemoved = false) const;
+	void updateFrom(const JsonNode & data);
+	// Is used for testing purposes only
+	void setImage(int32_t iconIndex, std::string image, std::string large);
+
+	CArtifact();
+	~CArtifact();
+
+	friend class CArtHandler;
+};
+
+VCMI_LIB_NAMESPACE_END

+ 36 - 0
lib/entities/artifact/CArtifactFittingSet.cpp

@@ -0,0 +1,36 @@
+/*
+ * CArtifactFittingSet.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#include "StdInc.h"
+#include "CArtifactFittingSet.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+CArtifactFittingSet::CArtifactFittingSet(IGameCallback *cb, ArtBearer::ArtBearer bearer)
+	: CArtifactSet(cb)
+	, GameCallbackHolder(cb)
+	, bearer(bearer)
+{
+}
+
+CArtifactFittingSet::CArtifactFittingSet(const CArtifactSet & artSet)
+	: CArtifactFittingSet(artSet.getCallback(), artSet.bearerType())
+{
+	artifactsWorn = artSet.artifactsWorn;
+	artifactsInBackpack = artSet.artifactsInBackpack;
+	artifactsTransitionPos = artSet.artifactsTransitionPos;
+}
+
+ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const
+{
+	return this->bearer;
+}
+
+VCMI_LIB_NAMESPACE_END

+ 35 - 0
lib/entities/artifact/CArtifactFittingSet.h

@@ -0,0 +1,35 @@
+/*
+ * CArtifactFittingSet.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "CArtifactSet.h"
+
+#include "../../GameCallbackHolder.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+// Used to try on artifacts before the claimed changes have been applied
+class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet, public GameCallbackHolder
+{
+	IGameCallback * getCallback() const final
+	{
+		return cb;
+	}
+
+public:
+	CArtifactFittingSet(IGameCallback * cb, ArtBearer::ArtBearer Bearer);
+	explicit CArtifactFittingSet(const CArtifactSet & artSet);
+	ArtBearer::ArtBearer bearerType() const override;
+
+protected:
+	ArtBearer::ArtBearer bearer;
+};
+
+VCMI_LIB_NAMESPACE_END

+ 4 - 5
lib/CArtifactInstance.cpp → lib/entities/artifact/CArtifactInstance.cpp

@@ -11,12 +11,11 @@
 #include "StdInc.h"
 #include "CArtifactInstance.h"
 
+#include "CArtifact.h"
 #include "CArtifactSet.h"
-#include "ArtifactUtils.h"
-#include "CArtHandler.h"
-#include "IGameCallback.h"
-#include "gameState/CGameState.h"
-#include "networkPacks/ArtifactLocation.h"
+
+#include "../../IGameCallback.h"
+#include "../../gameState/CGameState.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 0 - 0
lib/CArtifactInstance.h → lib/entities/artifact/CArtifactInstance.h


+ 377 - 0
lib/entities/artifact/CArtifactSet.cpp

@@ -0,0 +1,377 @@
+/*
+ * CArtifactSet.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#include "StdInc.h"
+#include "CArtifactSet.h"
+
+#include "CArtifact.h"
+#include "ArtifactUtils.h"
+
+#include "../../constants/StringConstants.h"
+#include "../../gameState/CGameState.h"
+#include "../../mapping/CMap.h"
+#include "../../serializer/JsonSerializeFormat.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+	const CArtifactInstance * CArtifactSet::getArt(const ArtifactPosition & pos, bool excludeLocked) const
+{
+	if(const ArtSlotInfo * si = getSlot(pos))
+	{
+		if(si->getArt() && (!excludeLocked || !si->locked))
+			return si->getArt();
+	}
+	return nullptr;
+}
+
+ArtifactInstanceID CArtifactSet::getArtID(const ArtifactPosition & pos, bool excludeLocked) const
+{
+	if(const ArtSlotInfo * si = getSlot(pos))
+	{
+		if(si->getArt() && (!excludeLocked || !si->locked))
+			return si->getArt()->getId();
+	}
+	return {};
+}
+
+ArtifactPosition CArtifactSet::getArtPos(const ArtifactID & aid, bool onlyWorn, bool allowLocked) const
+{
+	for(const auto & [slot, slotInfo] : artifactsWorn)
+	{
+		if(slotInfo.getArt()->getTypeId() == aid && (allowLocked || !slotInfo.locked))
+			return slot;
+	}
+	if(!onlyWorn)
+	{
+		size_t backpackPositionIdx = ArtifactPosition::BACKPACK_START;
+		for(const auto & artInfo : artifactsInBackpack)
+		{
+			const auto art = artInfo.getArt();
+			if(art && art->getType()->getId() == aid)
+				return ArtifactPosition(backpackPositionIdx);
+			backpackPositionIdx++;
+		}
+	}
+	return ArtifactPosition::PRE_FIRST;
+}
+
+const CArtifactInstance * CArtifactSet::getArtByInstanceId(const ArtifactInstanceID & artInstId) const
+{
+	for(const auto & i : artifactsWorn)
+		if(i.second.getArt()->getId() == artInstId)
+			return i.second.getArt();
+
+	for(const auto & i : artifactsInBackpack)
+		if(i.getArt()->getId() == artInstId)
+			return i.getArt();
+
+	return nullptr;
+}
+
+ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance * artInst) const
+{
+	if(artInst)
+	{
+		for(const auto & slot : artInst->getType()->getPossibleSlots().at(bearerType()))
+			if(getArt(slot) == artInst)
+				return slot;
+
+		ArtifactPosition backpackSlot = ArtifactPosition::BACKPACK_START;
+		for(auto & slotInfo : artifactsInBackpack)
+		{
+			if(slotInfo.getArt() == artInst)
+				return backpackSlot;
+			backpackSlot = ArtifactPosition(backpackSlot + 1);
+		}
+	}
+	return ArtifactPosition::PRE_FIRST;
+}
+
+bool CArtifactSet::hasArt(const ArtifactID & aid, bool onlyWorn, bool searchCombinedParts) const
+{
+	if(searchCombinedParts && getCombinedArtWithPart(aid))
+		return true;
+	if(getArtPos(aid, onlyWorn, searchCombinedParts) != ArtifactPosition::PRE_FIRST)
+		return true;
+	return false;
+}
+
+CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(const ArtifactPosition & slot, const CArtifactInstance * art)
+{
+	ArtPlacementMap resArtPlacement;
+	const auto putToSlot = [this](const ArtifactPosition & targetSlot, const CArtifactInstance * targetArt, bool locked)
+	{
+		ArtSlotInfo newSlot(targetArt, locked);
+
+		if(targetSlot == ArtifactPosition::TRANSITION_POS)
+		{
+			artifactsTransitionPos = newSlot;
+		}
+		else if(ArtifactUtils::isSlotEquipment(targetSlot))
+		{
+			artifactsWorn.insert_or_assign(targetSlot, newSlot);
+		}
+		else
+		{
+			auto position = artifactsInBackpack.begin() + targetSlot - ArtifactPosition::BACKPACK_START;
+			artifactsInBackpack.insert(position, newSlot);
+		}
+	};
+
+	putToSlot(slot, art, false);
+	if(art->getType()->isCombined() && ArtifactUtils::isSlotEquipment(slot))
+	{
+		const CArtifactInstance * mainPart = nullptr;
+		for(const auto & part : art->getPartsInfo())
+			if(vstd::contains(part.getArtifact()->getType()->getPossibleSlots().at(bearerType()), slot)
+			   && (part.slot == ArtifactPosition::PRE_FIRST))
+			{
+				mainPart = part.getArtifact();
+				break;
+			}
+
+		for(const auto & part : art->getPartsInfo())
+		{
+			if(part.getArtifact() != mainPart)
+			{
+				auto partSlot = part.slot;
+				if(!part.getArtifact()->getType()->canBePutAt(this, partSlot))
+					partSlot = ArtifactUtils::getArtAnyPosition(this, part.getArtifact()->getTypeId());
+
+				assert(ArtifactUtils::isSlotEquipment(partSlot));
+				putToSlot(partSlot, part.getArtifact(), true);
+				resArtPlacement.emplace(part.getArtifact(), partSlot);
+			}
+			else
+			{
+				resArtPlacement.emplace(part.getArtifact(), part.slot);
+			}
+		}
+	}
+	return resArtPlacement;
+}
+
+CArtifactSet::CArtifactSet(IGameCallback * cb)
+	:artifactsTransitionPos(cb)
+{}
+
+void CArtifactSet::removeArtifact(const ArtifactPosition & slot)
+{
+	const auto eraseArtSlot = [this](const ArtifactPosition & slotForErase)
+	{
+		if(slotForErase == ArtifactPosition::TRANSITION_POS)
+		{
+			artifactsTransitionPos.artifactID = {};
+		}
+		else if(ArtifactUtils::isSlotBackpack(slotForErase))
+		{
+			auto backpackSlot = ArtifactPosition(slotForErase - ArtifactPosition::BACKPACK_START);
+
+			assert(artifactsInBackpack.begin() + backpackSlot < artifactsInBackpack.end());
+			artifactsInBackpack.erase(artifactsInBackpack.begin() + backpackSlot);
+		}
+		else
+		{
+			artifactsWorn.erase(slotForErase);
+		}
+	};
+
+	if(const auto art = getArt(slot, false))
+	{
+		if(art->isCombined())
+		{
+			for(const auto & part : art->getPartsInfo())
+			{
+				if(part.slot != ArtifactPosition::PRE_FIRST)
+				{
+					assert(getArt(part.slot, false));
+					assert(getArt(part.slot, false) == part.getArtifact());
+				}
+				eraseArtSlot(part.slot);
+			}
+		}
+		eraseArtSlot(slot);
+	}
+}
+
+const CArtifactInstance * CArtifactSet::getCombinedArtWithPart(const ArtifactID & partId) const
+{
+	for(const auto & slot : artifactsInBackpack)
+	{
+		auto art = slot.getArt();
+		if(art->isCombined())
+		{
+			for(auto & ci : art->getPartsInfo())
+			{
+				if(ci.getArtifact()->getTypeId() == partId)
+					return art;
+			}
+		}
+	}
+	return nullptr;
+}
+
+const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const
+{
+	if(pos == ArtifactPosition::TRANSITION_POS)
+		return &artifactsTransitionPos;
+	if(vstd::contains(artifactsWorn, pos))
+		return &artifactsWorn.at(pos);
+	if(ArtifactUtils::isSlotBackpack(pos))
+	{
+		auto backpackPos = pos - ArtifactPosition::BACKPACK_START;
+		if(backpackPos < 0 || backpackPos >= artifactsInBackpack.size())
+			return nullptr;
+		else
+			return &artifactsInBackpack[backpackPos];
+	}
+
+	return nullptr;
+}
+
+void CArtifactSet::lockSlot(const ArtifactPosition & pos)
+{
+	if(pos == ArtifactPosition::TRANSITION_POS)
+		artifactsTransitionPos.locked = true;
+	else if(ArtifactUtils::isSlotEquipment(pos))
+		artifactsWorn.at(pos).locked = true;
+	else
+	{
+		assert(artifactsInBackpack.size() > pos - ArtifactPosition::BACKPACK_START);
+		(artifactsInBackpack.begin() + pos - ArtifactPosition::BACKPACK_START)->locked = true;
+	}
+}
+
+bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck) const
+{
+	if(bearerType() == ArtBearer::ALTAR)
+		return artifactsInBackpack.size() < GameConstants::ALTAR_ARTIFACTS_SLOTS;
+
+	if(const ArtSlotInfo *s = getSlot(pos))
+		return (onlyLockCheck || !s->getArt()) && !s->locked;
+
+	return true; //no slot means not used
+}
+
+void CArtifactSet::artDeserializationFix(CGameState & gs, CBonusSystemNode *node)
+{
+	for(auto & elem : artifactsWorn)
+		if(elem.second.artifactID.hasValue() && !elem.second.locked)
+			node->attachToSource(*gs.getArtInstance(elem.second.artifactID));
+}
+
+void CArtifactSet::serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map)
+{
+	//todo: creature and commander artifacts
+	if(handler.saving && artifactsInBackpack.empty() && artifactsWorn.empty())
+		return;
+
+	if(!handler.saving)
+	{
+		artifactsInBackpack.clear();
+		artifactsWorn.clear();
+	}
+
+	auto s = handler.enterStruct(fieldName);
+
+	switch(bearerType())
+	{
+		case ArtBearer::HERO:
+			serializeJsonHero(handler, map);
+			break;
+		case ArtBearer::CREATURE:
+			serializeJsonCreature(handler);
+			break;
+		case ArtBearer::COMMANDER:
+			serializeJsonCommander(handler);
+			break;
+		default:
+			assert(false);
+			break;
+	}
+}
+
+void CArtifactSet::serializeJsonHero(JsonSerializeFormat & handler, CMap * map)
+{
+	for(const auto & slot : ArtifactUtils::allWornSlots())
+	{
+		serializeJsonSlot(handler, slot, map);
+	}
+
+	std::vector<ArtifactID> backpackTemp;
+
+	if(handler.saving)
+	{
+		backpackTemp.reserve(artifactsInBackpack.size());
+		for(const ArtSlotInfo & info : artifactsInBackpack)
+			backpackTemp.push_back(info.getArt()->getTypeId());
+	}
+	handler.serializeIdArray(NArtifactPosition::backpack, backpackTemp);
+	if(!handler.saving)
+	{
+		for(const ArtifactID & artifactID : backpackTemp)
+		{
+			auto * artifact = map->createArtifact(artifactID);
+			auto slot = ArtifactPosition::BACKPACK_START + artifactsInBackpack.size();
+			if(artifact->getType()->canBePutAt(this, slot))
+			{
+				auto artsMap = putArtifact(slot, artifact);
+				artifact->addPlacementMap(artsMap);
+			}
+		}
+	}
+}
+
+void CArtifactSet::serializeJsonCreature(JsonSerializeFormat & handler)
+{
+	logGlobal->error("CArtifactSet::serializeJsonCreature not implemented");
+}
+
+void CArtifactSet::serializeJsonCommander(JsonSerializeFormat & handler)
+{
+	logGlobal->error("CArtifactSet::serializeJsonCommander not implemented");
+}
+
+void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const ArtifactPosition & slot, CMap * map)
+{
+	ArtifactID artifactID;
+
+	if(handler.saving)
+	{
+		const ArtSlotInfo * info = getSlot(slot);
+
+		if(info != nullptr && !info->locked)
+		{
+			artifactID = info->getArt()->getTypeId();
+			handler.serializeId(NArtifactPosition::namesHero[slot.num], artifactID, ArtifactID::NONE);
+		}
+	}
+	else
+	{
+		handler.serializeId(NArtifactPosition::namesHero[slot.num], artifactID, ArtifactID::NONE);
+
+		if(artifactID != ArtifactID::NONE)
+		{
+			auto * artifact = map->createArtifact(artifactID.toEnum());
+
+			if(artifact->getType()->canBePutAt(this, slot))
+			{
+				auto artsMap = putArtifact(slot, artifact);
+				artifact->addPlacementMap(artsMap);
+			}
+			else
+			{
+				logGlobal->debug("Artifact can't be put at the specified location."); //TODO add more debugging information
+			}
+		}
+	}
+}
+
+VCMI_LIB_NAMESPACE_END

+ 6 - 48
lib/CArtifactSet.h → lib/entities/artifact/CArtifactSet.h

@@ -1,5 +1,5 @@
 /*
- * CArtHandler.h, part of VCMI engine
+ * CArtifactSet.h, part of VCMI engine
  *
  * Authors: listed in file AUTHORS in main folder
  *
@@ -9,46 +9,17 @@
  */
 #pragma once
 
-#include "CArtHandler.h"
-#include "GameCallbackHolder.h"
-#include "constants/EntityIdentifiers.h"
-
-#include "CArtifactInstance.h"
+#include "ArtBearer.h"
+#include "ArtSlotInfo.h"
+#include "../../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-struct DLL_LINKAGE ArtSlotInfo : public GameCallbackHolder
-{
-	ArtifactInstanceID artifactID;
-	bool locked = false; //if locked, then artifact points to the combined artifact
-
-	explicit ArtSlotInfo(IGameCallback * cb);
-	ArtSlotInfo(const CArtifactInstance * artifact, bool locked);
-
-	const CArtifactInstance * getArt() const;
-	ArtifactInstanceID getID() const;
-
-	template <typename Handler> void serialize(Handler & h)
-	{
-		if (h.saving || h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
-		{
-			h & artifactID;
-		}
-		else
-		{
-			std::shared_ptr<CArtifactInstance> pointer;
-			h & pointer;
-			if (pointer->getId() == ArtifactInstanceID())
-				CArtifactInstance::saveCompatibilityFixArtifactID(pointer);
-			artifactID = pointer->getId();
-		}
-		h & locked;
-	}
-};
+class CArtifactInstance;
+class CMap;
 
 class DLL_LINKAGE CArtifactSet : public virtual Serializeable
 {
-
 public:
 	using ArtPlacementMap = std::map<const CArtifactInstance*, ArtifactPosition>;
 
@@ -93,17 +64,4 @@ private:
 	void serializeJsonSlot(JsonSerializeFormat & handler, const ArtifactPosition & slot, CMap * map);//normal slots
 };
 
-// Used to try on artifacts before the claimed changes have been applied
-class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet, public GameCallbackHolder
-{
-	IGameCallback * getCallback() const final { return cb; }
-public:
-	CArtifactFittingSet(IGameCallback *cb, ArtBearer::ArtBearer Bearer);
-	explicit CArtifactFittingSet(const CArtifactSet & artSet);
-	ArtBearer::ArtBearer bearerType() const override;
-
-protected:
-	ArtBearer::ArtBearer bearer;
-};
-
 VCMI_LIB_NAMESPACE_END

+ 26 - 0
lib/entities/artifact/EArtifactClass.h

@@ -0,0 +1,26 @@
+/*
+ * EArtifactClass.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+namespace EArtifactClass
+{
+	enum Type
+	{
+		ART_SPECIAL = 1,
+		ART_TREASURE = 2,
+		ART_MINOR = 4,
+		ART_MAJOR = 8,
+		ART_RELIC = 16
+	};
+}
+
+VCMI_LIB_NAMESPACE_END

+ 8 - 7
lib/gameState/CGameState.cpp

@@ -17,7 +17,6 @@
 #include "SThievesGuildInfo.h"
 #include "QuestInfo.h"
 
-#include "../ArtifactUtils.h"
 #include "../GameSettings.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../CPlayerState.h"
@@ -33,6 +32,8 @@
 #include "../battle/BattleInfo.h"
 #include "../campaign/CampaignState.h"
 #include "../constants/StringConstants.h"
+#include "../entities/artifact/ArtifactUtils.h"
+#include "../entities/artifact/CArtHandler.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../entities/hero/CHero.h"
 #include "../entities/hero/CHeroClass.h"
@@ -722,7 +723,7 @@ void CGameState::initStartingBonus()
 					logGlobal->error("Cannot give starting artifact - no heroes!");
 					break;
 				}
-				const Artifact * toGive = pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE).toEntity(LIBRARY);
+				const Artifact * toGive = pickRandomArtifact(getRandomGenerator(), EArtifactClass::ART_TREASURE).toEntity(LIBRARY);
 
 				CGHeroInstance *hero = elem.second.getHeroes()[0];
 				if(!giveHeroArtifact(hero, toGive->getId()))
@@ -1678,18 +1679,18 @@ ArtifactID CGameState::pickRandomArtifact(vstd::RNG & rand, int flags, std::func
 
 		auto const * artifact = artifactID.toArtifact();
 
-		assert(artifact->aClass != CArtifact::ART_SPECIAL); // should be filtered out when allowedArtifacts is initialized
+		assert(artifact->aClass != EArtifactClass::ART_SPECIAL); // should be filtered out when allowedArtifacts is initialized
 
-		if ((flags & CArtifact::ART_TREASURE) == 0 && artifact->aClass == CArtifact::ART_TREASURE)
+		if ((flags & EArtifactClass::ART_TREASURE) == 0 && artifact->aClass == EArtifactClass::ART_TREASURE)
 			continue;
 
-		if ((flags & CArtifact::ART_MINOR) == 0 && artifact->aClass == CArtifact::ART_MINOR)
+		if ((flags & EArtifactClass::ART_MINOR) == 0 && artifact->aClass == EArtifactClass::ART_MINOR)
 			continue;
 
-		if ((flags & CArtifact::ART_MAJOR) == 0 && artifact->aClass == CArtifact::ART_MAJOR)
+		if ((flags & EArtifactClass::ART_MAJOR) == 0 && artifact->aClass == EArtifactClass::ART_MAJOR)
 			continue;
 
-		if ((flags & CArtifact::ART_RELIC) == 0 && artifact->aClass == CArtifact::ART_RELIC)
+		if ((flags & EArtifactClass::ART_RELIC) == 0 && artifact->aClass == EArtifactClass::ART_RELIC)
 			continue;
 
 		if (!accepts(artifact->getId()))

+ 2 - 1
lib/gameState/CGameStateCampaign.cpp

@@ -14,6 +14,8 @@
 #include "QuestInfo.h"
 
 #include "../campaign/CampaignState.h"
+#include "../entities/artifact/ArtifactUtils.h"
+#include "../entities/artifact/CArtifact.h"
 #include "../entities/building/CBuilding.h"
 #include "../entities/building/CBuildingHandler.h"
 #include "../entities/hero/CHeroClass.h"
@@ -26,7 +28,6 @@
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../StartInfo.h"
 #include "../mapping/CMap.h"
-#include "../ArtifactUtils.h"
 #include "../CPlayerState.h"
 
 #include <vstd/RNG.h>

+ 2 - 2
lib/json/JsonRandom.cpp

@@ -20,12 +20,12 @@
 
 #include "../constants/StringConstants.h"
 #include "../GameLibrary.h"
-#include "../CArtHandler.h"
 #include "../CCreatureHandler.h"
 #include "../CCreatureSet.h"
 #include "../spells/CSpellHandler.h"
 #include "../CSkillHandler.h"
 #include "../IGameCallback.h"
+#include "../entities/artifact/CArtHandler.h"
 #include "../entities/hero/CHero.h"
 #include "../entities/hero/CHeroClass.h"
 #include "../gameState/CGameState.h"
@@ -147,7 +147,7 @@ JsonRandomizationException::JsonRandomizationException(const std::string & messa
 	{
 		assert(value.isStruct());
 
-		std::set<CArtifact::EartClass> allowedClasses;
+		std::set<EArtifactClass::Type> allowedClasses;
 		std::set<ArtifactPosition> allowedPositions;
 		ui32 minValue = 0;
 		ui32 maxValue = std::numeric_limits<ui32>::max();

+ 2 - 1
lib/mapObjects/CGHeroInstance.cpp

@@ -16,7 +16,6 @@
 #include <vstd/RNG.h>
 
 #include "../texts/CGeneralTextHandler.h"
-#include "../ArtifactUtils.h"
 #include "../TerrainHandler.h"
 #include "../RoadHandler.h"
 #include "../IGameSettings.h"
@@ -30,6 +29,8 @@
 #include "../mapping/CMap.h"
 #include "../StartInfo.h"
 #include "CGTownInstance.h"
+#include "../entities/artifact/ArtifactUtils.h"
+#include "../entities/artifact/CArtifact.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../entities/hero/CHeroHandler.h"
 #include "../entities/hero/CHeroClass.h"

+ 0 - 1
lib/mapObjects/CGHeroInstance.h

@@ -16,7 +16,6 @@
 
 #include "../bonuses/BonusCache.h"
 #include "../entities/hero/EHeroGender.h"
-#include "../CArtHandler.h" // For CArtifactSet
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 0 - 1
lib/mapObjects/CGMarket.h

@@ -11,7 +11,6 @@
 
 #include "CGObjectInstance.h"
 #include "IMarket.h"
-#include "../CArtHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 1 - 1
lib/mapObjects/CQuest.cpp

@@ -13,11 +13,11 @@
 
 #include <vcmi/spells/Spell.h>
 
-#include "../ArtifactUtils.h"
 #include "../CSoundBase.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "CGCreature.h"
 #include "../IGameCallback.h"
+#include "../entities/artifact/CArtifact.h"
 #include "../entities/hero/CHeroHandler.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../serializer/JsonSerializeFormat.h"

+ 1 - 1
lib/mapObjects/IMarket.cpp

@@ -11,12 +11,12 @@
 #include "StdInc.h"
 #include "IMarket.h"
 
-#include "CArtHandler.h"
 #include "CCreatureHandler.h"
 #include "CGObjectInstance.h"
 #include "CObjectHandler.h"
 
 #include "../GameLibrary.h"
+#include "../entities/artifact/CArtHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 1 - 1
lib/mapObjects/IMarket.h

@@ -11,7 +11,7 @@
 
 #include "../networkPacks/TradeItem.h"
 #include "../constants/Enumerations.h"
-#include "../CArtifactSet.h"
+#include "../entities/artifact/CArtifactSet.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 7 - 6
lib/mapObjects/MiscObjects.cpp

@@ -11,9 +11,10 @@
 #include "StdInc.h"
 #include "MiscObjects.h"
 
-#include "../ArtifactUtils.h"
 #include "../bonuses/Propagators.h"
 #include "../constants/StringConstants.h"
+#include "../entities/artifact/ArtifactUtils.h"
+#include "../entities/artifact/CArtifact.h"
 #include "../CConfigHandler.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../CSoundBase.h"
@@ -630,19 +631,19 @@ void CGArtifact::pickRandomObject(vstd::RNG & rand)
 	switch(ID.toEnum())
 	{
 		case MapObjectID::RANDOM_ART:
-			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC);
+			subID = cb->gameState().pickRandomArtifact(rand, EArtifactClass::ART_TREASURE | EArtifactClass::ART_MINOR | EArtifactClass::ART_MAJOR | EArtifactClass::ART_RELIC);
 			break;
 		case MapObjectID::RANDOM_TREASURE_ART:
-			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_TREASURE);
+			subID = cb->gameState().pickRandomArtifact(rand, EArtifactClass::ART_TREASURE);
 			break;
 		case MapObjectID::RANDOM_MINOR_ART:
-			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_MINOR);
+			subID = cb->gameState().pickRandomArtifact(rand, EArtifactClass::ART_MINOR);
 			break;
 		case MapObjectID::RANDOM_MAJOR_ART:
-			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_MAJOR);
+			subID = cb->gameState().pickRandomArtifact(rand, EArtifactClass::ART_MAJOR);
 			break;
 		case MapObjectID::RANDOM_RELIC_ART:
-			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_RELIC);
+			subID = cb->gameState().pickRandomArtifact(rand, EArtifactClass::ART_RELIC);
 			break;
 	}
 

+ 1 - 1
lib/mapping/CMap.cpp

@@ -13,7 +13,6 @@
 #include "CMapEditManager.h"
 #include "CMapOperation.h"
 
-#include "../CArtHandler.h"
 #include "../CCreatureHandler.h"
 #include "../CSkillHandler.h"
 #include "../GameLibrary.h"
@@ -23,6 +22,7 @@
 #include "../RoadHandler.h"
 #include "../TerrainHandler.h"
 
+#include "../entities/artifact/CArtHandler.h"
 #include "../entities/hero/CHeroHandler.h"
 #include "../gameState/CGameState.h"
 #include "../mapObjects/CGHeroInstance.h"

+ 1 - 1
lib/mapping/MapFormatH3M.cpp

@@ -15,7 +15,6 @@
 #include "MapReaderH3M.h"
 #include "MapFormat.h"
 
-#include "../ArtifactUtils.h"
 #include "../CCreatureHandler.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../CSkillHandler.h"
@@ -26,6 +25,7 @@
 #include "../TerrainHandler.h"
 #include "../GameLibrary.h"
 #include "../constants/StringConstants.h"
+#include "../entities/artifact/CArtHandler.h"
 #include "../entities/hero/CHeroHandler.h"
 #include "../filesystem/CBinaryReader.h"
 #include "../filesystem/Filesystem.h"

+ 1 - 1
lib/mapping/MapFormatJson.cpp

@@ -16,11 +16,11 @@
 #include "../json/JsonWriter.h"
 #include "CMap.h"
 #include "MapFormat.h"
-#include "../ArtifactUtils.h"
 #include "../GameLibrary.h"
 #include "../RiverHandler.h"
 #include "../RoadHandler.h"
 #include "../TerrainHandler.h"
+#include "../entities/artifact/CArtHandler.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../entities/hero/CHeroHandler.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"

+ 1 - 1
lib/modding/ContentTypeHandler.cpp

@@ -16,9 +16,9 @@
 #include "ModScope.h"
 
 #include "../BattleFieldHandler.h"
-#include "../CArtHandler.h"
 #include "../CCreatureHandler.h"
 #include "../CConfigHandler.h"
+#include "../entities/artifact/CArtHandler.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../entities/hero/CHeroClassHandler.h"
 #include "../entities/hero/CHeroHandler.h"

+ 3 - 26
lib/networkPacks/NetPacksLib.cpp

@@ -8,7 +8,6 @@
  *
  */
 #include "StdInc.h"
-#include "ArtifactUtils.h"
 #include "PacksForClient.h"
 #include "PacksForClientBattle.h"
 #include "PacksForServer.h"
@@ -19,7 +18,6 @@
 #include "SetStackEffect.h"
 #include "NetPackVisitor.h"
 #include "texts/CGeneralTextHandler.h"
-#include "CArtHandler.h"
 #include "GameLibrary.h"
 #include "mapping/CMap.h"
 #include "spells/CSpellHandler.h"
@@ -32,6 +30,9 @@
 #include "StartInfo.h"
 #include "CPlayerState.h"
 #include "TerrainHandler.h"
+#include "entities/artifact/ArtifactUtils.h"
+#include "entities/artifact/CArtifact.h"
+#include "entities/artifact/CArtifactFittingSet.h"
 #include "entities/building/CBuilding.h"
 #include "entities/building/TownFortifications.h"
 #include "mapObjects/CGCreature.h"
@@ -2447,28 +2448,4 @@ void SetRewardableConfiguration::applyGs(CGameState *gs)
 	}
 }
 
-ArtSlotInfo::ArtSlotInfo(IGameCallback * cb)
-	: GameCallbackHolder(cb)
-{
-}
-
-ArtSlotInfo::ArtSlotInfo(const CArtifactInstance * artifact, bool locked)
-	: GameCallbackHolder(artifact->cb)
-	, artifactID(artifact->getId())
-	, locked(locked)
-{
-}
-
-const CArtifactInstance * ArtSlotInfo::getArt() const
-{
-	if(!artifactID.hasValue())
-		return nullptr;
-	return cb->getArtInstance(artifactID);
-}
-
-ArtifactInstanceID ArtSlotInfo::getID() const
-{
-	return artifactID;
-}
-
 VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/rewardable/Limiter.cpp

@@ -13,12 +13,12 @@
 
 #include "../IGameCallback.h"
 #include "../CPlayerState.h"
+#include "../entities/artifact/ArtifactUtils.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../networkPacks/Component.h"
 #include "../serializer/JsonSerializeFormat.h"
 #include "../constants/StringConstants.h"
 #include "../CSkillHandler.h"
-#include "../ArtifactUtils.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 2 - 2
lib/rmg/CMapGenerator.cpp

@@ -15,13 +15,13 @@
 #include "../GameLibrary.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../CRandomGenerator.h"
+#include "../entities/artifact/CArtHandler.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../entities/faction/CFaction.h"
 #include "../entities/hero/CHero.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../mapping/CMapEditManager.h"
-#include "../CArtHandler.h"
 #include "../constants/StringConstants.h"
 #include "../filesystem/Filesystem.h"
 #include "CZonePlacer.h"
@@ -110,7 +110,7 @@ void CMapGenerator::initQuestArtsRemaining()
 	{
 		auto art = artID.toArtifact();
 		//Don't use parts of combined artifacts
-		if (art->aClass == CArtifact::ART_TREASURE && LIBRARY->arth->legalArtifact(art->getId()) && art->getPartOf().empty())
+		if (art->aClass == EArtifactClass::ART_TREASURE && LIBRARY->arth->legalArtifact(art->getId()) && art->getPartOf().empty())
 			questArtifacts.push_back(art->getId());
 	}
 }

+ 1 - 0
lib/rmg/modificators/QuestArtifactPlacer.cpp

@@ -15,6 +15,7 @@
 #include "TreasurePlacer.h"
 #include "../CZonePlacer.h"
 #include "../../GameLibrary.h"
+#include "../../entities/artifact/CArtHandler.h"
 #include "../../mapObjectConstructors/AObjectTypeHandler.h"
 #include "../../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../../mapObjects/MapObjects.h"

+ 0 - 1
lib/rmg/modificators/TreasurePlacer.cpp

@@ -21,7 +21,6 @@
 #include "../CZonePlacer.h"
 #include "PrisonHeroPlacer.h"
 #include "QuestArtifactPlacer.h"
-#include "../../ArtifactUtils.h"
 #include "../../mapObjectConstructors/AObjectTypeHandler.h"
 #include "../../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../../mapObjectConstructors/DwellingInstanceConstructor.h"

+ 1 - 0
lib/serializer/RegisterTypes.h

@@ -17,6 +17,7 @@
 #include "../bonuses/Propagators.h"
 #include "../bonuses/Updaters.h"
 #include "../campaign/CampaignState.h"
+#include "../entities/artifact/CArtifact.h"
 #include "../gameState/CGameState.h"
 #include "../gameState/CGameStateCampaign.h"
 #include "../gameState/TavernHeroesPool.h"

+ 1 - 1
lib/texts/MetaString.cpp

@@ -10,9 +10,9 @@
 #include "StdInc.h"
 #include "MetaString.h"
 
-#include "CArtHandler.h"
 #include "CCreatureHandler.h"
 #include "CCreatureSet.h"
+#include "entities/artifact/CArtifact.h"
 #include "entities/faction/CFaction.h"
 #include "entities/hero/CHero.h"
 #include "texts/CGeneralTextHandler.h"

+ 1 - 1
mapeditor/campaigneditor/scenarioproperties.cpp

@@ -13,9 +13,9 @@
 #include "startingbonus.h"
 
 #include "../../lib/GameLibrary.h"
-#include "../../lib/CArtHandler.h"
 #include "../../lib/CCreatureHandler.h"
 #include "../../lib/texts/CGeneralTextHandler.h"
+#include "../../lib/entities/artifact/CArtHandler.h"
 #include "../../lib/entities/hero/CHeroHandler.h"
 #include "../../lib/campaign/CampaignState.h"
 #include "../../lib/mapping/CMap.h"

+ 1 - 1
mapeditor/campaigneditor/startingbonus.cpp

@@ -14,10 +14,10 @@
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapObjects/CGTownInstance.h"
 #include "../../lib/campaign/CampaignState.h"
+#include "../../lib/entities/artifact/CArtHandler.h"
 #include "../../lib/entities/building/CBuilding.h"
 #include "../../lib/entities/hero/CHero.h"
 #include "../../lib/mapping/CMap.h"
-#include "../../lib/CArtHandler.h"
 #include "../../lib/CSkillHandler.h"
 #include "../../lib/CCreatureHandler.h"
 #include "../../lib/spells/CSpellHandler.h"

+ 3 - 1
mapeditor/inspector/artifactwidget.cpp

@@ -12,9 +12,11 @@
 #include "ui_artifactwidget.h"
 #include "inspector.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/GameLibrary.h"
 #include "../../lib/constants/StringConstants.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtHandler.h"
+#include "../../lib/entities/artifact/CArtifactFittingSet.h"
 
 ArtifactWidget::ArtifactWidget(CArtifactFittingSet & fittingSet, QWidget * parent) :
 	QDialog(parent),

+ 5 - 1
mapeditor/inspector/artifactwidget.h

@@ -10,7 +10,11 @@
 #pragma once
 
 #include <QDialog>
-#include "../../lib/mapObjects/CGHeroInstance.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+class ArtifactPosition;
+class CArtifactFittingSet;
+VCMI_LIB_NAMESPACE_END
 
 namespace Ui {
 class ArtifactWidget;

+ 2 - 1
mapeditor/inspector/heroartifactswidget.cpp

@@ -15,8 +15,9 @@
 #include "mapeditorroles.h"
 #include "../mapcontroller.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/constants/StringConstants.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtHandler.h"
 #include "../../lib/mapping/CMap.h"
 
 HeroArtifactsWidget::HeroArtifactsWidget(MapController & controller, CGHeroInstance & h, QWidget * parent) :

+ 1 - 0
mapeditor/inspector/heroartifactswidget.h

@@ -12,6 +12,7 @@
 #include <QDialog>
 #include "baseinspectoritemdelegate.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
+#include "../../lib/entities/artifact/CArtifactFittingSet.h"
 
 namespace Ui {
 class HeroArtifactsWidget;

+ 0 - 2
mapeditor/inspector/inspector.cpp

@@ -9,8 +9,6 @@
  */
 #include "StdInc.h"
 #include "inspector.h"
-#include "../lib/ArtifactUtils.h"
-#include "../lib/CArtHandler.h"
 #include "../lib/entities/hero/CHeroClass.h"
 #include "../lib/entities/hero/CHeroHandler.h"
 #include "../lib/spells/CSpellHandler.h"

+ 1 - 1
mapeditor/inspector/questwidget.cpp

@@ -14,9 +14,9 @@
 #include "../lib/GameLibrary.h"
 #include "../lib/CSkillHandler.h"
 #include "../lib/spells/CSpellHandler.h"
-#include "../lib/CArtHandler.h"
 #include "../lib/CCreatureHandler.h"
 #include "../lib/constants/StringConstants.h"
+#include "../lib/entities/artifact/CArtHandler.h"
 #include "../lib/mapping/CMap.h"
 #include "../lib/mapObjects/CGHeroInstance.h"
 #include "../lib/mapObjects/CGCreature.h"

+ 2 - 1
mapeditor/inspector/rewardswidget.cpp

@@ -13,9 +13,9 @@
 #include "../lib/GameLibrary.h"
 #include "../lib/CSkillHandler.h"
 #include "../lib/spells/CSpellHandler.h"
-#include "../lib/CArtHandler.h"
 #include "../lib/CCreatureHandler.h"
 #include "../lib/constants/StringConstants.h"
+#include "../lib/entities/artifact/CArtifact.h"
 #include "../lib/mapping/CMap.h"
 #include "../lib/rewardable/Configuration.h"
 #include "../lib/rewardable/Limiter.h"
@@ -23,6 +23,7 @@
 #include "../lib/mapObjects/CGPandoraBox.h"
 #include "../lib/mapObjects/CQuest.h"
 
+#include <vcmi/ArtifactService.h>
 #include <vcmi/HeroTypeService.h>
 #include <vcmi/HeroType.h>
 #include <vcmi/HeroClassService.h>

+ 1 - 1
mapeditor/mapcontroller.cpp

@@ -11,8 +11,8 @@
 #include "StdInc.h"
 #include "mapcontroller.h"
 
-#include "../lib/ArtifactUtils.h"
 #include "../lib/GameConstants.h"
+#include "../lib/entities/artifact/CArtifact.h"
 #include "../lib/entities/hero/CHeroClass.h"
 #include "../lib/entities/hero/CHeroHandler.h"
 #include "../lib/mapObjectConstructors/AObjectTypeHandler.h"

+ 1 - 1
mapeditor/mapsettings/mapsettings.cpp

@@ -13,8 +13,8 @@
 #include "ui_mapsettings.h"
 #include "mainwindow.h"
 
-#include "../../lib/CArtHandler.h"
 #include "../../lib/CSkillHandler.h"
+#include "../../lib/entities/artifact/CArtHandler.h"
 #include "../../lib/entities/hero/CHeroHandler.h"
 #include "../../lib/spells/CSpellHandler.h"
 

+ 1 - 0
mapeditor/mapsettings/victoryconditions.cpp

@@ -13,6 +13,7 @@
 #include "../mapcontroller.h"
 
 #include "../../lib/constants/StringConstants.h"
+#include "../../lib/entities/artifact/CArtHandler.h"
 #include "../../lib/entities/faction/CTownHandler.h"
 #include "../../lib/mapObjects/CGCreature.h"
 #include "../../lib/texts/CGeneralTextHandler.h"

+ 3 - 2
server/CGameHandler.cpp

@@ -23,8 +23,6 @@
 #include "queries/MapQueries.h"
 #include "queries/VisitQueries.h"
 
-#include "../lib/ArtifactUtils.h"
-#include "../lib/CArtHandler.h"
 #include "../lib/CConfigHandler.h"
 #include "../lib/CCreatureHandler.h"
 #include "../lib/CCreatureSet.h"
@@ -45,6 +43,9 @@
 
 #include "../lib/battle/BattleInfo.h"
 
+#include "../lib/entities/artifact/ArtifactUtils.h"
+#include "../lib/entities/artifact/CArtifact.h"
+#include "../lib/entities/artifact/CArtifactFittingSet.h"
 #include "../lib/entities/building/CBuilding.h"
 #include "../lib/entities/faction/CTownHandler.h"
 #include "../lib/entities/hero/CHeroHandler.h"

+ 2 - 1
server/battles/BattleResultProcessor.cpp

@@ -17,11 +17,12 @@
 #include "../queries/QueriesProcessor.h"
 #include "../queries/BattleQueries.h"
 
-#include "../../lib/ArtifactUtils.h"
 #include "../../lib/CStack.h"
 #include "../../lib/CPlayerState.h"
 #include "../../lib/IGameSettings.h"
 #include "../../lib/battle/SideInBattle.h"
+#include "../../lib/entities/artifact/ArtifactUtils.h"
+#include "../../lib/entities/artifact/CArtifactFittingSet.h"
 #include "../../lib/gameState/CGameState.h"
 #include "../../lib/mapObjects/CGTownInstance.h"
 #include "../../lib/networkPacks/PacksForClientBattle.h"

+ 1 - 0
server/processors/PlayerMessageProcessor.cpp

@@ -18,6 +18,7 @@
 
 #include "../../lib/CPlayerState.h"
 #include "../../lib/StartInfo.h"
+#include "../../lib/entities/artifact/CArtHandler.h"
 #include "../../lib/entities/building/CBuilding.h"
 #include "../../lib/entities/hero/CHeroHandler.h"
 #include "../../lib/gameState/CGameState.h"

+ 1 - 1
test/entity/CArtifactTest.cpp

@@ -9,7 +9,7 @@
  */
 #include "StdInc.h"
 
-#include "../../lib/CArtHandler.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 
 namespace test
 {