瀏覽代碼

Merge pull request #2202 from IvanSavenko/map_objects_reorganization

Map objects code reorganization
Ivan Savenko 2 年之前
父節點
當前提交
8d278e653f
共有 100 個文件被更改,包括 1839 次插入1571 次删除
  1. 1 0
      AI/Nullkiller/AIGateway.cpp
  2. 0 1
      AI/Nullkiller/AIUtility.h
  3. 4 1
      AI/Nullkiller/Engine/FuzzyHelper.cpp
  4. 3 1
      AI/Nullkiller/Engine/PriorityEvaluator.cpp
  5. 0 1
      AI/VCAI/AIUtility.h
  6. 7 2
      AI/VCAI/FuzzyHelper.cpp
  7. 1 0
      AI/VCAI/MapObjectsEvaluator.cpp
  8. 2 1
      AI/VCAI/MapObjectsEvaluator.h
  9. 1 0
      AI/VCAI/VCAI.cpp
  10. 0 1
      CCallback.cpp
  11. 1 1
      client/CPlayerInterface.cpp
  12. 1 0
      client/NetPacksClient.cpp
  13. 1 0
      client/mapView/MapRenderer.cpp
  14. 1 0
      client/mapView/MapViewCache.cpp
  15. 2 1
      client/mapView/mapHandler.cpp
  16. 0 2
      client/render/Graphics.cpp
  17. 2 0
      client/windows/GUIClasses.cpp
  18. 19 6
      cmake_modules/VCMI_lib.cmake
  19. 2 1
      lib/CArtHandler.cpp
  20. 2 1
      lib/CCreatureHandler.cpp
  21. 0 1
      lib/CGameInfoCallback.cpp
  22. 1 2
      lib/CGameInterface.h
  23. 1 2
      lib/CGameState.cpp
  24. 2 2
      lib/CHeroHandler.cpp
  25. 1 2
      lib/CModHandler.cpp
  26. 2 2
      lib/CTownHandler.cpp
  27. 1 1
      lib/CTownHandler.h
  28. 0 1
      lib/GameConstants.cpp
  29. 4 1
      lib/IGameCallback.cpp
  30. 1 1
      lib/JsonRandom.cpp
  31. 4 0
      lib/NetPacks.h
  32. 3 2
      lib/NetPacksLib.cpp
  33. 2 1
      lib/PathfinderUtil.h
  34. 1 1
      lib/ResourceSet.cpp
  35. 2 2
      lib/VCMI_Lib.cpp
  36. 225 0
      lib/mapObjectConstructors/AObjectTypeHandler.cpp
  37. 127 0
      lib/mapObjectConstructors/AObjectTypeHandler.h
  38. 5 206
      lib/mapObjectConstructors/CObjectClassesHandler.cpp
  39. 138 0
      lib/mapObjectConstructors/CObjectClassesHandler.h
  40. 2 1
      lib/mapObjectConstructors/CRewardableConstructor.cpp
  41. 1 1
      lib/mapObjectConstructors/CRewardableConstructor.h
  42. 9 8
      lib/mapObjectConstructors/CommonConstructors.cpp
  43. 10 3
      lib/mapObjectConstructors/CommonConstructors.h
  44. 60 0
      lib/mapObjectConstructors/IObjectInfo.h
  45. 46 0
      lib/mapObjectConstructors/RandomMapInfo.h
  46. 28 0
      lib/mapObjectConstructors/SObjectSounds.h
  47. 1 1
      lib/mapObjects/CArmedInstance.h
  48. 2 1
      lib/mapObjects/CBank.cpp
  49. 0 1
      lib/mapObjects/CBank.h
  50. 2 1
      lib/mapObjects/CGDwelling.cpp
  51. 2 1
      lib/mapObjects/CGHeroInstance.cpp
  52. 0 2
      lib/mapObjects/CGHeroInstance.h
  53. 2 157
      lib/mapObjects/CGMarket.cpp
  54. 2 18
      lib/mapObjects/CGMarket.h
  55. 348 0
      lib/mapObjects/CGObjectInstance.cpp
  56. 145 0
      lib/mapObjects/CGObjectInstance.h
  57. 0 1
      lib/mapObjects/CGPandoraBox.h
  58. 1 1
      lib/mapObjects/CGTownBuilding.h
  59. 2 1
      lib/mapObjects/CGTownInstance.cpp
  60. 1 3
      lib/mapObjects/CGTownInstance.h
  61. 0 337
      lib/mapObjects/CObjectClassesHandler.h
  62. 1 496
      lib/mapObjects/CObjectHandler.cpp
  63. 2 226
      lib/mapObjects/CObjectHandler.h
  64. 1 1
      lib/mapObjects/CQuest.cpp
  65. 0 5
      lib/mapObjects/CQuest.h
  66. 2 1
      lib/mapObjects/CRewardableObject.cpp
  67. 179 0
      lib/mapObjects/IMarket.cpp
  68. 35 0
      lib/mapObjects/IMarket.h
  69. 188 0
      lib/mapObjects/IObjectInterface.cpp
  70. 107 0
      lib/mapObjects/IObjectInterface.h
  71. 0 1
      lib/mapObjects/MiscObjects.cpp
  72. 4 1
      lib/mapObjects/MiscObjects.h
  73. 2 3
      lib/mapObjects/ObjectTemplate.cpp
  74. 1 1
      lib/mapping/CMap.cpp
  75. 0 2
      lib/mapping/CMapEditManager.cpp
  76. 3 1
      lib/mapping/MapFormatH3M.cpp
  77. 2 2
      lib/mapping/MapFormatJson.cpp
  78. 3 1
      lib/mapping/MapIdentifiersH3M.cpp
  79. 4 3
      lib/mapping/ObstacleProxy.cpp
  80. 4 3
      lib/registerTypes/RegisterTypes.h
  81. 0 1
      lib/registerTypes/TypesClientPacks1.cpp
  82. 0 1
      lib/registerTypes/TypesClientPacks2.cpp
  83. 0 1
      lib/registerTypes/TypesLobbyPacks.cpp
  84. 0 1
      lib/registerTypes/TypesMapObjects1.cpp
  85. 0 1
      lib/registerTypes/TypesMapObjects2.cpp
  86. 0 1
      lib/registerTypes/TypesMapObjects3.cpp
  87. 0 1
      lib/registerTypes/TypesServerPacks.cpp
  88. 1 0
      lib/rewardable/Configuration.h
  89. 3 0
      lib/rewardable/Info.cpp
  90. 1 1
      lib/rewardable/Info.h
  91. 2 1
      lib/rewardable/Interface.h
  92. 15 0
      lib/rewardable/Limiter.cpp
  93. 7 10
      lib/rewardable/Limiter.h
  94. 17 0
      lib/rewardable/Reward.cpp
  95. 10 12
      lib/rewardable/Reward.h
  96. 2 1
      lib/rmg/CMapGenerator.cpp
  97. 2 2
      lib/rmg/Functions.cpp
  98. 3 3
      lib/rmg/RmgObject.cpp
  99. 2 1
      lib/rmg/modificators/ConnectionsPlacer.cpp
  100. 2 1
      lib/rmg/modificators/MinePlacer.cpp

+ 1 - 0
AI/Nullkiller/AIGateway.cpp

@@ -11,6 +11,7 @@
 
 #include "../../lib/UnlockGuard.h"
 #include "../../lib/mapObjects/MapObjects.h"
+#include "../../lib/mapObjects/ObjectTemplate.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/CHeroHandler.h"
 #include "../../lib/GameSettings.h"

+ 0 - 1
AI/Nullkiller/AIUtility.h

@@ -45,7 +45,6 @@
 #include "../../lib/CTownHandler.h"
 #include "../../lib/spells/CSpellHandler.h"
 #include "../../lib/CStopWatch.h"
-#include "../../lib/mapObjects/CObjectHandler.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/CPathfinder.h"
 #include "../../CCallback.h"

+ 4 - 1
AI/Nullkiller/Engine/FuzzyHelper.cpp

@@ -10,10 +10,13 @@
 #include "../StdInc.h"
 #include "FuzzyHelper.h"
 
-#include "../../../lib/mapObjects/CommonConstructors.h"
 #include "../Goals/Goals.h"
 #include "Nullkiller.h"
 
+#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
+#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
+#include "../../../lib/mapObjectConstructors/CommonConstructors.h"
+
 namespace NKAI
 {
 

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

@@ -11,8 +11,10 @@
 #include <limits>
 
 #include "Nullkiller.h"
+#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
+#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
+#include "../../../lib/mapObjectConstructors/CommonConstructors.h"
 #include "../../../lib/mapObjects/MapObjects.h"
-#include "../../../lib/mapObjects/CommonConstructors.h"
 #include "../../../lib/CCreatureHandler.h"
 #include "../../../lib/CPathfinder.h"
 #include "../../../lib/CGameStateFwd.h"

+ 0 - 1
AI/VCAI/AIUtility.h

@@ -15,7 +15,6 @@
 #include "../../lib/CTownHandler.h"
 #include "../../lib/spells/CSpellHandler.h"
 #include "../../lib/CStopWatch.h"
-#include "../../lib/mapObjects/CObjectHandler.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/CPathfinder.h"
 #include "../../CCallback.h"

+ 7 - 2
AI/VCAI/FuzzyHelper.cpp

@@ -10,10 +10,15 @@
 #include "StdInc.h"
 #include "FuzzyHelper.h"
 
-#include "../../lib/mapObjects/CommonConstructors.h"
 #include "Goals/Goals.h"
 #include "VCAI.h"
 
+#include "../../lib/mapObjectConstructors/AObjectTypeHandler.h"
+#include "../../lib/mapObjectConstructors/CObjectClassesHandler.h"
+#include "../../lib/mapObjectConstructors/CommonConstructors.h"
+#include "../../lib/mapObjects/CBank.h"
+#include "../../lib/mapObjects/CGDwelling.h"
+
 FuzzyHelper * fh;
 
 extern boost::thread_specific_ptr<VCAI> ai;
@@ -332,4 +337,4 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj, const VCAI * ai)
 	default:
 		return 0;
 	}
-}
+}

+ 1 - 0
AI/VCAI/MapObjectsEvaluator.cpp

@@ -4,6 +4,7 @@
 #include "../../lib/VCMI_Lib.h"
 #include "../../lib/CCreatureHandler.h"
 #include "../../lib/CHeroHandler.h"
+#include "../../lib/mapObjectConstructors/AObjectTypeHandler.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapObjects/CGTownInstance.h"
 #include "../../lib/mapObjects/MiscObjects.h"

+ 2 - 1
AI/VCAI/MapObjectsEvaluator.h

@@ -8,7 +8,8 @@
 *
 */
 #pragma once
-#include "../../lib/mapObjects/CObjectClassesHandler.h"
+
+#include "../../lib/mapObjectConstructors/CObjectClassesHandler.h"
 
 class MapObjectsEvaluator
 {

+ 1 - 0
AI/VCAI/VCAI.cpp

@@ -16,6 +16,7 @@
 
 #include "../../lib/UnlockGuard.h"
 #include "../../lib/mapObjects/MapObjects.h"
+#include "../../lib/mapObjects/ObjectTemplate.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/CHeroHandler.h"
 #include "../../lib/GameSettings.h"

+ 0 - 1
CCallback.cpp

@@ -16,7 +16,6 @@
 #include "client/Client.h"
 #include "lib/mapping/CMap.h"
 #include "lib/CBuildingHandler.h"
-#include "lib/mapObjects/CObjectClassesHandler.h"
 #include "lib/CGeneralTextHandler.h"
 #include "lib/CHeroHandler.h"
 #include "lib/NetPacks.h"

+ 1 - 1
client/CPlayerInterface.cpp

@@ -52,9 +52,9 @@
 #include "../lib/serializer/BinarySerializer.h"
 #include "../lib/spells/CSpellHandler.h"
 #include "../lib/CTownHandler.h"
-#include "../lib/mapObjects/CObjectClassesHandler.h" // For displaying correct UI when interacting with objects
 #include "../lib/mapObjects/CGTownInstance.h"
 #include "../lib/mapObjects/MiscObjects.h"
+#include "../lib/mapObjects/ObjectTemplate.h"
 #include "../lib/CStack.h"
 #include "../lib/JsonNode.h"
 #include "CMusicHandler.h"

+ 1 - 0
client/NetPacksClient.cpp

@@ -36,6 +36,7 @@
 #include "../lib/CSoundBase.h"
 #include "../lib/StartInfo.h"
 #include "../lib/CConfigHandler.h"
+#include "../lib/mapObjects/CGMarket.h"
 #include "../lib/mapping/CCampaignHandler.h"
 #include "../lib/CGameState.h"
 #include "../lib/CStack.h"

+ 1 - 0
client/mapView/MapRenderer.cpp

@@ -27,6 +27,7 @@
 #include "../../lib/TerrainHandler.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapObjects/MiscObjects.h"
+#include "../../lib/mapObjects/ObjectTemplate.h"
 #include "../../lib/mapping/CMapDefines.h"
 
 struct NeighborTilesInfo

+ 1 - 0
client/mapView/MapViewCache.cpp

@@ -20,6 +20,7 @@
 #include "../render/IImage.h"
 
 #include "../../lib/mapObjects/CObjectHandler.h"
+#include "../../lib/int3.h"
 
 MapViewCache::~MapViewCache() = default;
 

+ 2 - 1
client/mapView/mapHandler.cpp

@@ -19,8 +19,9 @@
 #include "../../lib/CGeneralTextHandler.h"
 #include "../../lib/TerrainHandler.h"
 #include "../../lib/UnlockGuard.h"
+#include "../../lib/mapObjectConstructors/CObjectClassesHandler.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
-#include "../../lib/mapObjects/CObjectClassesHandler.h"
+#include "../../lib/mapObjects/ObjectTemplate.h"
 #include "../../lib/mapping/CMap.h"
 
 bool CMapHandler::hasOngoingAnimations()

+ 0 - 2
client/render/Graphics.cpp

@@ -36,8 +36,6 @@
 #include "../lib/JsonNode.h"
 #include "../lib/vcmi_endian.h"
 #include "../lib/CStopWatch.h"
-#include "../lib/mapObjects/CObjectClassesHandler.h"
-#include "../lib/mapObjects/CObjectHandler.h"
 #include "../lib/CHeroHandler.h"
 
 #include <SDL_surface.h>

+ 2 - 0
client/windows/GUIClasses.cpp

@@ -46,7 +46,9 @@
 #include "../../CCallback.h"
 
 #include "../lib/mapObjects/CGHeroInstance.h"
+#include "../lib/mapObjects/CGMarket.h"
 #include "../lib/mapObjects/CGTownInstance.h"
+#include "../lib/mapObjects/ObjectTemplate.h"
 #include "../lib/CArtHandler.h"
 #include "../lib/CBuildingHandler.h"
 #include "../lib/CConfigHandler.h"

+ 19 - 6
cmake_modules/VCMI_lib.cmake

@@ -65,20 +65,25 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/logging/CBasicLogConfigurator.cpp
 		${MAIN_LIB_DIR}/logging/CLogger.cpp
 
+		${MAIN_LIB_DIR}/mapObjectConstructors/AObjectTypeHandler.cpp
+		${MAIN_LIB_DIR}/mapObjectConstructors/CObjectClassesHandler.cpp
+		${MAIN_LIB_DIR}/mapObjectConstructors/CommonConstructors.cpp
+		${MAIN_LIB_DIR}/mapObjectConstructors/CRewardableConstructor.cpp
+
 		${MAIN_LIB_DIR}/mapObjects/CArmedInstance.cpp
 		${MAIN_LIB_DIR}/mapObjects/CBank.cpp
 		${MAIN_LIB_DIR}/mapObjects/CGDwelling.cpp
 		${MAIN_LIB_DIR}/mapObjects/CGHeroInstance.cpp
 		${MAIN_LIB_DIR}/mapObjects/CGMarket.cpp
+		${MAIN_LIB_DIR}/mapObjects/CGObjectInstance.cpp
 		${MAIN_LIB_DIR}/mapObjects/CGPandoraBox.cpp
 		${MAIN_LIB_DIR}/mapObjects/CGTownBuilding.cpp
 		${MAIN_LIB_DIR}/mapObjects/CGTownInstance.cpp
-		${MAIN_LIB_DIR}/mapObjects/CObjectClassesHandler.cpp
 		${MAIN_LIB_DIR}/mapObjects/CObjectHandler.cpp
-		${MAIN_LIB_DIR}/mapObjects/CommonConstructors.cpp
 		${MAIN_LIB_DIR}/mapObjects/CQuest.cpp
-		${MAIN_LIB_DIR}/mapObjects/CRewardableConstructor.cpp
 		${MAIN_LIB_DIR}/mapObjects/CRewardableObject.cpp
+		${MAIN_LIB_DIR}/mapObjects/IMarket.cpp
+		${MAIN_LIB_DIR}/mapObjects/IObjectInterface.cpp
 		${MAIN_LIB_DIR}/mapObjects/MiscObjects.cpp
 		${MAIN_LIB_DIR}/mapObjects/ObjectTemplate.cpp
 
@@ -362,20 +367,28 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/logging/CBasicLogConfigurator.h
 		${MAIN_LIB_DIR}/logging/CLogger.h
 
+		${MAIN_LIB_DIR}/mapObjectConstructors/AObjectTypeHandler.h
+		${MAIN_LIB_DIR}/mapObjectConstructors/CObjectClassesHandler.h
+		${MAIN_LIB_DIR}/mapObjectConstructors/CommonConstructors.h
+		${MAIN_LIB_DIR}/mapObjectConstructors/CRewardableConstructor.h
+		${MAIN_LIB_DIR}/mapObjectConstructors/IObjectInfo.h
+		${MAIN_LIB_DIR}/mapObjectConstructors/RandomMapInfo.h
+		${MAIN_LIB_DIR}/mapObjectConstructors/SObjectSounds.h
+
 		${MAIN_LIB_DIR}/mapObjects/CArmedInstance.h
 		${MAIN_LIB_DIR}/mapObjects/CBank.h
 		${MAIN_LIB_DIR}/mapObjects/CGDwelling.h
 		${MAIN_LIB_DIR}/mapObjects/CGHeroInstance.h
 		${MAIN_LIB_DIR}/mapObjects/CGMarket.h
+		${MAIN_LIB_DIR}/mapObjects/CGObjectInstance.h
 		${MAIN_LIB_DIR}/mapObjects/CGPandoraBox.h
 		${MAIN_LIB_DIR}/mapObjects/CGTownBuilding.h
 		${MAIN_LIB_DIR}/mapObjects/CGTownInstance.h
-		${MAIN_LIB_DIR}/mapObjects/CObjectClassesHandler.h
 		${MAIN_LIB_DIR}/mapObjects/CObjectHandler.h
-		${MAIN_LIB_DIR}/mapObjects/CommonConstructors.h
 		${MAIN_LIB_DIR}/mapObjects/CQuest.h
-		${MAIN_LIB_DIR}/mapObjects/CRewardableConstructor.h
 		${MAIN_LIB_DIR}/mapObjects/CRewardableObject.h
+		${MAIN_LIB_DIR}/mapObjects/IMarket.h
+		${MAIN_LIB_DIR}/mapObjects/IObjectInterface.h
 		${MAIN_LIB_DIR}/mapObjects/MapObjects.h
 		${MAIN_LIB_DIR}/mapObjects/MiscObjects.h
 		${MAIN_LIB_DIR}/mapObjects/ObjectTemplate.h

+ 2 - 1
lib/CArtHandler.cpp

@@ -23,7 +23,8 @@
 #include "StringConstants.h"
 #include "CRandomGenerator.h"
 
-#include "mapObjects/CObjectClassesHandler.h"
+#include "mapObjectConstructors/AObjectTypeHandler.h"
+#include "mapObjectConstructors/CObjectClassesHandler.h"
 #include "mapping/CMap.h"
 #include "serializer/JsonSerializeFormat.h"
 

+ 2 - 1
lib/CCreatureHandler.cpp

@@ -23,7 +23,8 @@
 #include "bonuses/Updaters.h"
 #include "serializer/JsonDeserializer.h"
 #include "serializer/JsonUpdater.h"
-#include "mapObjects/CObjectClassesHandler.h"
+#include "mapObjectConstructors/AObjectTypeHandler.h"
+#include "mapObjectConstructors/CObjectClassesHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 0 - 1
lib/CGameInfoCallback.cpp

@@ -12,7 +12,6 @@
 
 #include "CGameState.h" // PlayerState
 #include "CGeneralTextHandler.h"
-#include "mapObjects/CObjectHandler.h" // for CGObjectInstance
 #include "StartInfo.h" // for StartInfo
 #include "battle/BattleInfo.h" // for BattleInfo
 #include "NetPacks.h" // for InfoWindow

+ 1 - 2
lib/CGameInterface.h

@@ -15,8 +15,6 @@
 
 #include "spells/ViewSpellInt.h"
 
-#include "mapObjects/CObjectHandler.h"
-
 class CBattleCallback;
 class CCallback;
 
@@ -68,6 +66,7 @@ namespace scripting
 }
 #endif
 
+using TTeleportExitsList = std::vector<std::pair<ObjectInstanceID, int3>>;
 
 class DLL_LINKAGE CBattleGameInterface : public IBattleEventsReceiver
 {

+ 1 - 2
lib/CGameState.cpp

@@ -11,20 +11,19 @@
 #include "CGameState.h"
 
 #include "mapping/CCampaignHandler.h"
-#include "mapObjects/CObjectClassesHandler.h"
 #include "CArtHandler.h"
 #include "CBuildingHandler.h"
 #include "CGeneralTextHandler.h"
 #include "CTownHandler.h"
 #include "spells/CSpellHandler.h"
 #include "CHeroHandler.h"
-#include "mapObjects/CObjectHandler.h"
 #include "CModHandler.h"
 #include "GameSettings.h"
 #include "TerrainHandler.h"
 #include "CSkillHandler.h"
 #include "mapping/CMap.h"
 #include "mapping/CMapService.h"
+#include "mapObjectConstructors/CObjectClassesHandler.h"
 #include "StartInfo.h"
 #include "NetPacks.h"
 #include "registerTypes/RegisterTypes.h"

+ 2 - 2
lib/CHeroHandler.cpp

@@ -20,12 +20,12 @@
 #include "GameSettings.h"
 #include "CModHandler.h"
 #include "CTownHandler.h"
-#include "mapObjects/CObjectHandler.h" //for hero specialty
 #include "CSkillHandler.h"
-#include "mapObjects/CObjectClassesHandler.h"
 #include "BattleFieldHandler.h"
 #include "bonuses/Limiters.h"
 #include "bonuses/Updaters.h"
+#include "mapObjectConstructors/AObjectTypeHandler.h"
+#include "mapObjectConstructors/CObjectClassesHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 1 - 2
lib/CModHandler.cpp

@@ -9,7 +9,6 @@
  */
 #include "StdInc.h"
 #include "CModHandler.h"
-#include "mapObjects/CObjectClassesHandler.h"
 #include "rmg/CRmgTemplateStorage.h"
 #include "filesystem/FileStream.h"
 #include "filesystem/AdapterLoaders.h"
@@ -20,7 +19,6 @@
 #include "CArtHandler.h"
 #include "CTownHandler.h"
 #include "CHeroHandler.h"
-#include "mapObjects/CObjectHandler.h"
 #include "StringConstants.h"
 #include "CStopWatch.h"
 #include "IHandlerBase.h"
@@ -35,6 +33,7 @@
 #include "TerrainHandler.h"
 #include "BattleFieldHandler.h"
 #include "ObstacleHandler.h"
+#include "mapObjectConstructors/CObjectClassesHandler.h"
 
 #include <vstd/StringUtils.h>
 

+ 2 - 2
lib/CTownHandler.cpp

@@ -22,11 +22,11 @@
 #include "TerrainHandler.h"
 #include "spells/CSpellHandler.h"
 #include "filesystem/Filesystem.h"
-#include "mapObjects/CObjectClassesHandler.h"
-#include "mapObjects/CObjectHandler.h"
 #include "bonuses/Bonus.h"
 #include "bonuses/Propagators.h"
 #include "ResourceSet.h"
+#include "mapObjectConstructors/AObjectTypeHandler.h"
+#include "mapObjectConstructors/CObjectClassesHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 1 - 1
lib/CTownHandler.h

@@ -22,7 +22,7 @@
 #include "bonuses/Bonus.h"
 #include "bonuses/BonusList.h"
 #include "Point.h"
-#include "mapObjects/CRewardableConstructor.h"
+#include "rewardable/Info.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 0 - 1
lib/GameConstants.cpp

@@ -26,7 +26,6 @@
 #include <vcmi/spells/Service.h>
 
 #include "VCMI_Lib.h"
-#include "mapObjects/CObjectClassesHandler.h"//todo: remove
 #include "CArtHandler.h"//todo: remove
 #include "CCreatureHandler.h"//todo: remove
 #include "spells/CSpellHandler.h" //todo: remove

+ 4 - 1
lib/IGameCallback.cpp

@@ -28,8 +28,11 @@
 #include "serializer/BinarySerializer.h"
 #include "serializer/CLoadIntegrityValidator.h"
 #include "rmg/CMapGenOptions.h"
+#include "mapObjectConstructors/AObjectTypeHandler.h"
+#include "mapObjectConstructors/CObjectClassesHandler.h"
+#include "mapObjects/CObjectHandler.h"
+#include "mapObjects/ObjectTemplate.h"
 #include "mapping/CCampaignHandler.h"
-#include "mapObjects/CObjectClassesHandler.h"
 #include "StartInfo.h"
 #include "CGameState.h"
 #include "mapping/CMap.h"

+ 1 - 1
lib/JsonRandom.cpp

@@ -23,8 +23,8 @@
 #include "CCreatureSet.h"
 #include "spells/CSpellHandler.h"
 #include "CSkillHandler.h"
-#include "mapObjects/CObjectHandler.h"
 #include "IGameCallback.h"
+#include "mapObjects/IObjectInterface.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 4 - 0
lib/NetPacks.h

@@ -36,6 +36,10 @@ struct ArtSlotInfo;
 struct QuestInfo;
 class IBattleState;
 
+// This one teleport-specific, but has to be available everywhere in callbacks and netpacks
+// For now it's will be there till teleports code refactored and moved into own file
+using TTeleportExitsList = std::vector<std::pair<ObjectInstanceID, int3>>;
+
 struct DLL_LINKAGE Query : public CPackForClient
 {
 	QueryID queryID; // equals to -1 if it is not an actual query (and should not be answered)

+ 3 - 2
lib/NetPacksLib.cpp

@@ -11,10 +11,8 @@
 #include "NetPacks.h"
 #include "NetPackVisitor.h"
 #include "CGeneralTextHandler.h"
-#include "mapObjects/CObjectClassesHandler.h"
 #include "CArtHandler.h"
 #include "CHeroHandler.h"
-#include "mapObjects/CObjectHandler.h"
 #include "CModHandler.h"
 #include "VCMI_Lib.h"
 #include "mapping/CMap.h"
@@ -28,6 +26,9 @@
 #include "StartInfo.h"
 #include "CPlayerState.h"
 #include "TerrainHandler.h"
+#include "mapObjects/CGMarket.h"
+#include "mapObjectConstructors/AObjectTypeHandler.h"
+#include "mapObjectConstructors/CObjectClassesHandler.h"
 #include "mapping/CCampaignHandler.h"
 #include "GameSettings.h"
 

+ 2 - 1
lib/PathfinderUtil.h

@@ -10,7 +10,8 @@
 #pragma once
 
 #include "TerrainHandler.h"
-#include "mapObjects/CObjectHandler.h"
+#include "mapObjects/CGObjectInstance.h"
+#include "mapping/CMapDefines.h"
 #include "CGameState.h"
 
 VCMI_LIB_NAMESPACE_BEGIN

+ 1 - 1
lib/ResourceSet.cpp

@@ -14,8 +14,8 @@
 #include "StringConstants.h"
 #include "JsonNode.h"
 #include "serializer/JsonSerializeFormat.h"
-#include "VCMI_Lib.h"
 #include "mapObjects/CObjectHandler.h"
+#include "VCMI_Lib.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 2 - 2
lib/VCMI_Lib.cpp

@@ -14,9 +14,7 @@
 #include "CArtHandler.h"
 #include "CBonusTypeHandler.h"
 #include "CCreatureHandler.h"
-#include "mapObjects/CObjectClassesHandler.h"
 #include "CHeroHandler.h"
-#include "mapObjects/CObjectHandler.h"
 #include "CTownHandler.h"
 #include "CConfigHandler.h"
 #include "RoadHandler.h"
@@ -34,6 +32,8 @@
 #include "filesystem/Filesystem.h"
 #include "CConsoleHandler.h"
 #include "rmg/CRmgTemplateStorage.h"
+#include "mapObjectConstructors/CObjectClassesHandler.h"
+#include "mapObjects/CObjectHandler.h"
 #include "mapping/CMapEditManager.h"
 #include "ScriptHandler.h"
 #include "BattleFieldHandler.h"

+ 225 - 0
lib/mapObjectConstructors/AObjectTypeHandler.cpp

@@ -0,0 +1,225 @@
+/*
+ * AObjectTypeHandler.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 "AObjectTypeHandler.h"
+
+#include "../CGeneralTextHandler.h"
+#include "../VCMI_Lib.h"
+#include "../mapObjects/CGObjectInstance.h"
+#include "../mapObjects/ObjectTemplate.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+std::string AObjectTypeHandler::getJsonKey() const
+{
+	return modScope + ':' + subTypeName;
+}
+
+si32 AObjectTypeHandler::getIndex() const
+{
+	return type;
+}
+
+si32 AObjectTypeHandler::getSubIndex() const
+{
+	return subtype;
+}
+
+std::string AObjectTypeHandler::getTypeName() const
+{
+	return typeName;
+}
+
+std::string AObjectTypeHandler::getSubTypeName() const
+{
+	return subTypeName;
+}
+
+static ui32 loadJsonOrMax(const JsonNode & input)
+{
+	if (input.isNull())
+		return std::numeric_limits<ui32>::max();
+	else
+		return static_cast<ui32>(input.Float());
+}
+
+void AObjectTypeHandler::init(const JsonNode & input)
+{
+	base = input["base"];
+
+	if (!input["rmg"].isNull())
+	{
+		rmgInfo.value =     static_cast<ui32>(input["rmg"]["value"].Float());
+
+		const JsonNode & mapLimit = input["rmg"]["mapLimit"];
+		if (!mapLimit.isNull())
+			rmgInfo.mapLimit = static_cast<ui32>(mapLimit.Float());
+
+		rmgInfo.zoneLimit = loadJsonOrMax(input["rmg"]["zoneLimit"]);
+		rmgInfo.rarity =    static_cast<ui32>(input["rmg"]["rarity"].Float());
+	} // else block is not needed - set in constructor
+
+	for (auto entry : input["templates"].Struct())
+	{
+		entry.second.setType(JsonNode::JsonType::DATA_STRUCT);
+		JsonUtils::inherit(entry.second, base);
+
+		auto * tmpl = new ObjectTemplate;
+		tmpl->id = Obj(type);
+		tmpl->subid = subtype;
+		tmpl->stringID = entry.first; // FIXME: create "fullID" - type.object.template?
+		try
+		{
+			tmpl->readJson(entry.second);
+			templates.push_back(std::shared_ptr<const ObjectTemplate>(tmpl));
+		}
+		catch (const std::exception & e)
+		{
+			logGlobal->warn("Failed to load terrains for object %s: %s", entry.first, e.what());
+		}
+	}
+
+	for(const JsonNode & node : input["sounds"]["ambient"].Vector())
+		sounds.ambient.push_back(node.String());
+
+	for(const JsonNode & node : input["sounds"]["visit"].Vector())
+		sounds.visit.push_back(node.String());
+
+	for(const JsonNode & node : input["sounds"]["removal"].Vector())
+		sounds.removal.push_back(node.String());
+
+	if(input["aiValue"].isNull())
+		aiValue = std::nullopt;
+	else
+		aiValue = static_cast<std::optional<si32>>(input["aiValue"].Integer());
+
+	if(input["battleground"].getType() == JsonNode::JsonType::DATA_STRING)
+		battlefield = input["battleground"].String();
+	else
+		battlefield = std::nullopt;
+
+	initTypeData(input);
+}
+
+bool AObjectTypeHandler::objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const
+{
+	return false; // by default there are no overrides
+}
+
+void AObjectTypeHandler::preInitObject(CGObjectInstance * obj) const
+{
+	obj->ID = Obj(type);
+	obj->subID = subtype;
+	obj->typeName = typeName;
+	obj->subTypeName = subTypeName;
+}
+
+void AObjectTypeHandler::initTypeData(const JsonNode & input)
+{
+	// empty implementation for overrides
+}
+
+bool AObjectTypeHandler::hasNameTextID() const
+{
+	return false;
+}
+
+std::string AObjectTypeHandler::getNameTextID() const
+{
+	return TextIdentifier("mapObject", modScope, typeName, subTypeName, "name").get();
+}
+
+std::string AObjectTypeHandler::getNameTranslated() const
+{
+	return VLC->generaltexth->translate(getNameTextID());
+}
+
+SObjectSounds AObjectTypeHandler::getSounds() const
+{
+	return sounds;
+}
+
+void AObjectTypeHandler::addTemplate(const std::shared_ptr<const ObjectTemplate> & templ)
+{
+	templates.push_back(templ);
+}
+
+void AObjectTypeHandler::addTemplate(JsonNode config)
+{
+	config.setType(JsonNode::JsonType::DATA_STRUCT); // ensure that input is not null
+	JsonUtils::inherit(config, base);
+	auto * tmpl = new ObjectTemplate;
+	tmpl->id = Obj(type);
+	tmpl->subid = subtype;
+	tmpl->stringID.clear(); // TODO?
+	tmpl->readJson(config);
+	templates.emplace_back(tmpl);
+}
+
+std::vector<std::shared_ptr<const ObjectTemplate>> AObjectTypeHandler::getTemplates() const
+{
+	return templates;
+}
+
+BattleField AObjectTypeHandler::getBattlefield() const
+{
+	return battlefield ? BattleField::fromString(battlefield.value()) : BattleField::NONE;
+}
+
+std::vector<std::shared_ptr<const ObjectTemplate>>AObjectTypeHandler::getTemplates(TerrainId terrainType) const
+{
+	std::vector<std::shared_ptr<const ObjectTemplate>> templates = getTemplates();
+	std::vector<std::shared_ptr<const ObjectTemplate>> filtered;
+	const auto cfun = [&](const std::shared_ptr<const ObjectTemplate> & obj)
+	{
+		return obj->canBePlacedAt(terrainType);
+	};
+	std::copy_if(templates.begin(), templates.end(), std::back_inserter(filtered), cfun);
+	// H3 defines allowed terrains in a weird way - artifacts, monsters and resources have faulty masks here
+	// Perhaps we should re-define faulty templates and remove this workaround (already done for resources)
+	if (type == Obj::ARTIFACT || type == Obj::MONSTER)
+		return templates;
+	else
+		return filtered;
+}
+
+std::shared_ptr<const ObjectTemplate> AObjectTypeHandler::getOverride(TerrainId terrainType, const CGObjectInstance * object) const
+{
+	std::vector<std::shared_ptr<const ObjectTemplate>> ret = getTemplates(terrainType);
+	for (const auto & tmpl: ret)
+	{
+		if (objectFilter(object, tmpl))
+			return tmpl;
+	}
+	return std::shared_ptr<const ObjectTemplate>(); //empty
+}
+
+const RandomMapInfo & AObjectTypeHandler::getRMGInfo()
+{
+	return rmgInfo;
+}
+
+std::optional<si32> AObjectTypeHandler::getAiValue() const
+{
+	return aiValue;
+}
+
+bool AObjectTypeHandler::isStaticObject()
+{
+	return false; // most of classes are not static
+}
+
+void AObjectTypeHandler::afterLoadFinalization()
+{
+}
+
+
+VCMI_LIB_NAMESPACE_END

+ 127 - 0
lib/mapObjectConstructors/AObjectTypeHandler.h

@@ -0,0 +1,127 @@
+/*
+ * AObjectTypeHandler.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 "RandomMapInfo.h"
+#include "SObjectSounds.h"
+#include "../JsonNode.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class ObjectTemplate;
+class CGObjectInstance;
+class CRandomGenerator;
+class IObjectInfo;
+
+/// Class responsible for creation of objects of specific type & subtype
+class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
+{
+	friend class CObjectClassesHandler;
+
+	RandomMapInfo rmgInfo;
+
+	JsonNode base; /// describes base template
+
+	std::vector<std::shared_ptr<const ObjectTemplate>> templates;
+
+	SObjectSounds sounds;
+
+	std::optional<si32> aiValue;
+	std::optional<std::string> battlefield;
+
+	std::string modScope;
+	std::string typeName;
+	std::string subTypeName;
+
+	si32 type;
+	si32 subtype;
+
+protected:
+	void preInitObject(CGObjectInstance * obj) const;
+	virtual bool objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const;
+
+	/// initialization for classes that inherit this one
+	virtual void initTypeData(const JsonNode & input);
+public:
+
+	virtual ~AObjectTypeHandler() = default;
+
+	si32 getIndex() const;
+	si32 getSubIndex() const;
+
+	std::string getTypeName() const;
+	std::string getSubTypeName() const;
+
+	/// loads generic data from Json structure and passes it towards type-specific constructors
+	void init(const JsonNode & input);
+
+	/// returns full form of identifier of this object in form of modName:objectName
+	std::string getJsonKey() const;
+
+	/// Returns object-specific name, if set
+	SObjectSounds getSounds() const;
+
+	void addTemplate(const std::shared_ptr<const ObjectTemplate> & templ);
+	void addTemplate(JsonNode config);
+
+	/// returns all templates matching parameters
+	std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates() const;
+	std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates(const TerrainId terrainType) const;
+
+	/// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle)
+	/// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server)
+	std::shared_ptr<const ObjectTemplate> getOverride(TerrainId terrainType, const CGObjectInstance * object) const;
+
+	BattleField getBattlefield() const;
+
+	const RandomMapInfo & getRMGInfo();
+
+	std::optional<si32> getAiValue() const;
+
+	/// returns true if this class provides custom text ID's instead of generic per-object name
+	virtual bool hasNameTextID() const;
+
+	/// returns object's name in form of translatable text ID
+	virtual std::string getNameTextID() const;
+
+	/// returns object's name in form of human-readable text
+	std::string getNameTranslated() const;
+
+	virtual bool isStaticObject();
+
+	virtual void afterLoadFinalization();
+
+	/// Creates object and set up core properties (like ID/subID). Object is NOT initialized
+	/// to allow creating objects before game start (e.g. map loading)
+	virtual CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const = 0;
+
+	/// Configures object properties. Should be re-entrable, resetting state of the object if necessarily
+	/// This should set remaining properties, including randomized or depending on map
+	virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const = 0;
+
+	/// Returns object configuration, if available. Otherwise returns NULL
+	virtual std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const = 0;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & type;
+		h & subtype;
+		h & templates;
+		h & rmgInfo;
+		h & modScope;
+		h & typeName;
+		h & subTypeName;
+		h & sounds;
+		h & aiValue;
+		h & battlefield;
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 5 - 206
lib/mapObjects/CObjectClassesHandler.cpp → lib/mapObjectConstructors/CObjectClassesHandler.cpp

@@ -21,9 +21,11 @@
 #include "../JsonNode.h"
 #include "../CSoundBase.h"
 
-#include "CRewardableConstructor.h"
-#include "CommonConstructors.h"
-#include "MapObjects.h"
+#include "../mapObjectConstructors/CRewardableConstructor.h"
+#include "../mapObjectConstructors/CommonConstructors.h"
+#include "../mapObjects/CQuest.h"
+#include "../mapObjects/CGPandoraBox.h"
+#include "../mapObjects/ObjectTemplate.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -470,207 +472,4 @@ std::string CObjectClassesHandler::getObjectHandlerName(si32 type) const
 	return objects.at(type)->handlerName;
 }
 
-std::string AObjectTypeHandler::getJsonKey() const
-{
-	return modScope + ':' + subTypeName;
-}
-
-si32 AObjectTypeHandler::getIndex() const
-{
-	return type;
-}
-
-si32 AObjectTypeHandler::getSubIndex() const
-{
-	return subtype;
-}
-
-std::string AObjectTypeHandler::getTypeName() const
-{
-	return typeName;
-}
-
-std::string AObjectTypeHandler::getSubTypeName() const
-{
-	return subTypeName;
-}
-
-static ui32 loadJsonOrMax(const JsonNode & input)
-{
-	if (input.isNull())
-		return std::numeric_limits<ui32>::max();
-	else
-		return static_cast<ui32>(input.Float());
-}
-
-void AObjectTypeHandler::init(const JsonNode & input)
-{
-	base = input["base"];
-
-	if (!input["rmg"].isNull())
-	{
-		rmgInfo.value =     static_cast<ui32>(input["rmg"]["value"].Float());
-
-		const JsonNode & mapLimit = input["rmg"]["mapLimit"];
-		if (!mapLimit.isNull())
-			rmgInfo.mapLimit = static_cast<ui32>(mapLimit.Float());
-
-		rmgInfo.zoneLimit = loadJsonOrMax(input["rmg"]["zoneLimit"]);
-		rmgInfo.rarity =    static_cast<ui32>(input["rmg"]["rarity"].Float());
-	} // else block is not needed - set in constructor
-
-	for (auto entry : input["templates"].Struct())
-	{
-		entry.second.setType(JsonNode::JsonType::DATA_STRUCT);
-		JsonUtils::inherit(entry.second, base);
-
-		auto * tmpl = new ObjectTemplate;
-		tmpl->id = Obj(type);
-		tmpl->subid = subtype;
-		tmpl->stringID = entry.first; // FIXME: create "fullID" - type.object.template?
-		try
-		{
-			tmpl->readJson(entry.second);
-			templates.push_back(std::shared_ptr<const ObjectTemplate>(tmpl));
-		}
-		catch (const std::exception & e)
-		{
-			logGlobal->warn("Failed to load terrains for object %s: %s", entry.first, e.what());
-		}
-	}
-
-	for(const JsonNode & node : input["sounds"]["ambient"].Vector())
-		sounds.ambient.push_back(node.String());
-
-	for(const JsonNode & node : input["sounds"]["visit"].Vector())
-		sounds.visit.push_back(node.String());
-
-	for(const JsonNode & node : input["sounds"]["removal"].Vector())
-		sounds.removal.push_back(node.String());
-
-	if(input["aiValue"].isNull())
-		aiValue = std::nullopt;
-	else
-		aiValue = static_cast<std::optional<si32>>(input["aiValue"].Integer());
-
-	if(input["battleground"].getType() == JsonNode::JsonType::DATA_STRING)
-		battlefield = input["battleground"].String();
-	else
-		battlefield = std::nullopt;
-
-	initTypeData(input);
-}
-
-bool AObjectTypeHandler::objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const
-{
-	return false; // by default there are no overrides
-}
-
-void AObjectTypeHandler::preInitObject(CGObjectInstance * obj) const
-{
-	obj->ID = Obj(type);
-	obj->subID = subtype;
-	obj->typeName = typeName;
-	obj->subTypeName = subTypeName;
-}
-
-void AObjectTypeHandler::initTypeData(const JsonNode & input)
-{
-	// empty implementation for overrides
-}
-
-bool AObjectTypeHandler::hasNameTextID() const
-{
-	return false;
-}
-
-std::string AObjectTypeHandler::getNameTextID() const
-{
-	return TextIdentifier("mapObject", modScope, typeName, subTypeName, "name").get();
-}
-
-std::string AObjectTypeHandler::getNameTranslated() const
-{
-	return VLC->generaltexth->translate(getNameTextID());
-}
-
-SObjectSounds AObjectTypeHandler::getSounds() const
-{
-	return sounds;
-}
-
-void AObjectTypeHandler::addTemplate(const std::shared_ptr<const ObjectTemplate> & templ)
-{
-	templates.push_back(templ);
-}
-
-void AObjectTypeHandler::addTemplate(JsonNode config)
-{
-	config.setType(JsonNode::JsonType::DATA_STRUCT); // ensure that input is not null
-	JsonUtils::inherit(config, base);
-	auto * tmpl = new ObjectTemplate;
-	tmpl->id = Obj(type);
-	tmpl->subid = subtype;
-	tmpl->stringID.clear(); // TODO?
-	tmpl->readJson(config);
-	templates.emplace_back(tmpl);
-}
-
-std::vector<std::shared_ptr<const ObjectTemplate>> AObjectTypeHandler::getTemplates() const
-{
-	return templates;
-}
-
-BattleField AObjectTypeHandler::getBattlefield() const
-{
-	return battlefield ? BattleField::fromString(battlefield.value()) : BattleField::NONE;
-}
-
-std::vector<std::shared_ptr<const ObjectTemplate>>AObjectTypeHandler::getTemplates(TerrainId terrainType) const
-{
-	std::vector<std::shared_ptr<const ObjectTemplate>> templates = getTemplates();
-	std::vector<std::shared_ptr<const ObjectTemplate>> filtered;
-	const auto cfun = [&](const std::shared_ptr<const ObjectTemplate> & obj)
-	{
-		return obj->canBePlacedAt(terrainType);
-	};
-	std::copy_if(templates.begin(), templates.end(), std::back_inserter(filtered), cfun);
-	// H3 defines allowed terrains in a weird way - artifacts, monsters and resources have faulty masks here
-	// Perhaps we should re-define faulty templates and remove this workaround (already done for resources)
-	if (type == Obj::ARTIFACT || type == Obj::MONSTER)
-		return templates;
-	else
-		return filtered;
-}
-
-std::shared_ptr<const ObjectTemplate> AObjectTypeHandler::getOverride(TerrainId terrainType, const CGObjectInstance * object) const
-{
-	std::vector<std::shared_ptr<const ObjectTemplate>> ret = getTemplates(terrainType);
-	for (const auto & tmpl: ret)
-	{
-		if (objectFilter(object, tmpl))
-			return tmpl;
-	}
-	return std::shared_ptr<const ObjectTemplate>(); //empty
-}
-
-const RandomMapInfo & AObjectTypeHandler::getRMGInfo()
-{
-	return rmgInfo;
-}
-
-std::optional<si32> AObjectTypeHandler::getAiValue() const
-{
-	return aiValue;
-}
-
-bool AObjectTypeHandler::isStaticObject()
-{
-	return false; // most of classes are not static
-}
-
-void AObjectTypeHandler::afterLoadFinalization()
-{
-}
-
 VCMI_LIB_NAMESPACE_END

+ 138 - 0
lib/mapObjectConstructors/CObjectClassesHandler.h

@@ -0,0 +1,138 @@
+/*
+ * CObjectClassesHandler.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 "../IHandlerBase.h"
+#include "../JsonNode.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class CRandomGenerator;
+class AObjectTypeHandler;
+class ObjectTemplate;
+struct SObjectSounds;
+
+struct DLL_LINKAGE CompoundMapObjectID
+{
+	si32 primaryID;
+	si32 secondaryID;
+
+	CompoundMapObjectID(si32 primID, si32 secID) : primaryID(primID), secondaryID(secID) {};
+
+	bool operator<(const CompoundMapObjectID& other) const
+	{
+		if(this->primaryID != other.primaryID)
+			return this->primaryID < other.primaryID;
+		else
+			return this->secondaryID < other.secondaryID;
+	}
+
+	bool operator==(const CompoundMapObjectID& other) const
+	{
+		return (this->primaryID == other.primaryID) && (this->secondaryID == other.secondaryID);
+	}
+};
+
+class CGObjectInstance;
+
+using TObjectTypeHandler = std::shared_ptr<AObjectTypeHandler>;
+
+/// Class responsible for creation of adventure map objects of specific type
+class DLL_LINKAGE ObjectClass
+{
+public:
+	std::string modScope;
+	std::string identifier;
+
+	si32 id;
+	std::string handlerName; // ID of handler that controls this object, should be determined using handlerConstructor map
+
+	JsonNode base;
+	std::vector<TObjectTypeHandler> objects;
+
+	ObjectClass() = default;
+
+	std::string getJsonKey() const;
+	std::string getNameTextID() const;
+	std::string getNameTranslated() const;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & id;
+		h & handlerName;
+		h & base;
+		h & objects;
+		h & identifier;
+		h & modScope;
+	}
+};
+
+/// Main class responsible for creation of all adventure map objects
+class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
+{
+	/// list of object handlers, each of them handles only one type
+	std::vector<ObjectClass * > objects;
+
+	/// map that is filled during contruction with all known handlers. Not serializeable due to usage of std::function
+	std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;
+
+	/// container with H3 templates, used only during loading, no need to serialize it
+	using TTemplatesContainer = std::multimap<std::pair<si32, si32>, std::shared_ptr<const ObjectTemplate>>;
+	TTemplatesContainer legacyTemplates;
+
+	TObjectTypeHandler loadSubObjectFromJson(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index);
+
+	void loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj);
+	void loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index);
+
+	ObjectClass * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index);
+
+	void generateExtraMonolithsForRMG();
+
+public:
+	CObjectClassesHandler();
+	~CObjectClassesHandler();
+
+	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 loadSubObject(const std::string & identifier, JsonNode config, si32 ID, si32 subID);
+	void removeSubObject(si32 ID, si32 subID);
+
+	void beforeValidate(JsonNode & object) override;
+	void afterLoadFinalization() override;
+
+	std::vector<bool> getDefaultAllowed() const override;
+
+	/// Queries to detect loaded objects
+	std::set<si32> knownObjects() const;
+	std::set<si32> knownSubObjects(si32 primaryID) const;
+
+	/// returns handler for specified object (ID-based). ObjectHandler keeps ownership
+	TObjectTypeHandler getHandlerFor(si32 type, si32 subtype) const;
+	TObjectTypeHandler getHandlerFor(const std::string & scope, const std::string & type, const std::string & subtype) const;
+	TObjectTypeHandler getHandlerFor(CompoundMapObjectID compoundIdentifier) const;
+
+	std::string getObjectName(si32 type, si32 subtype) const;
+
+	SObjectSounds getObjectSounds(si32 type, si32 subtype) const;
+
+	/// Returns handler string describing the handler (for use in client)
+	std::string getObjectHandlerName(si32 type) const;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & objects;
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 2 - 1
lib/mapObjects/CRewardableConstructor.cpp → lib/mapObjectConstructors/CRewardableConstructor.cpp

@@ -9,7 +9,8 @@
  */
 #include "StdInc.h"
 #include "CRewardableConstructor.h"
-#include "CRewardableObject.h"
+
+#include "../mapObjects/CRewardableObject.h"
 #include "../CGeneralTextHandler.h"
 #include "../IGameCallback.h"
 

+ 1 - 1
lib/mapObjects/CRewardableConstructor.h → lib/mapObjectConstructors/CRewardableConstructor.h

@@ -9,7 +9,7 @@
  */
 #pragma once
 
-#include "../mapObjects/CObjectClassesHandler.h"
+#include "AObjectTypeHandler.h"
 #include "../rewardable/Info.h"
 
 VCMI_LIB_NAMESPACE_BEGIN

+ 9 - 8
lib/mapObjects/CommonConstructors.cpp → lib/mapObjectConstructors/CommonConstructors.cpp

@@ -10,18 +10,19 @@
 #include "StdInc.h"
 #include "CommonConstructors.h"
 
-#include "CGTownInstance.h"
-#include "CGHeroInstance.h"
-#include "CBank.h"
-#include "../TerrainHandler.h"
-#include "../mapping/CMapDefines.h"
-#include "../CHeroHandler.h"
-#include "../CGeneralTextHandler.h"
 #include "../CCreatureHandler.h"
-#include "JsonRandom.h"
+#include "../CGeneralTextHandler.h"
+#include "../CHeroHandler.h"
 #include "../CModHandler.h"
 #include "../IGameCallback.h"
 #include "../StringConstants.h"
+#include "../TerrainHandler.h"
+#include "../mapObjects/CBank.h"
+#include "../mapObjects/CGHeroInstance.h"
+#include "../mapObjects/CGTownInstance.h"
+#include "../mapObjects/ObjectTemplate.h"
+#include "../mapping/CMapDefines.h"
+#include "JsonRandom.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 10 - 3
lib/mapObjects/CommonConstructors.h → lib/mapObjectConstructors/CommonConstructors.h

@@ -9,9 +9,15 @@
 */
 #pragma once
 
-#include "CObjectClassesHandler.h"
-#include "../CTownHandler.h" // for building ID-based filters
-#include "MapObjects.h"
+#include "AObjectTypeHandler.h"
+
+#include "../mapObjects/CGMarket.h"
+#include "../mapObjects/MiscObjects.h"
+#include "../mapObjects/CGHeroInstance.h"
+#include "../mapObjects/CGTownInstance.h"
+#include "../mapObjects/CBank.h"
+#include "../LogicalExpression.h"
+#include "IObjectInfo.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -21,6 +27,7 @@ class CGHeroInstance;
 class CGDwelling;
 class CHeroClass;
 class CBank;
+class CFaction;
 class CStackBasicDescriptor;
 
 /// Class that is used for objects that do not have dedicated handler

+ 60 - 0
lib/mapObjectConstructors/IObjectInfo.h

@@ -0,0 +1,60 @@
+/*
+ * IObjectInfo.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
+
+class DLL_LINKAGE IObjectInfo
+{
+public:
+	struct CArmyStructure
+	{
+		ui32 totalStrength;
+		ui32 shootersStrength;
+		ui32 flyersStrength;
+		ui32 walkersStrength;
+
+		CArmyStructure() :
+			totalStrength(0),
+			shootersStrength(0),
+			flyersStrength(0),
+			walkersStrength(0)
+		{}
+
+		bool operator <(const CArmyStructure & other) const
+		{
+			return this->totalStrength < other.totalStrength;
+		}
+	};
+
+	/// Returns possible composition of guards. Actual guards would be
+	/// somewhere between these two values
+	virtual CArmyStructure minGuards() const { return CArmyStructure(); }
+	virtual CArmyStructure maxGuards() const { return CArmyStructure(); }
+
+	virtual bool givesResources() const { return false; }
+
+	virtual bool givesExperience() const { return false; }
+	virtual bool givesMana() const { return false; }
+	virtual bool givesMovement() const { return false; }
+
+	virtual bool givesPrimarySkills() const { return false; }
+	virtual bool givesSecondarySkills() const { return false; }
+
+	virtual bool givesArtifacts() const { return false; }
+	virtual bool givesCreatures() const { return false; }
+	virtual bool givesSpells() const { return false; }
+
+	virtual bool givesBonuses() const { return false; }
+
+	virtual ~IObjectInfo() = default;
+};
+
+VCMI_LIB_NAMESPACE_END

+ 46 - 0
lib/mapObjectConstructors/RandomMapInfo.h

@@ -0,0 +1,46 @@
+/*
+ * RandomMapInfo.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
+
+/// Structure that describes placement rules for this object in random map
+struct DLL_LINKAGE RandomMapInfo
+{
+	/// How valuable this object is, 1k = worthless, 10k = Utopia-level
+	ui32 value;
+
+	/// How many of such objects can be placed on map, 0 = object can not be placed by RMG
+	std::optional<ui32> mapLimit;
+
+	/// How many of such objects can be placed in one zone, 0 = unplaceable
+	ui32 zoneLimit;
+
+	/// Rarity of object, 5 = extremely rare, 100 = common
+	ui32 rarity;
+
+	RandomMapInfo():
+		value(0),
+		zoneLimit(0),
+		rarity(0)
+	{}
+
+	void setMapLimit(ui32 val) { mapLimit = val; }
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & value;
+		h & mapLimit;
+		h & zoneLimit;
+		h & rarity;
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 28 - 0
lib/mapObjectConstructors/SObjectSounds.h

@@ -0,0 +1,28 @@
+/*
+ * SObjectSounds.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
+
+struct SObjectSounds
+{
+	std::vector<std::string> ambient;
+	std::vector<std::string> visit;
+	std::vector<std::string> removal;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & ambient;
+		h & visit;
+		h & removal;
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/mapObjects/CArmedInstance.h

@@ -9,7 +9,7 @@
  */
 #pragma once
 
-#include "CObjectHandler.h"
+#include "CGObjectInstance.h"
 #include "../CCreatureSet.h"
 #include "../bonuses/CBonusProxy.h"
 #include "../bonuses/CBonusSystemNode.h"

+ 2 - 1
lib/mapObjects/CBank.cpp

@@ -17,7 +17,8 @@
 #include "../NetPacks.h"
 #include "../CGeneralTextHandler.h"
 #include "../CSoundBase.h"
-#include "CommonConstructors.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
+#include "../mapObjectConstructors/CommonConstructors.h"
 #include "../IGameCallback.h"
 #include "../CGameState.h"
 

+ 0 - 1
lib/mapObjects/CBank.h

@@ -9,7 +9,6 @@
  */
 #pragma once
 
-#include "CObjectHandler.h"
 #include "CArmedInstance.h"
 
 VCMI_LIB_NAMESPACE_BEGIN

+ 2 - 1
lib/mapObjects/CGDwelling.cpp

@@ -10,8 +10,9 @@
 
 #include "StdInc.h"
 #include "CGDwelling.h"
-#include "CObjectClassesHandler.h"
 #include "../serializer/JsonSerializeFormat.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../CTownHandler.h"
 #include "../IGameCallback.h"
 #include "../CGameState.h"

+ 2 - 1
lib/mapObjects/CGHeroInstance.cpp

@@ -24,7 +24,6 @@
 #include "../CSoundBase.h"
 #include "../spells/CSpellHandler.h"
 #include "../CSkillHandler.h"
-#include "CObjectClassesHandler.h"
 #include "../IGameCallback.h"
 #include "../CGameState.h"
 #include "../CCreatureHandler.h"
@@ -32,6 +31,8 @@
 #include "../mapping/CMap.h"
 #include "CGTownInstance.h"
 #include "../serializer/JsonSerializeFormat.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../StringConstants.h"
 #include "../battle/Unit.h"
 

+ 0 - 2
lib/mapObjects/CGHeroInstance.h

@@ -11,11 +11,9 @@
 
 #include <vcmi/spells/Caster.h>
 
-#include "CObjectHandler.h"
 #include "CArmedInstance.h"
 
 #include "../CArtHandler.h" // For CArtifactSet
-#include "../CRandomGenerator.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 2 - 157
lib/mapObjects/CGMarket.cpp

@@ -19,166 +19,11 @@
 #include "CGTownInstance.h"
 #include "../GameSettings.h"
 #include "../CSkillHandler.h"
-#include "CObjectClassesHandler.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMarketMode mode) const
-{
-	switch(mode)
-	{
-	case EMarketMode::RESOURCE_RESOURCE:
-		{
-			double effectiveness = std::min((getMarketEfficiency() + 1.0) / 20.0, 0.5);
-
-			double r = VLC->objh->resVals[id1]; //value of given resource
-			double g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
-
-			if(r>g) //if given resource is more expensive than wanted
-			{
-				val2 = static_cast<int>(ceil(r / g));
-				val1 = 1;
-			}
-			else //if wanted resource is more expensive
-			{
-				val1 = static_cast<int>((g / r) + 0.5);
-				val2 = 1;
-			}
-		}
-		break;
-	case EMarketMode::CREATURE_RESOURCE:
-		{
-			const double effectivenessArray[] = {0.0, 0.3, 0.45, 0.50, 0.65, 0.7, 0.85, 0.9, 1.0};
-			double effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)];
-
-			double r = VLC->creatures()->getByIndex(id1)->getRecruitCost(EGameResID::GOLD); //value of given creature in gold
-			double g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
-
-			if(r>g) //if given resource is more expensive than wanted
-			{
-				val2 = static_cast<int>(ceil(r / g));
-				val1 = 1;
-			}
-			else //if wanted resource is more expensive
-			{
-				val1 = static_cast<int>((g / r) + 0.5);
-				val2 = 1;
-			}
-		}
-		break;
-	case EMarketMode::RESOURCE_PLAYER:
-		val1 = 1;
-		val2 = 1;
-		break;
-	case EMarketMode::RESOURCE_ARTIFACT:
-		{
-			double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
-			double r = VLC->objh->resVals[id1]; //value of offered resource
-			double g = VLC->artifacts()->getByIndex(id2)->getPrice() / effectiveness; //value of bought artifact in gold
-
-			if(id1 != 6) //non-gold prices are doubled
-				r /= 2;
-
-			val1 = std::max(1, static_cast<int>((g / r) + 0.5)); //don't sell arts for less than 1 resource
-			val2 = 1;
-		}
-		break;
-	case EMarketMode::ARTIFACT_RESOURCE:
-		{
-			double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
-			double r = VLC->artifacts()->getByIndex(id1)->getPrice() * effectiveness;
-			double g = VLC->objh->resVals[id2];
-
-// 			if(id2 != 6) //non-gold prices are doubled
-// 				r /= 2;
-
-			val1 = 1;
-			val2 = std::max(1, static_cast<int>((r / g) + 0.5)); //at least one resource is given in return
-		}
-		break;
-	case EMarketMode::CREATURE_EXP:
-		{
-			val1 = 1;
-			val2 = (VLC->creh->objects[id1]->getAIValue() / 40) * 5;
-		}
-		break;
-	case EMarketMode::ARTIFACT_EXP:
-		{
-			val1 = 1;
-
-			int givenClass = VLC->arth->objects[id1]->getArtClassSerial();
-			if(givenClass < 0 || givenClass > 3)
-			{
-				val2 = 0;
-				return false;
-			}
-
-			static constexpr int expPerClass[] = {1000, 1500, 3000, 6000};
-			val2 = expPerClass[givenClass];
-		}
-		break;
-	default:
-		assert(0);
-		return false;
-	}
-
-	return true;
-}
-
-bool IMarket::allowsTrade(EMarketMode::EMarketMode mode) const
-{
-	return false;
-}
-
-int IMarket::availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const
-{
-	switch(mode)
-	{
-	case EMarketMode::RESOURCE_RESOURCE:
-	case EMarketMode::ARTIFACT_RESOURCE:
-	case EMarketMode::CREATURE_RESOURCE:
-			return -1;
-	default:
-			return 1;
-	}
-}
-
-std::vector<int> IMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
-{
-	std::vector<int> ret;
-	switch(mode)
-	{
-	case EMarketMode::RESOURCE_RESOURCE:
-	case EMarketMode::ARTIFACT_RESOURCE:
-	case EMarketMode::CREATURE_RESOURCE:
-		for (int i = 0; i < 7; i++)
-			ret.push_back(i);
-	}
-	return ret;
-}
-
-const IMarket * IMarket::castFrom(const CGObjectInstance *obj, bool verbose)
-{
-	auto * imarket = dynamic_cast<const IMarket *>(obj);
-	if(verbose && !imarket)
-		logGlobal->error("Cannot cast to IMarket object type %s", obj->typeName);
-	return imarket;
-}
-
-IMarket::IMarket()
-{
-}
-
-std::vector<EMarketMode::EMarketMode> IMarket::availableModes() const
-{
-	std::vector<EMarketMode::EMarketMode> ret;
-	for (int i = 0; i < EMarketMode::MARTKET_AFTER_LAST_PLACEHOLDER; i++)
-	if(allowsTrade(static_cast<EMarketMode::EMarketMode>(i)))
-		ret.push_back(static_cast<EMarketMode::EMarketMode>(i));
-
-	return ret;
-}
-
 void CGMarket::initObj(CRandomGenerator & rand)
 {
 	VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand);

+ 2 - 18
lib/mapObjects/CGMarket.h

@@ -9,27 +9,11 @@
  */
 #pragma once
 
-#include "CObjectHandler.h"
+#include "CGObjectInstance.h"
+#include "IMarket.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class DLL_LINKAGE IMarket
-{
-public:
-	IMarket();
-	virtual ~IMarket() {}
-
-	virtual int getMarketEfficiency() const = 0;
-	virtual bool allowsTrade(EMarketMode::EMarketMode mode) const;
-	virtual int availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const; //-1 if unlimited
-	virtual std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const;
-
-	bool getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMarketMode mode) const; //val1 - how many units of id1 player has to give to receive val2 units
-	std::vector<EMarketMode::EMarketMode> availableModes() const;
-
-	static const IMarket *castFrom(const CGObjectInstance *obj, bool verbose = true);
-};
-
 class DLL_LINKAGE CGMarket : public CGObjectInstance, public IMarket
 {
 public:

+ 348 - 0
lib/mapObjects/CGObjectInstance.cpp

@@ -0,0 +1,348 @@
+/*
+ * CObjectHandler.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 "CGObjectInstance.h"
+
+#include "CGHeroInstance.h"
+#include "ObjectTemplate.h"
+
+#include "../CGameState.h"
+#include "../CGeneralTextHandler.h"
+#include "../IGameCallback.h"
+#include "../NetPacks.h"
+#include "../StringConstants.h"
+#include "../TerrainHandler.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
+#include "../mapping/CMap.h"
+#include "../serializer/JsonSerializeFormat.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+//TODO: remove constructor
+CGObjectInstance::CGObjectInstance():
+	pos(-1,-1,-1),
+	ID(Obj::NO_OBJ),
+	subID(-1),
+	tempOwner(PlayerColor::UNFLAGGABLE),
+	blockVisit(false)
+{
+}
+
+//must be instantiated in .cpp file for access to complete types of all member fields
+CGObjectInstance::~CGObjectInstance() = default;
+
+int32_t CGObjectInstance::getObjGroupIndex() const
+{
+	return ID.num;
+}
+
+int32_t CGObjectInstance::getObjTypeIndex() const
+{
+	return subID;
+}
+
+int3 CGObjectInstance::getPosition() const
+{
+	return pos;
+}
+
+int3 CGObjectInstance::getTopVisiblePos() const
+{
+	return pos - appearance->getTopVisibleOffset();
+}
+
+void CGObjectInstance::setOwner(const PlayerColor & ow)
+{
+	tempOwner = ow;
+}
+int CGObjectInstance::getWidth() const//returns width of object graphic in tiles
+{
+	return appearance->getWidth();
+}
+int CGObjectInstance::getHeight() const //returns height of object graphic in tiles
+{
+	return appearance->getHeight();
+}
+bool CGObjectInstance::visitableAt(int x, int y) const //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
+{
+	return appearance->isVisitableAt(pos.x - x, pos.y - y);
+}
+bool CGObjectInstance::blockingAt(int x, int y) const
+{
+	return appearance->isBlockedAt(pos.x - x, pos.y - y);
+}
+
+bool CGObjectInstance::coveringAt(int x, int y) const
+{
+	return appearance->isVisibleAt(pos.x - x, pos.y - y);
+}
+
+std::set<int3> CGObjectInstance::getBlockedPos() const
+{
+	std::set<int3> ret;
+	for(int w=0; w<getWidth(); ++w)
+	{
+		for(int h=0; h<getHeight(); ++h)
+		{
+			if(appearance->isBlockedAt(w, h))
+				ret.insert(int3(pos.x - w, pos.y - h, pos.z));
+		}
+	}
+	return ret;
+}
+
+std::set<int3> CGObjectInstance::getBlockedOffsets() const
+{
+	return appearance->getBlockedOffsets();
+}
+
+void CGObjectInstance::setType(si32 ID, si32 subID)
+{
+	auto position = visitablePos();
+	auto oldOffset = getVisitableOffset();
+	auto &tile = cb->gameState()->map->getTile(position);
+
+	//recalculate blockvis tiles - new appearance might have different blockmap than before
+	cb->gameState()->map->removeBlockVisTiles(this, true);
+	auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
+	if(!handler)
+	{
+		logGlobal->error("Unknown object type %d:%d at %s", ID, subID, visitablePos().toString());
+		return;
+	}
+	if(!handler->getTemplates(tile.terType->getId()).empty())
+	{
+		appearance = handler->getTemplates(tile.terType->getId())[0];
+	}
+	else
+	{
+		logGlobal->warn("Object %d:%d at %s has no templates suitable for terrain %s", ID, subID, visitablePos().toString(), tile.terType->getNameTranslated());
+		appearance = handler->getTemplates()[0]; // get at least some appearance since alternative is crash
+	}
+
+	if(this->ID == Obj::PRISON && ID == Obj::HERO)
+	{
+		auto newOffset = getVisitableOffset();
+		// FIXME: potentially unused code - setType is NOT called when releasing hero from prison
+		// instead, appearance update & pos adjustment occurs in GiveHero::applyGs
+
+		// adjust position since hero and prison may have different visitable offset
+		pos = pos - oldOffset + newOffset;
+	}
+
+	this->ID = Obj(ID);
+	this->subID = subID;
+
+	cb->gameState()->map->addBlockVisTiles(this);
+}
+
+void CGObjectInstance::initObj(CRandomGenerator & rand)
+{
+	switch(ID)
+	{
+	case Obj::TAVERN:
+		blockVisit = true;
+		break;
+	}
+}
+
+void CGObjectInstance::setProperty( ui8 what, ui32 val )
+{
+	setPropertyDer(what, val); // call this before any actual changes (needed at least for dwellings)
+
+	switch(what)
+	{
+	case ObjProperty::OWNER:
+		tempOwner = PlayerColor(val);
+		break;
+	case ObjProperty::BLOCKVIS:
+		blockVisit = val;
+		break;
+	case ObjProperty::ID:
+		ID = Obj(val);
+		break;
+	case ObjProperty::SUBID:
+		subID = val;
+		break;
+	}
+}
+
+void CGObjectInstance::setPropertyDer( ui8 what, ui32 val )
+{}
+
+int3 CGObjectInstance::getSightCenter() const
+{
+	return visitablePos();
+}
+
+int CGObjectInstance::getSightRadius() const
+{
+	return 3;
+}
+
+int3 CGObjectInstance::getVisitableOffset() const
+{
+	return appearance->getVisitableOffset();
+}
+
+void CGObjectInstance::giveDummyBonus(const ObjectInstanceID & heroID, BonusDuration::Type duration) const
+{
+	GiveBonus gbonus;
+	gbonus.bonus.type = BonusType::NONE;
+	gbonus.id = heroID.getNum();
+	gbonus.bonus.duration = duration;
+	gbonus.bonus.source = BonusSource::OBJECT;
+	gbonus.bonus.sid = ID;
+	cb->giveHeroBonus(&gbonus);
+}
+
+std::string CGObjectInstance::getObjectName() const
+{
+	return VLC->objtypeh->getObjectName(ID, subID);
+}
+
+std::optional<std::string> CGObjectInstance::getAmbientSound() const
+{
+	const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).ambient;
+	if(!sounds.empty())
+		return sounds.front(); // TODO: Support randomization of ambient sounds
+
+	return std::nullopt;
+}
+
+std::optional<std::string> CGObjectInstance::getVisitSound() const
+{
+	const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).visit;
+	if(!sounds.empty())
+		return *RandomGeneratorUtil::nextItem(sounds, CRandomGenerator::getDefault());
+
+	return std::nullopt;
+}
+
+std::optional<std::string> CGObjectInstance::getRemovalSound() const
+{
+	const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).removal;
+	if(!sounds.empty())
+		return *RandomGeneratorUtil::nextItem(sounds, CRandomGenerator::getDefault());
+
+	return std::nullopt;
+}
+
+std::string CGObjectInstance::getHoverText(PlayerColor player) const
+{
+	auto text = getObjectName();
+	if (tempOwner.isValidPlayer())
+		text += "\n" + VLC->generaltexth->arraytxt[23 + tempOwner.getNum()];
+	return text;
+}
+
+std::string CGObjectInstance::getHoverText(const CGHeroInstance * hero) const
+{
+	return getHoverText(hero->tempOwner);
+}
+
+void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
+{
+	switch(ID)
+	{
+	case Obj::HILL_FORT:
+		{
+			openWindow(EOpenWindowMode::HILL_FORT_WINDOW,id.getNum(),h->id.getNum());
+		}
+		break;
+	case Obj::SANCTUARY:
+		{
+			//You enter the sanctuary and immediately feel as if a great weight has been lifted off your shoulders.  You feel safe here.
+			h->showInfoDialog(114);
+		}
+		break;
+	case Obj::TAVERN:
+		{
+			openWindow(EOpenWindowMode::TAVERN_WINDOW,h->id.getNum(),id.getNum());
+		}
+		break;
+	}
+}
+
+int3 CGObjectInstance::visitablePos() const
+{
+	return pos - getVisitableOffset();
+}
+
+bool CGObjectInstance::isVisitable() const
+{
+	return appearance->isVisitable();
+}
+
+bool CGObjectInstance::passableFor(PlayerColor color) const
+{
+	return false;
+}
+
+void CGObjectInstance::updateFrom(const JsonNode & data)
+{
+
+}
+
+void CGObjectInstance::serializeJson(JsonSerializeFormat & handler)
+{
+	//only save here, loading is handled by map loader
+	if(handler.saving)
+	{
+		handler.serializeString("type", typeName);
+		handler.serializeString("subtype", subTypeName);
+
+		handler.serializeInt("x", pos.x);
+		handler.serializeInt("y", pos.y);
+		handler.serializeInt("l", pos.z);
+		JsonNode app;
+		appearance->writeJson(app, false);
+		handler.serializeRaw("template", app, std::nullopt);
+	}
+
+	{
+		auto options = handler.enterStruct("options");
+		serializeJsonOptions(handler);
+	}
+}
+
+void CGObjectInstance::afterAddToMap(CMap * map)
+{
+	//nothing here
+}
+
+void CGObjectInstance::afterRemoveFromMap(CMap * map)
+{
+	//nothing here
+}
+
+void CGObjectInstance::serializeJsonOptions(JsonSerializeFormat & handler)
+{
+	//nothing here
+}
+
+void CGObjectInstance::serializeJsonOwner(JsonSerializeFormat & handler)
+{
+	ui8 temp = tempOwner.getNum();
+
+	handler.serializeEnum("owner", temp, PlayerColor::NEUTRAL.getNum(), GameConstants::PLAYER_COLOR_NAMES);
+
+	if(!handler.saving)
+		tempOwner = PlayerColor(temp);
+}
+
+BattleField CGObjectInstance::getBattlefield() const
+{
+	return VLC->objtypeh->getHandlerFor(ID, subID)->getBattlefield();
+}
+
+VCMI_LIB_NAMESPACE_END

+ 145 - 0
lib/mapObjects/CGObjectInstance.h

@@ -0,0 +1,145 @@
+/*
+ * CGObjectInstance.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 "IObjectInterface.h"
+#include "../int3.h"
+#include "../bonuses/BonusEnum.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class JsonSerializeFormat;
+class ObjectTemplate;
+class CMap;
+
+class DLL_LINKAGE CGObjectInstance : public IObjectInterface
+{
+public:
+	/// Position of bottom-right corner of object on map
+	int3 pos;
+	/// Type of object, e.g. town, hero, creature.
+	Obj ID;
+	/// Subtype of object, depends on type
+	si32 subID;
+	/// Current owner of an object (when below PLAYER_LIMIT)
+	PlayerColor tempOwner;
+	/// Index of object in map's list of objects
+	ObjectInstanceID id;
+	/// Defines appearance of object on map (animation, blocked tiles, blit order, etc)
+	std::shared_ptr<const ObjectTemplate> appearance;
+	/// If true hero can visit this object only from neighbouring tiles and can't stand on this object
+	bool blockVisit;
+
+	std::string instanceName;
+	std::string typeName;
+	std::string subTypeName;
+
+	CGObjectInstance(); //TODO: remove constructor
+	~CGObjectInstance() override;
+
+	int32_t getObjGroupIndex() const override;
+	int32_t getObjTypeIndex() const override;
+
+	/// "center" tile from which the sight distance is calculated
+	int3 getSightCenter() const;
+
+	PlayerColor getOwner() const override
+	{
+		return this->tempOwner;
+	}
+	void setOwner(const PlayerColor & ow);
+
+	/** APPEARANCE ACCESSORS **/
+
+	int getWidth() const; //returns width of object graphic in tiles
+	int getHeight() const; //returns height of object graphic in tiles
+	bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) (h3m pos)
+	int3 visitablePos() const override;
+	int3 getPosition() const override;
+	int3 getTopVisiblePos() const;
+	bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) (h3m pos)
+	bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) (h3m pos)
+	std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object
+	std::set<int3> getBlockedOffsets() const; //returns set of relative positions blocked by this object
+	bool isVisitable() const; //returns true if object is visitable
+
+	virtual BattleField getBattlefield() const;
+
+	virtual bool isTile2Terrain() const { return false; }
+
+	std::optional<std::string> getAmbientSound() const;
+	std::optional<std::string> getVisitSound() const;
+	std::optional<std::string> getRemovalSound() const;
+
+	/** VIRTUAL METHODS **/
+
+	/// Returns true if player can pass through visitable tiles of this object
+	virtual bool passableFor(PlayerColor color) const;
+	/// Range of revealed map around this object, counting from getSightCenter()
+	virtual int getSightRadius() const;
+	/// returns (x,y,0) offset to a visitable tile of object
+	virtual int3 getVisitableOffset() const;
+	/// Called mostly during map randomization to turn random object into a regular one (e.g. "Random Monster" into "Pikeman")
+	virtual void setType(si32 ID, si32 subID);
+
+	/// returns text visible in status bar with specific hero/player active.
+
+	/// Returns generic name of object, without any player-specific info
+	virtual std::string getObjectName() const;
+
+	/// Returns hover name for situation when there are no selected heroes. Default = object name
+	virtual std::string getHoverText(PlayerColor player) const;
+	/// Returns hero-specific hover name, including visited/not visited info. Default = player-specific name
+	virtual std::string getHoverText(const CGHeroInstance * hero) const;
+
+	/** OVERRIDES OF IObjectInterface **/
+
+	void initObj(CRandomGenerator & rand) override;
+	void onHeroVisit(const CGHeroInstance * h) const override;
+	/// method for synchronous update. Note: For new properties classes should override setPropertyDer instead
+	void setProperty(ui8 what, ui32 val) final;
+
+	virtual void afterAddToMap(CMap * map);
+	virtual void afterRemoveFromMap(CMap * map);
+
+	///Entry point of binary (de-)serialization
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & instanceName;
+		h & typeName;
+		h & subTypeName;
+		h & pos;
+		h & ID;
+		h & subID;
+		h & id;
+		h & tempOwner;
+		h & blockVisit;
+		h & appearance;
+		//definfo is handled by map serializer
+	}
+
+	///Entry point of Json (de-)serialization
+	void serializeJson(JsonSerializeFormat & handler);
+	virtual void updateFrom(const JsonNode & data);
+
+protected:
+	/// virtual method that allows synchronously update object state on server and all clients
+	virtual void setPropertyDer(ui8 what, ui32 val);
+
+	/// Gives dummy bonus from this object to hero. Can be used to track visited state
+	void giveDummyBonus(const ObjectInstanceID & heroID, BonusDuration::Type duration = BonusDuration::ONE_DAY) const;
+
+	///Serialize object-type specific options
+	virtual void serializeJsonOptions(JsonSerializeFormat & handler);
+
+	void serializeJsonOwner(JsonSerializeFormat & handler);
+};
+
+VCMI_LIB_NAMESPACE_END

+ 0 - 1
lib/mapObjects/CGPandoraBox.h

@@ -9,7 +9,6 @@
  */
 #pragma once
 
-#include "CObjectHandler.h"
 #include "CArmedInstance.h"
 #include "../ResourceSet.h"
 

+ 1 - 1
lib/mapObjects/CGTownBuilding.h

@@ -10,7 +10,7 @@
 
 #pragma once
 
-#include "CObjectHandler.h"
+#include "IObjectInterface.h"
 #include "../rewardable/Interface.h"
 
 VCMI_LIB_NAMESPACE_BEGIN

+ 2 - 1
lib/mapObjects/CGTownInstance.cpp

@@ -11,7 +11,6 @@
 #include "StdInc.h"
 #include "CGTownInstance.h"
 #include "CGTownBuilding.h"
-#include "CObjectClassesHandler.h"
 #include "../spells/CSpellHandler.h"
 #include "../bonuses/Bonus.h"
 #include "../battle/IBattleInfoCallback.h"
@@ -24,6 +23,8 @@
 #include "../mapping/CMap.h"
 #include "../CPlayerState.h"
 #include "../TerrainHandler.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../serializer/JsonSerializeFormat.h"
 
 VCMI_LIB_NAMESPACE_BEGIN

+ 1 - 3
lib/mapObjects/CGTownInstance.h

@@ -9,9 +9,7 @@
  */
 #pragma once
 
-#include "CObjectHandler.h"
-#include "CGMarket.h" // For IMarket interface
-#include "CArmedInstance.h"
+#include "IMarket.h"
 #include "CGDwelling.h"
 #include "CGTownBuilding.h"
 

+ 0 - 337
lib/mapObjects/CObjectClassesHandler.h

@@ -1,337 +0,0 @@
-/*
- * CObjectClassesHandler.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 "ObjectTemplate.h"
-
-#include "../GameConstants.h"
-#include "../ConstTransitivePtr.h"
-#include "../IHandlerBase.h"
-#include "../JsonNode.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-class JsonNode;
-class CRandomGenerator;
-
-
-struct SObjectSounds
-{
-	std::vector<std::string> ambient;
-	std::vector<std::string> visit;
-	std::vector<std::string> removal;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & ambient;
-		h & visit;
-		h & removal;
-	}
-};
-
-/// Structure that describes placement rules for this object in random map
-struct DLL_LINKAGE RandomMapInfo
-{
-	/// How valuable this object is, 1k = worthless, 10k = Utopia-level
-	ui32 value;
-
-	/// How many of such objects can be placed on map, 0 = object can not be placed by RMG
-	std::optional<ui32> mapLimit;
-
-	/// How many of such objects can be placed in one zone, 0 = unplaceable
-	ui32 zoneLimit;
-
-	/// Rarity of object, 5 = extremely rare, 100 = common
-	ui32 rarity;
-
-	RandomMapInfo():
-		value(0),
-		zoneLimit(0),
-		rarity(0)
-	{}
-
-	void setMapLimit(ui32 val) { mapLimit = val; }
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & value;
-		h & mapLimit;
-		h & zoneLimit;
-		h & rarity;
-	}
-};
-
-struct DLL_LINKAGE CompoundMapObjectID
-{
-	si32 primaryID;
-	si32 secondaryID;
-
-	CompoundMapObjectID(si32 primID, si32 secID) : primaryID(primID), secondaryID(secID) {};
-
-	bool operator<(const CompoundMapObjectID& other) const
-	{
-		if(this->primaryID != other.primaryID)
-			return this->primaryID < other.primaryID;
-		else
-			return this->secondaryID < other.secondaryID;
-	}
-
-	bool operator==(const CompoundMapObjectID& other) const
-	{
-		return (this->primaryID == other.primaryID) && (this->secondaryID == other.secondaryID);
-	}
-};
-
-class DLL_LINKAGE IObjectInfo
-{
-public:
-	struct CArmyStructure
-	{
-		ui32 totalStrength;
-		ui32 shootersStrength;
-		ui32 flyersStrength;
-		ui32 walkersStrength;
-
-		CArmyStructure() :
-			totalStrength(0),
-			shootersStrength(0),
-			flyersStrength(0),
-			walkersStrength(0)
-		{}
-
-		bool operator <(const CArmyStructure & other) const
-		{
-			return this->totalStrength < other.totalStrength;
-		}
-	};
-
-	/// Returns possible composition of guards. Actual guards would be
-	/// somewhere between these two values
-	virtual CArmyStructure minGuards() const { return CArmyStructure(); }
-	virtual CArmyStructure maxGuards() const { return CArmyStructure(); }
-
-	virtual bool givesResources() const { return false; }
-
-	virtual bool givesExperience() const { return false; }
-	virtual bool givesMana() const { return false; }
-	virtual bool givesMovement() const { return false; }
-
-	virtual bool givesPrimarySkills() const { return false; }
-	virtual bool givesSecondarySkills() const { return false; }
-
-	virtual bool givesArtifacts() const { return false; }
-	virtual bool givesCreatures() const { return false; }
-	virtual bool givesSpells() const { return false; }
-
-	virtual bool givesBonuses() const { return false; }
-
-	virtual ~IObjectInfo() = default;
-};
-
-class CGObjectInstance;
-
-/// Class responsible for creation of objects of specific type & subtype
-class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
-{
-	friend class CObjectClassesHandler;
-
-	RandomMapInfo rmgInfo;
-
-	JsonNode base; /// describes base template
-
-	std::vector<std::shared_ptr<const ObjectTemplate>> templates;
-
-	SObjectSounds sounds;
-
-	std::optional<si32> aiValue;
-	std::optional<std::string> battlefield;
-
-	std::string modScope;
-	std::string typeName;
-	std::string subTypeName;
-
-	si32 type;
-	si32 subtype;
-
-protected:
-	void preInitObject(CGObjectInstance * obj) const;
-	virtual bool objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const;
-
-	/// initialization for classes that inherit this one
-	virtual void initTypeData(const JsonNode & input);
-public:
-
-	virtual ~AObjectTypeHandler() = default;
-
-	si32 getIndex() const;
-	si32 getSubIndex() const;
-
-	std::string getTypeName() const;
-	std::string getSubTypeName() const;
-
-	/// loads generic data from Json structure and passes it towards type-specific constructors
-	void init(const JsonNode & input);
-
-	/// returns full form of identifier of this object in form of modName:objectName
-	std::string getJsonKey() const;
-
-	/// Returns object-specific name, if set
-	SObjectSounds getSounds() const;
-
-	void addTemplate(const std::shared_ptr<const ObjectTemplate> & templ);
-	void addTemplate(JsonNode config);
-
-	/// returns all templates matching parameters
-	std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates() const;
-	std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates(const TerrainId terrainType) const;
-
-	/// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle)
-	/// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server)
-	std::shared_ptr<const ObjectTemplate> getOverride(TerrainId terrainType, const CGObjectInstance * object) const;
-
-	BattleField getBattlefield() const;
-
-	const RandomMapInfo & getRMGInfo();
-
-	std::optional<si32> getAiValue() const;
-
-	/// returns true if this class provides custom text ID's instead of generic per-object name
-	virtual bool hasNameTextID() const;
-
-	/// returns object's name in form of translatable text ID
-	virtual std::string getNameTextID() const;
-
-	/// returns object's name in form of human-readable text
-	std::string getNameTranslated() const;
-
-	virtual bool isStaticObject();
-
-	virtual void afterLoadFinalization();
-
-	/// Creates object and set up core properties (like ID/subID). Object is NOT initialized
-	/// to allow creating objects before game start (e.g. map loading)
-	virtual CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const = 0;
-
-	/// Configures object properties. Should be re-entrable, resetting state of the object if necessarily
-	/// This should set remaining properties, including randomized or depending on map
-	virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const = 0;
-
-	/// Returns object configuration, if available. Otherwise returns NULL
-	virtual std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const = 0;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & type;
-		h & subtype;
-		h & templates;
-		h & rmgInfo;
-		h & modScope;
-		h & typeName;
-		h & subTypeName;
-		h & sounds;
-		h & aiValue;
-		h & battlefield;
-	}
-};
-
-using TObjectTypeHandler = std::shared_ptr<AObjectTypeHandler>;
-
-/// Class responsible for creation of adventure map objects of specific type
-class DLL_LINKAGE ObjectClass
-{
-public:
-	std::string modScope;
-	std::string identifier;
-
-	si32 id;
-	std::string handlerName; // ID of handler that controls this object, should be determined using handlerConstructor map
-
-	JsonNode base;
-	std::vector<TObjectTypeHandler> objects;
-
-	ObjectClass() = default;
-
-	std::string getJsonKey() const;
-	std::string getNameTextID() const;
-	std::string getNameTranslated() const;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & id;
-		h & handlerName;
-		h & base;
-		h & objects;
-		h & identifier;
-		h & modScope;
-	}
-};
-
-/// Main class responsible for creation of all adventure map objects
-class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
-{
-	/// list of object handlers, each of them handles only one type
-	std::vector<ObjectClass * > objects;
-
-	/// map that is filled during contruction with all known handlers. Not serializeable due to usage of std::function
-	std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;
-
-	/// container with H3 templates, used only during loading, no need to serialize it
-	using TTemplatesContainer = std::multimap<std::pair<si32, si32>, std::shared_ptr<const ObjectTemplate>>;
-	TTemplatesContainer legacyTemplates;
-
-	TObjectTypeHandler loadSubObjectFromJson(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index);
-
-	void loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj);
-	void loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index);
-
-	ObjectClass * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index);
-
-	void generateExtraMonolithsForRMG();
-
-public:
-	CObjectClassesHandler();
-	~CObjectClassesHandler();
-
-	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 loadSubObject(const std::string & identifier, JsonNode config, si32 ID, si32 subID);
-	void removeSubObject(si32 ID, si32 subID);
-
-	void beforeValidate(JsonNode & object) override;
-	void afterLoadFinalization() override;
-
-	std::vector<bool> getDefaultAllowed() const override;
-
-	/// Queries to detect loaded objects
-	std::set<si32> knownObjects() const;
-	std::set<si32> knownSubObjects(si32 primaryID) const;
-
-	/// returns handler for specified object (ID-based). ObjectHandler keeps ownership
-	TObjectTypeHandler getHandlerFor(si32 type, si32 subtype) const;
-	TObjectTypeHandler getHandlerFor(const std::string & scope, const std::string & type, const std::string & subtype) const;
-	TObjectTypeHandler getHandlerFor(CompoundMapObjectID compoundIdentifier) const;
-
-	std::string getObjectName(si32 type, si32 subtype) const;
-
-	SObjectSounds getObjectSounds(si32 type, si32 subtype) const;
-
-	/// Returns handler string describing the handler (for use in client)
-	std::string getObjectHandlerName(si32 type) const;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & objects;
-	}
-};
-
-VCMI_LIB_NAMESPACE_END

+ 1 - 496
lib/mapObjects/CObjectHandler.cpp

@@ -11,89 +11,11 @@
 #include "StdInc.h"
 #include "CObjectHandler.h"
 
-#include "../NetPacks.h"
-#include "../CGeneralTextHandler.h"
-#include "../CHeroHandler.h"
-#include "../CSoundBase.h"
+#include "CGObjectInstance.h"
 #include "../filesystem/ResourceID.h"
-#include "../IGameCallback.h"
-#include "../CGameState.h"
-#include "../StringConstants.h"
-#include "../mapping/CMap.h"
-#include "../TerrainHandler.h"
-
-#include "CObjectClassesHandler.h"
-#include "CGTownInstance.h"
-
-#include "../serializer/JsonSerializeFormat.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-IGameCallback * IObjectInterface::cb = nullptr;
-
-///helpers
-void IObjectInterface::openWindow(const EOpenWindowMode type, const int id1, const int id2)
-{
-	OpenWindow ow;
-	ow.window = type;
-	ow.id1 = id1;
-	ow.id2 = id2;
-	IObjectInterface::cb->sendAndApply(&ow);
-}
-
-void IObjectInterface::showInfoDialog(const ui32 txtID, const ui16 soundID, EInfoWindowMode mode) const
-{
-	InfoWindow iw;
-	iw.soundID = soundID;
-	iw.player = getOwner();
-	iw.type = mode;
-	iw.text.addTxt(MetaString::ADVOB_TXT,txtID);
-	IObjectInterface::cb->sendAndApply(&iw);
-}
-
-///IObjectInterface
-void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
-{}
-
-void IObjectInterface::onHeroLeave(const CGHeroInstance * h) const
-{}
-
-void IObjectInterface::newTurn(CRandomGenerator & rand) const
-{}
-
-void IObjectInterface::initObj(CRandomGenerator & rand)
-{}
-
-void IObjectInterface::setProperty( ui8 what, ui32 val )
-{}
-
-bool IObjectInterface::wasVisited (PlayerColor player) const
-{
-	return false;
-}
-bool IObjectInterface::wasVisited (const CGHeroInstance * h) const
-{
-	return false;
-}
-
-void IObjectInterface::postInit()
-{}
-
-void IObjectInterface::preInit()
-{}
-
-void IObjectInterface::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
-{}
-
-void IObjectInterface::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
-{}
-
-void IObjectInterface::garrisonDialogClosed(const CGHeroInstance *hero) const
-{}
-
-void IObjectInterface::heroLevelUpDone(const CGHeroInstance *hero) const
-{}
-
 CObjectHandler::CObjectHandler()
 {
 	logGlobal->trace("\t\tReading resources prices ");
@@ -105,324 +27,6 @@ CObjectHandler::CObjectHandler()
 	logGlobal->trace("\t\tDone loading resource prices!");
 }
 
-//TODO: remove constructor
-CGObjectInstance::CGObjectInstance():
-	pos(-1,-1,-1),
-	ID(Obj::NO_OBJ),
-	subID(-1),
-	tempOwner(PlayerColor::UNFLAGGABLE),
-	blockVisit(false)
-{
-}
-
-//must be instantiated in .cpp file for access to complete types of all member fields
-CGObjectInstance::~CGObjectInstance() = default;
-
-int32_t CGObjectInstance::getObjGroupIndex() const
-{
-	return ID.num;
-}
-
-int32_t CGObjectInstance::getObjTypeIndex() const
-{
-	return subID;
-}
-
-int3 CGObjectInstance::getPosition() const
-{
-	return pos;
-}
-
-int3 CGObjectInstance::getTopVisiblePos() const
-{
-	return pos - appearance->getTopVisibleOffset();
-}
-
-void CGObjectInstance::setOwner(const PlayerColor & ow)
-{
-	tempOwner = ow;
-}
-int CGObjectInstance::getWidth() const//returns width of object graphic in tiles
-{
-	return appearance->getWidth();
-}
-int CGObjectInstance::getHeight() const //returns height of object graphic in tiles
-{
-	return appearance->getHeight();
-}
-bool CGObjectInstance::visitableAt(int x, int y) const //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
-{
-	return appearance->isVisitableAt(pos.x - x, pos.y - y);
-}
-bool CGObjectInstance::blockingAt(int x, int y) const
-{
-	return appearance->isBlockedAt(pos.x - x, pos.y - y);
-}
-
-bool CGObjectInstance::coveringAt(int x, int y) const
-{
-	return appearance->isVisibleAt(pos.x - x, pos.y - y);
-}
-
-std::set<int3> CGObjectInstance::getBlockedPos() const
-{
-	std::set<int3> ret;
-	for(int w=0; w<getWidth(); ++w)
-	{
-		for(int h=0; h<getHeight(); ++h)
-		{
-			if(appearance->isBlockedAt(w, h))
-				ret.insert(int3(pos.x - w, pos.y - h, pos.z));
-		}
-	}
-	return ret;
-}
-
-std::set<int3> CGObjectInstance::getBlockedOffsets() const
-{
-	return appearance->getBlockedOffsets();
-}
-
-void CGObjectInstance::setType(si32 ID, si32 subID)
-{
-	auto position = visitablePos();
-	auto oldOffset = getVisitableOffset();
-	auto &tile = cb->gameState()->map->getTile(position);
-
-	//recalculate blockvis tiles - new appearance might have different blockmap than before
-	cb->gameState()->map->removeBlockVisTiles(this, true);
-	auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
-	if(!handler)
-	{
-		logGlobal->error("Unknown object type %d:%d at %s", ID, subID, visitablePos().toString());
-		return;
-	}
-	if(!handler->getTemplates(tile.terType->getId()).empty())
-	{
-		appearance = handler->getTemplates(tile.terType->getId())[0];
-	}
-	else
-	{
-		logGlobal->warn("Object %d:%d at %s has no templates suitable for terrain %s", ID, subID, visitablePos().toString(), tile.terType->getNameTranslated());
-		appearance = handler->getTemplates()[0]; // get at least some appearance since alternative is crash
-	}
-
-	if(this->ID == Obj::PRISON && ID == Obj::HERO)
-	{
-		auto newOffset = getVisitableOffset();
-		// FIXME: potentially unused code - setType is NOT called when releasing hero from prison
-		// instead, appearance update & pos adjustment occurs in GiveHero::applyGs
-
-		// adjust position since hero and prison may have different visitable offset
-		pos = pos - oldOffset + newOffset;
-	}
-
-	this->ID = Obj(ID);
-	this->subID = subID;
-
-	cb->gameState()->map->addBlockVisTiles(this);
-}
-
-void CGObjectInstance::initObj(CRandomGenerator & rand)
-{
-	switch(ID)
-	{
-	case Obj::TAVERN:
-		blockVisit = true;
-		break;
-	}
-}
-
-void CGObjectInstance::setProperty( ui8 what, ui32 val )
-{
-	setPropertyDer(what, val); // call this before any actual changes (needed at least for dwellings)
-
-	switch(what)
-	{
-	case ObjProperty::OWNER:
-		tempOwner = PlayerColor(val);
-		break;
-	case ObjProperty::BLOCKVIS:
-		blockVisit = val;
-		break;
-	case ObjProperty::ID:
-		ID = Obj(val);
-		break;
-	case ObjProperty::SUBID:
-		subID = val;
-		break;
-	}
-}
-
-void CGObjectInstance::setPropertyDer( ui8 what, ui32 val )
-{}
-
-int3 CGObjectInstance::getSightCenter() const
-{
-	return visitablePos();
-}
-
-int CGObjectInstance::getSightRadius() const
-{
-	return 3;
-}
-
-int3 CGObjectInstance::getVisitableOffset() const
-{
-	return appearance->getVisitableOffset();
-}
-
-void CGObjectInstance::giveDummyBonus(const ObjectInstanceID & heroID, BonusDuration::Type duration) const
-{
-	GiveBonus gbonus;
-	gbonus.bonus.type = BonusType::NONE;
-	gbonus.id = heroID.getNum();
-	gbonus.bonus.duration = duration;
-	gbonus.bonus.source = BonusSource::OBJECT;
-	gbonus.bonus.sid = ID;
-	cb->giveHeroBonus(&gbonus);
-}
-
-std::string CGObjectInstance::getObjectName() const
-{
-	return VLC->objtypeh->getObjectName(ID, subID);
-}
-
-std::optional<std::string> CGObjectInstance::getAmbientSound() const
-{
-	const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).ambient;
-	if(!sounds.empty())
-		return sounds.front(); // TODO: Support randomization of ambient sounds
-
-	return std::nullopt;
-}
-
-std::optional<std::string> CGObjectInstance::getVisitSound() const
-{
-	const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).visit;
-	if(!sounds.empty())
-		return *RandomGeneratorUtil::nextItem(sounds, CRandomGenerator::getDefault());
-
-	return std::nullopt;
-}
-
-std::optional<std::string> CGObjectInstance::getRemovalSound() const
-{
-	const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).removal;
-	if(!sounds.empty())
-		return *RandomGeneratorUtil::nextItem(sounds, CRandomGenerator::getDefault());
-
-	return std::nullopt;
-}
-
-std::string CGObjectInstance::getHoverText(PlayerColor player) const
-{
-	auto text = getObjectName();
-	if (tempOwner.isValidPlayer())
-		text += "\n" + VLC->generaltexth->arraytxt[23 + tempOwner.getNum()];
-	return text;
-}
-
-std::string CGObjectInstance::getHoverText(const CGHeroInstance * hero) const
-{
-	return getHoverText(hero->tempOwner);
-}
-
-void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
-{
-	switch(ID)
-	{
-	case Obj::HILL_FORT:
-		{
-			openWindow(EOpenWindowMode::HILL_FORT_WINDOW,id.getNum(),h->id.getNum());
-		}
-		break;
-	case Obj::SANCTUARY:
-		{
-			//You enter the sanctuary and immediately feel as if a great weight has been lifted off your shoulders.  You feel safe here.
-			h->showInfoDialog(114);
-		}
-		break;
-	case Obj::TAVERN:
-		{
-			openWindow(EOpenWindowMode::TAVERN_WINDOW,h->id.getNum(),id.getNum());
-		}
-		break;
-	}
-}
-
-int3 CGObjectInstance::visitablePos() const
-{
-	return pos - getVisitableOffset();
-}
-
-bool CGObjectInstance::isVisitable() const
-{
-	return appearance->isVisitable();
-}
-
-bool CGObjectInstance::passableFor(PlayerColor color) const
-{
-	return false;
-}
-
-void CGObjectInstance::updateFrom(const JsonNode & data)
-{
-
-}
-
-void CGObjectInstance::serializeJson(JsonSerializeFormat & handler)
-{
-	//only save here, loading is handled by map loader
-	if(handler.saving)
-	{
-		handler.serializeString("type", typeName);
-		handler.serializeString("subtype", subTypeName);
-
-		handler.serializeInt("x", pos.x);
-		handler.serializeInt("y", pos.y);
-		handler.serializeInt("l", pos.z);
-		JsonNode app;
-		appearance->writeJson(app, false);
-		handler.serializeRaw("template", app, std::nullopt);
-	}
-
-	{
-		auto options = handler.enterStruct("options");
-		serializeJsonOptions(handler);
-	}
-}
-
-void CGObjectInstance::afterAddToMap(CMap * map)
-{
-	//nothing here
-}
-
-void CGObjectInstance::afterRemoveFromMap(CMap * map)
-{
-	//nothing here
-}
-
-void CGObjectInstance::serializeJsonOptions(JsonSerializeFormat & handler)
-{
-	//nothing here
-}
-
-void CGObjectInstance::serializeJsonOwner(JsonSerializeFormat & handler)
-{
-	ui8 temp = tempOwner.getNum();
-
-	handler.serializeEnum("owner", temp, PlayerColor::NEUTRAL.getNum(), GameConstants::PLAYER_COLOR_NAMES);
-
-	if(!handler.saving)
-		tempOwner = PlayerColor(temp);
-}
-
-BattleField CGObjectInstance::getBattlefield() const
-{
-	return VLC->objtypeh->getHandlerFor(ID, subID)->getBattlefield();
-}
-
 CGObjectInstanceBySubIdFinder::CGObjectInstanceBySubIdFinder(CGObjectInstance * obj) : obj(obj)
 {
 
@@ -433,103 +37,4 @@ bool CGObjectInstanceBySubIdFinder::operator()(CGObjectInstance * obj) const
 	return this->obj->subID == obj->subID;
 }
 
-int3 IBoatGenerator::bestLocation() const
-{
-	std::vector<int3> offsets;
-	getOutOffsets(offsets);
-
-	for (auto & offset : offsets)
-	{
-		if(const TerrainTile *tile = IObjectInterface::cb->getTile(o->pos + offset, false)) //tile is in the map
-		{
-			if(tile->terType->isWater()  &&  (!tile->blocked || tile->blockingObjects.front()->ID == Obj::BOAT)) //and is water and is not blocked or is blocked by boat
-				return o->pos + offset;
-		}
-	}
-	return int3 (-1,-1,-1);
-}
-
-IBoatGenerator::EGeneratorState IBoatGenerator::shipyardStatus() const
-{
-	int3 tile = bestLocation();
-	const TerrainTile *t = IObjectInterface::cb->getTile(tile);
-	if(!t)
-		return TILE_BLOCKED; //no available water
-	else if(t->blockingObjects.empty())
-		return GOOD; //OK
-	else if(t->blockingObjects.front()->ID == Obj::BOAT)
-		return BOAT_ALREADY_BUILT; //blocked with boat
-	else
-		return TILE_BLOCKED; //blocked
-}
-
-BoatId IBoatGenerator::getBoatType() const
-{
-	//We make good ships by default
-	return EBoatId::BOAT_GOOD;
-}
-
-
-IBoatGenerator::IBoatGenerator(const CGObjectInstance *O)
-: o(O)
-{
-}
-
-void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visitor) const
-{
-	switch(shipyardStatus())
-	{
-	case BOAT_ALREADY_BUILT:
-		out.addTxt(MetaString::GENERAL_TXT, 51);
-		break;
-	case TILE_BLOCKED:
-		if(visitor)
-		{
-			out.addTxt(MetaString::GENERAL_TXT, 134);
-			out.addReplacement(visitor->getNameTranslated());
-		}
-		else
-			out.addTxt(MetaString::ADVOB_TXT, 189);
-		break;
-	case NO_WATER:
-		logGlobal->error("Shipyard without water! %s \t %d", o->pos.toString(), o->id.getNum());
-		return;
-	}
-}
-
-void IShipyard::getBoatCost(TResources & cost) const
-{
-	cost[EGameResID::WOOD] = 10;
-	cost[EGameResID::GOLD] = 1000;
-}
-
-IShipyard::IShipyard(const CGObjectInstance *O)
-	: IBoatGenerator(O)
-{
-}
-
-IShipyard * IShipyard::castFrom( CGObjectInstance *obj )
-{
-	if(!obj)
-		return nullptr;
-
-	if(obj->ID == Obj::TOWN)
-	{
-		return dynamic_cast<CGTownInstance *>(obj);
-	}
-	else if(obj->ID == Obj::SHIPYARD)
-	{
-		return dynamic_cast<CGShipyard *>(obj);
-	}
-	else
-	{
-		return nullptr;
-	}
-}
-
-const IShipyard * IShipyard::castFrom( const CGObjectInstance *obj )
-{
-	return castFrom(const_cast<CGObjectInstance*>(obj));
-}
-
 VCMI_LIB_NAMESPACE_END

+ 2 - 226
lib/mapObjects/CObjectHandler.h

@@ -9,236 +9,12 @@
  */
 #pragma once
 
-#include "ObjectTemplate.h"
-
-#include "../int3.h"
-#include "../NetPacksBase.h"
-#include "../ResourceSet.h"
-
-#include "../bonuses/Bonus.h"
+#include "../GameConstants.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class CGHeroInstance;
-class IGameCallback;
 class CGObjectInstance;
-struct MetaString;
-struct BattleResult;
-class JsonSerializeFormat;
-class CRandomGenerator;
-class CMap;
-class JsonNode;
-
-// This one teleport-specific, but has to be available everywhere in callbacks and netpacks
-// For now it's will be there till teleports code refactored and moved into own file
-using TTeleportExitsList = std::vector<std::pair<ObjectInstanceID, int3>>;
-
-class DLL_LINKAGE IObjectInterface
-{
-public:
-	static IGameCallback *cb;
-
-	virtual ~IObjectInterface() = default;
-
-	virtual int32_t getObjGroupIndex() const = 0;
-	virtual int32_t getObjTypeIndex() const = 0;
-
-	virtual PlayerColor getOwner() const = 0;
-	virtual int3 visitablePos() const = 0;
-	virtual int3 getPosition() const = 0;
-
-	virtual void onHeroVisit(const CGHeroInstance * h) const;
-	virtual void onHeroLeave(const CGHeroInstance * h) const;
-	virtual void newTurn(CRandomGenerator & rand) const;
-	virtual void initObj(CRandomGenerator & rand); //synchr
-	virtual void setProperty(ui8 what, ui32 val);//synchr
-
-	//Called when queries created DURING HERO VISIT are resolved
-	//First parameter is always hero that visited object and triggered the query
-	virtual void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const;
-	virtual void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const;
-	virtual void garrisonDialogClosed(const CGHeroInstance *hero) const;
-	virtual void heroLevelUpDone(const CGHeroInstance *hero) const;
-
-	//unified helper to show info dialog for object owner
-	virtual void showInfoDialog(const ui32 txtID, const ui16 soundID = 0, EInfoWindowMode mode = EInfoWindowMode::AUTO) const;
-
-	//unified helper to show a specific window
-	static void openWindow(const EOpenWindowMode type, const int id1, const int id2 = -1);
-
-	//unified interface, AI helpers
-	virtual bool wasVisited (PlayerColor player) const;
-	virtual bool wasVisited (const CGHeroInstance * h) const;
-
-	static void preInit(); //called before objs receive their initObj
-	static void postInit();//called after objs receive their initObj
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		logGlobal->error("IObjectInterface serialized, unexpected, should not happen!");
-	}
-};
-
-class DLL_LINKAGE IBoatGenerator
-{
-public:
-	const CGObjectInstance *o;
-
-	IBoatGenerator(const CGObjectInstance *O);
-	virtual ~IBoatGenerator() = default;
-
-	virtual BoatId getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
-	virtual void getOutOffsets(std::vector<int3> &offsets) const =0; //offsets to obj pos when we boat can be placed
-	int3 bestLocation() const; //returns location when the boat should be placed
-
-	enum EGeneratorState {GOOD, BOAT_ALREADY_BUILT, TILE_BLOCKED, NO_WATER};
-	EGeneratorState shipyardStatus() const; //0 - can buid, 1 - there is already a boat at dest tile, 2 - dest tile is blocked, 3 - no water
-	void getProblemText(MetaString &out, const CGHeroInstance *visitor = nullptr) const;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & o;
-	}
-};
-
-class DLL_LINKAGE IShipyard : public IBoatGenerator
-{
-public:
-	IShipyard(const CGObjectInstance *O);
-
-	virtual void getBoatCost(TResources & cost) const;
-
-	static const IShipyard *castFrom(const CGObjectInstance *obj);
-	static IShipyard *castFrom(CGObjectInstance *obj);
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & static_cast<IBoatGenerator&>(*this);
-	}
-};
-
-class DLL_LINKAGE CGObjectInstance : public IObjectInterface
-{
-public:
-	/// Position of bottom-right corner of object on map
-	int3 pos;
-	/// Type of object, e.g. town, hero, creature.
-	Obj ID;
-	/// Subtype of object, depends on type
-	si32 subID;
-	/// Current owner of an object (when below PLAYER_LIMIT)
-	PlayerColor tempOwner;
-	/// Index of object in map's list of objects
-	ObjectInstanceID id;
-	/// Defines appearance of object on map (animation, blocked tiles, blit order, etc)
-	std::shared_ptr<const ObjectTemplate> appearance;
-	/// If true hero can visit this object only from neighbouring tiles and can't stand on this object
-	bool blockVisit;
-
-	std::string instanceName;
-	std::string typeName;
-	std::string subTypeName;
-
-	CGObjectInstance(); //TODO: remove constructor
-	~CGObjectInstance() override;
-
-	int32_t getObjGroupIndex() const override;
-	int32_t getObjTypeIndex() const override;
-
-	/// "center" tile from which the sight distance is calculated
-	int3 getSightCenter() const;
-
-	PlayerColor getOwner() const override 
-	{
-		return this->tempOwner;
-	}
-	void setOwner(const PlayerColor & ow);
-
-	/** APPEARANCE ACCESSORS **/
-
-	int getWidth() const; //returns width of object graphic in tiles
-	int getHeight() const; //returns height of object graphic in tiles
-	bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) (h3m pos)
-	int3 visitablePos() const override;
-	int3 getPosition() const override;
-	int3 getTopVisiblePos() const;
-	bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) (h3m pos)
-	bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) (h3m pos)
-	std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object
-	std::set<int3> getBlockedOffsets() const; //returns set of relative positions blocked by this object
-	bool isVisitable() const; //returns true if object is visitable
-
-	virtual BattleField getBattlefield() const;
-
-	virtual bool isTile2Terrain() const { return false; }
-
-	std::optional<std::string> getAmbientSound() const;
-	std::optional<std::string> getVisitSound() const;
-	std::optional<std::string> getRemovalSound() const;
-
-	/** VIRTUAL METHODS **/
-
-	/// Returns true if player can pass through visitable tiles of this object
-	virtual bool passableFor(PlayerColor color) const;
-	/// Range of revealed map around this object, counting from getSightCenter()
-	virtual int getSightRadius() const;
-	/// returns (x,y,0) offset to a visitable tile of object
-	virtual int3 getVisitableOffset() const;
-	/// Called mostly during map randomization to turn random object into a regular one (e.g. "Random Monster" into "Pikeman")
-	virtual void setType(si32 ID, si32 subID);
-
-	/// returns text visible in status bar with specific hero/player active.
-
-	/// Returns generic name of object, without any player-specific info
-	virtual std::string getObjectName() const;
-
-	/// Returns hover name for situation when there are no selected heroes. Default = object name
-	virtual std::string getHoverText(PlayerColor player) const;
-	/// Returns hero-specific hover name, including visited/not visited info. Default = player-specific name
-	virtual std::string getHoverText(const CGHeroInstance * hero) const;
-
-	/** OVERRIDES OF IObjectInterface **/
-
-	void initObj(CRandomGenerator & rand) override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	/// method for synchronous update. Note: For new properties classes should override setPropertyDer instead
-	void setProperty(ui8 what, ui32 val) final;
-
-	virtual void afterAddToMap(CMap * map);
-	virtual void afterRemoveFromMap(CMap * map);
-
-	///Entry point of binary (de-)serialization
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & instanceName;
-		h & typeName;
-		h & subTypeName;
-		h & pos;
-		h & ID;
-		h & subID;
-		h & id;
-		h & tempOwner;
-		h & blockVisit;
-		h & appearance;
-		//definfo is handled by map serializer
-	}
-
-	///Entry point of Json (de-)serialization
-	void serializeJson(JsonSerializeFormat & handler);
-	virtual void updateFrom(const JsonNode & data);
-
-protected:
-	/// virtual method that allows synchronously update object state on server and all clients
-	virtual void setPropertyDer(ui8 what, ui32 val);
-
-	/// Gives dummy bonus from this object to hero. Can be used to track visited state
-	void giveDummyBonus(const ObjectInstanceID & heroID, BonusDuration::Type duration = BonusDuration::ONE_DAY) const;
-
-	///Serialize object-type specific options
-	virtual void serializeJsonOptions(JsonSerializeFormat & handler);
-
-	void serializeJsonOwner(JsonSerializeFormat & handler);
-};
+class int3;
 
 /// function object which can be used to find an object with an specific sub ID
 class CGObjectInstanceBySubIdFinder

+ 1 - 1
lib/mapObjects/CQuest.cpp

@@ -17,10 +17,10 @@
 #include "../CSoundBase.h"
 #include "../CGeneralTextHandler.h"
 #include "../CHeroHandler.h"
-#include "CObjectClassesHandler.h"
 #include "MiscObjects.h"
 #include "../IGameCallback.h"
 #include "../CGameState.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../serializer/JsonSerializeFormat.h"
 #include "../CModHandler.h"
 #include "../GameConstants.h"

+ 0 - 5
lib/mapObjects/CQuest.h

@@ -9,18 +9,13 @@
  */
 #pragma once
 
-#include "CObjectHandler.h"
 #include "CArmedInstance.h"
-
 #include "../ResourceSet.h"
-#include "../CCreatureSet.h"
-#include "../NetPacksBase.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
 class CGCreature;
 
-
 class DLL_LINKAGE CQuest final
 {
 	mutable std::unordered_map<ArtifactID, unsigned, ArtifactID::hash> artifactsRequirements; // artifact ID -> required count

+ 2 - 1
lib/mapObjects/CRewardableObject.cpp

@@ -10,12 +10,13 @@
 
 #include "StdInc.h"
 #include "CRewardableObject.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 #include "../CGameState.h"
 #include "../CGeneralTextHandler.h"
 #include "../CPlayerState.h"
 #include "../IGameCallback.h"
 #include "../NetPacks.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 179 - 0
lib/mapObjects/IMarket.cpp

@@ -0,0 +1,179 @@
+/*
+ * IMarket.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 "IMarket.h"
+
+#include "CArtHandler.h"
+#include "CCreatureHandler.h"
+#include "CGObjectInstance.h"
+#include "CObjectHandler.h"
+
+#include "../VCMI_Lib.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMarketMode mode) const
+{
+	switch(mode)
+	{
+	case EMarketMode::RESOURCE_RESOURCE:
+		{
+			double effectiveness = std::min((getMarketEfficiency() + 1.0) / 20.0, 0.5);
+
+			double r = VLC->objh->resVals[id1]; //value of given resource
+			double g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
+
+			if(r>g) //if given resource is more expensive than wanted
+			{
+				val2 = static_cast<int>(ceil(r / g));
+				val1 = 1;
+			}
+			else //if wanted resource is more expensive
+			{
+				val1 = static_cast<int>((g / r) + 0.5);
+				val2 = 1;
+			}
+		}
+		break;
+	case EMarketMode::CREATURE_RESOURCE:
+		{
+			const double effectivenessArray[] = {0.0, 0.3, 0.45, 0.50, 0.65, 0.7, 0.85, 0.9, 1.0};
+			double effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)];
+
+			double r = VLC->creatures()->getByIndex(id1)->getRecruitCost(EGameResID::GOLD); //value of given creature in gold
+			double g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
+
+			if(r>g) //if given resource is more expensive than wanted
+			{
+				val2 = static_cast<int>(ceil(r / g));
+				val1 = 1;
+			}
+			else //if wanted resource is more expensive
+			{
+				val1 = static_cast<int>((g / r) + 0.5);
+				val2 = 1;
+			}
+		}
+		break;
+	case EMarketMode::RESOURCE_PLAYER:
+		val1 = 1;
+		val2 = 1;
+		break;
+	case EMarketMode::RESOURCE_ARTIFACT:
+		{
+			double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
+			double r = VLC->objh->resVals[id1]; //value of offered resource
+			double g = VLC->artifacts()->getByIndex(id2)->getPrice() / effectiveness; //value of bought artifact in gold
+
+			if(id1 != 6) //non-gold prices are doubled
+				r /= 2;
+
+			val1 = std::max(1, static_cast<int>((g / r) + 0.5)); //don't sell arts for less than 1 resource
+			val2 = 1;
+		}
+		break;
+	case EMarketMode::ARTIFACT_RESOURCE:
+		{
+			double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
+			double r = VLC->artifacts()->getByIndex(id1)->getPrice() * effectiveness;
+			double g = VLC->objh->resVals[id2];
+
+// 			if(id2 != 6) //non-gold prices are doubled
+// 				r /= 2;
+
+			val1 = 1;
+			val2 = std::max(1, static_cast<int>((r / g) + 0.5)); //at least one resource is given in return
+		}
+		break;
+	case EMarketMode::CREATURE_EXP:
+		{
+			val1 = 1;
+			val2 = (VLC->creh->objects[id1]->getAIValue() / 40) * 5;
+		}
+		break;
+	case EMarketMode::ARTIFACT_EXP:
+		{
+			val1 = 1;
+
+			int givenClass = VLC->arth->objects[id1]->getArtClassSerial();
+			if(givenClass < 0 || givenClass > 3)
+			{
+				val2 = 0;
+				return false;
+			}
+
+			static constexpr int expPerClass[] = {1000, 1500, 3000, 6000};
+			val2 = expPerClass[givenClass];
+		}
+		break;
+	default:
+		assert(0);
+		return false;
+	}
+
+	return true;
+}
+
+bool IMarket::allowsTrade(EMarketMode::EMarketMode mode) const
+{
+	return false;
+}
+
+int IMarket::availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const
+{
+	switch(mode)
+	{
+	case EMarketMode::RESOURCE_RESOURCE:
+	case EMarketMode::ARTIFACT_RESOURCE:
+	case EMarketMode::CREATURE_RESOURCE:
+			return -1;
+	default:
+			return 1;
+	}
+}
+
+std::vector<int> IMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
+{
+	std::vector<int> ret;
+	switch(mode)
+	{
+	case EMarketMode::RESOURCE_RESOURCE:
+	case EMarketMode::ARTIFACT_RESOURCE:
+	case EMarketMode::CREATURE_RESOURCE:
+		for (int i = 0; i < 7; i++)
+			ret.push_back(i);
+	}
+	return ret;
+}
+
+const IMarket * IMarket::castFrom(const CGObjectInstance *obj, bool verbose)
+{
+	auto * imarket = dynamic_cast<const IMarket *>(obj);
+	if(verbose && !imarket)
+		logGlobal->error("Cannot cast to IMarket object type %s", obj->typeName);
+	return imarket;
+}
+
+IMarket::IMarket()
+{
+}
+
+std::vector<EMarketMode::EMarketMode> IMarket::availableModes() const
+{
+	std::vector<EMarketMode::EMarketMode> ret;
+	for (int i = 0; i < EMarketMode::MARTKET_AFTER_LAST_PLACEHOLDER; i++)
+	if(allowsTrade(static_cast<EMarketMode::EMarketMode>(i)))
+		ret.push_back(static_cast<EMarketMode::EMarketMode>(i));
+
+	return ret;
+}
+
+VCMI_LIB_NAMESPACE_END

+ 35 - 0
lib/mapObjects/IMarket.h

@@ -0,0 +1,35 @@
+/*
+ * IMarket.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 "../GameConstants.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class CGObjectInstance;
+
+class DLL_LINKAGE IMarket
+{
+public:
+	IMarket();
+	virtual ~IMarket() {}
+
+	virtual int getMarketEfficiency() const = 0;
+	virtual bool allowsTrade(EMarketMode::EMarketMode mode) const;
+	virtual int availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const; //-1 if unlimited
+	virtual std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const;
+
+	bool getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMarketMode mode) const; //val1 - how many units of id1 player has to give to receive val2 units
+	std::vector<EMarketMode::EMarketMode> availableModes() const;
+
+	static const IMarket *castFrom(const CGObjectInstance *obj, bool verbose = true);
+};
+
+VCMI_LIB_NAMESPACE_END

+ 188 - 0
lib/mapObjects/IObjectInterface.cpp

@@ -0,0 +1,188 @@
+/*
+ * IObjectInterface.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 "IObjectInterface.h"
+
+#include "CGTownInstance.h"
+#include "MiscObjects.h"
+
+#include "../NetPacks.h"
+#include "../IGameCallback.h"
+#include "../TerrainHandler.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+IGameCallback * IObjectInterface::cb = nullptr;
+
+///helpers
+void IObjectInterface::openWindow(const EOpenWindowMode type, const int id1, const int id2)
+{
+	OpenWindow ow;
+	ow.window = type;
+	ow.id1 = id1;
+	ow.id2 = id2;
+	IObjectInterface::cb->sendAndApply(&ow);
+}
+
+void IObjectInterface::showInfoDialog(const ui32 txtID, const ui16 soundID, EInfoWindowMode mode) const
+{
+	InfoWindow iw;
+	iw.soundID = soundID;
+	iw.player = getOwner();
+	iw.type = mode;
+	iw.text.addTxt(MetaString::ADVOB_TXT,txtID);
+	IObjectInterface::cb->sendAndApply(&iw);
+}
+
+///IObjectInterface
+void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
+{}
+
+void IObjectInterface::onHeroLeave(const CGHeroInstance * h) const
+{}
+
+void IObjectInterface::newTurn(CRandomGenerator & rand) const
+{}
+
+void IObjectInterface::initObj(CRandomGenerator & rand)
+{}
+
+void IObjectInterface::setProperty( ui8 what, ui32 val )
+{}
+
+bool IObjectInterface::wasVisited (PlayerColor player) const
+{
+	return false;
+}
+bool IObjectInterface::wasVisited (const CGHeroInstance * h) const
+{
+	return false;
+}
+
+void IObjectInterface::postInit()
+{}
+
+void IObjectInterface::preInit()
+{}
+
+void IObjectInterface::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+{}
+
+void IObjectInterface::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
+{}
+
+void IObjectInterface::garrisonDialogClosed(const CGHeroInstance *hero) const
+{}
+
+void IObjectInterface::heroLevelUpDone(const CGHeroInstance *hero) const
+{}
+
+int3 IBoatGenerator::bestLocation() const
+{
+	std::vector<int3> offsets;
+	getOutOffsets(offsets);
+
+	for (auto & offset : offsets)
+	{
+		if(const TerrainTile *tile = IObjectInterface::cb->getTile(o->pos + offset, false)) //tile is in the map
+		{
+			if(tile->terType->isWater()  &&  (!tile->blocked || tile->blockingObjects.front()->ID == Obj::BOAT)) //and is water and is not blocked or is blocked by boat
+				return o->pos + offset;
+		}
+	}
+	return int3 (-1,-1,-1);
+}
+
+IBoatGenerator::EGeneratorState IBoatGenerator::shipyardStatus() const
+{
+	int3 tile = bestLocation();
+	const TerrainTile *t = IObjectInterface::cb->getTile(tile);
+	if(!t)
+		return TILE_BLOCKED; //no available water
+	else if(t->blockingObjects.empty())
+		return GOOD; //OK
+	else if(t->blockingObjects.front()->ID == Obj::BOAT)
+		return BOAT_ALREADY_BUILT; //blocked with boat
+	else
+		return TILE_BLOCKED; //blocked
+}
+
+BoatId IBoatGenerator::getBoatType() const
+{
+	//We make good ships by default
+	return EBoatId::BOAT_GOOD;
+}
+
+
+IBoatGenerator::IBoatGenerator(const CGObjectInstance *O)
+: o(O)
+{
+}
+
+void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visitor) const
+{
+	switch(shipyardStatus())
+	{
+	case BOAT_ALREADY_BUILT:
+		out.addTxt(MetaString::GENERAL_TXT, 51);
+		break;
+	case TILE_BLOCKED:
+		if(visitor)
+		{
+			out.addTxt(MetaString::GENERAL_TXT, 134);
+			out.addReplacement(visitor->getNameTranslated());
+		}
+		else
+			out.addTxt(MetaString::ADVOB_TXT, 189);
+		break;
+	case NO_WATER:
+		logGlobal->error("Shipyard without water! %s \t %d", o->pos.toString(), o->id.getNum());
+		return;
+	}
+}
+
+void IShipyard::getBoatCost(TResources & cost) const
+{
+	cost[EGameResID::WOOD] = 10;
+	cost[EGameResID::GOLD] = 1000;
+}
+
+IShipyard::IShipyard(const CGObjectInstance *O)
+	: IBoatGenerator(O)
+{
+}
+
+IShipyard * IShipyard::castFrom( CGObjectInstance *obj )
+{
+	if(!obj)
+		return nullptr;
+
+	if(obj->ID == Obj::TOWN)
+	{
+		return dynamic_cast<CGTownInstance *>(obj);
+	}
+	else if(obj->ID == Obj::SHIPYARD)
+	{
+		return dynamic_cast<CGShipyard *>(obj);
+	}
+	else
+	{
+		return nullptr;
+	}
+}
+
+const IShipyard * IShipyard::castFrom( const CGObjectInstance *obj )
+{
+	return castFrom(const_cast<CGObjectInstance*>(obj));
+}
+
+
+VCMI_LIB_NAMESPACE_END

+ 107 - 0
lib/mapObjects/IObjectInterface.h

@@ -0,0 +1,107 @@
+/*
+ * IObjectInterface.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 "../NetPacksBase.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+struct BattleResult;
+class CGObjectInstance;
+class CRandomGenerator;
+class IGameCallback;
+class ResourceSet;
+class int3;
+
+class DLL_LINKAGE IObjectInterface
+{
+public:
+	static IGameCallback *cb;
+
+	virtual ~IObjectInterface() = default;
+
+	virtual int32_t getObjGroupIndex() const = 0;
+	virtual int32_t getObjTypeIndex() const = 0;
+
+	virtual PlayerColor getOwner() const = 0;
+	virtual int3 visitablePos() const = 0;
+	virtual int3 getPosition() const = 0;
+
+	virtual void onHeroVisit(const CGHeroInstance * h) const;
+	virtual void onHeroLeave(const CGHeroInstance * h) const;
+	virtual void newTurn(CRandomGenerator & rand) const;
+	virtual void initObj(CRandomGenerator & rand); //synchr
+	virtual void setProperty(ui8 what, ui32 val);//synchr
+
+	//Called when queries created DURING HERO VISIT are resolved
+	//First parameter is always hero that visited object and triggered the query
+	virtual void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const;
+	virtual void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const;
+	virtual void garrisonDialogClosed(const CGHeroInstance *hero) const;
+	virtual void heroLevelUpDone(const CGHeroInstance *hero) const;
+
+	//unified helper to show info dialog for object owner
+	virtual void showInfoDialog(const ui32 txtID, const ui16 soundID = 0, EInfoWindowMode mode = EInfoWindowMode::AUTO) const;
+
+	//unified helper to show a specific window
+	static void openWindow(const EOpenWindowMode type, const int id1, const int id2 = -1);
+
+	//unified interface, AI helpers
+	virtual bool wasVisited (PlayerColor player) const;
+	virtual bool wasVisited (const CGHeroInstance * h) const;
+
+	static void preInit(); //called before objs receive their initObj
+	static void postInit();//called after objs receive their initObj
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		logGlobal->error("IObjectInterface serialized, unexpected, should not happen!");
+	}
+};
+
+class DLL_LINKAGE IBoatGenerator
+{
+public:
+	const CGObjectInstance *o;
+
+	IBoatGenerator(const CGObjectInstance *O);
+	virtual ~IBoatGenerator() = default;
+
+	virtual BoatId getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
+	virtual void getOutOffsets(std::vector<int3> &offsets) const =0; //offsets to obj pos when we boat can be placed
+	int3 bestLocation() const; //returns location when the boat should be placed
+
+	enum EGeneratorState {GOOD, BOAT_ALREADY_BUILT, TILE_BLOCKED, NO_WATER};
+	EGeneratorState shipyardStatus() const; //0 - can buid, 1 - there is already a boat at dest tile, 2 - dest tile is blocked, 3 - no water
+	void getProblemText(MetaString &out, const CGHeroInstance *visitor = nullptr) const;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & o;
+	}
+};
+
+class DLL_LINKAGE IShipyard : public IBoatGenerator
+{
+public:
+	IShipyard(const CGObjectInstance *O);
+
+	virtual void getBoatCost(ResourceSet & cost) const;
+
+	static const IShipyard *castFrom(const CGObjectInstance *obj);
+	static IShipyard *castFrom(CGObjectInstance *obj);
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<IBoatGenerator&>(*this);
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 0 - 1
lib/mapObjects/MiscObjects.cpp

@@ -19,7 +19,6 @@
 #include "../CModHandler.h"
 #include "../CHeroHandler.h"
 #include "../CSkillHandler.h"
-#include "CObjectClassesHandler.h"
 #include "../spells/CSpellHandler.h"
 #include "../IGameCallback.h"
 #include "../CGameState.h"

+ 4 - 1
lib/mapObjects/MiscObjects.h

@@ -9,7 +9,6 @@
  */
 #pragma once
 
-#include "CObjectHandler.h"
 #include "CArmedInstance.h"
 #include "../ResourceSet.h"
 
@@ -17,6 +16,10 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 class CMap;
 
+// This one teleport-specific, but has to be available everywhere in callbacks and netpacks
+// For now it's will be there till teleports code refactored and moved into own file
+using TTeleportExitsList = std::vector<std::pair<ObjectInstanceID, int3>>;
+
 /// Legacy class, use CRewardableObject instead
 class DLL_LINKAGE CTeamVisited: public CGObjectInstance
 {

+ 2 - 3
lib/mapObjects/ObjectTemplate.cpp

@@ -8,7 +8,7 @@
  *
  */
 #include "StdInc.h"
-#include "CObjectClassesHandler.h"
+#include "ObjectTemplate.h"
 
 #include "../filesystem/Filesystem.h"
 #include "../filesystem/CBinaryReader.h"
@@ -16,12 +16,11 @@
 #include "../GameConstants.h"
 #include "../StringConstants.h"
 #include "../CGeneralTextHandler.h"
-#include "CObjectHandler.h"
 #include "../CModHandler.h"
 #include "../JsonNode.h"
 #include "../TerrainHandler.h"
 
-#include "CRewardableConstructor.h"
+#include "../mapObjectConstructors/CRewardableConstructor.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 1 - 1
lib/mapping/CMap.cpp

@@ -18,8 +18,8 @@
 #include "../RiverHandler.h"
 #include "../RoadHandler.h"
 #include "../TerrainHandler.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 #include "../mapObjects/CGHeroInstance.h"
+#include "../mapObjects/ObjectTemplate.h"
 #include "../CGeneralTextHandler.h"
 #include "../spells/CSpellHandler.h"
 #include "../CSkillHandler.h"

+ 0 - 2
lib/mapping/CMapEditManager.cpp

@@ -10,8 +10,6 @@
 #include "StdInc.h"
 #include "CMapEditManager.h"
 
-
-#include "../mapObjects/CObjectClassesHandler.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../VCMI_Lib.h"
 #include "CDrawRoadsOperation.h"

+ 3 - 1
lib/mapping/MapFormatH3M.cpp

@@ -29,8 +29,10 @@
 #include "../VCMI_Lib.h"
 #include "../filesystem/CBinaryReader.h"
 #include "../filesystem/Filesystem.h"
-#include "../mapObjects/CObjectClassesHandler.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../mapObjects/MapObjects.h"
+#include "../mapObjects/ObjectTemplate.h"
 #include "../spells/CSpellHandler.h"
 
 #include <boost/crc.hpp>

+ 2 - 2
lib/mapping/MapFormatJson.cpp

@@ -23,9 +23,9 @@
 #include "../RiverHandler.h"
 #include "../RoadHandler.h"
 #include "../TerrainHandler.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../mapObjects/ObjectTemplate.h"
-#include "../mapObjects/CObjectHandler.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../mapObjects/CGTownInstance.h"
 #include "../spells/CSpellHandler.h"

+ 3 - 1
lib/mapping/MapIdentifiersH3M.cpp

@@ -15,8 +15,10 @@
 #include "../VCMI_Lib.h"
 #include "../CModHandler.h"
 #include "../CTownHandler.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 #include "../filesystem/Filesystem.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
+#include "../mapObjects/ObjectTemplate.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 4 - 3
lib/mapping/ObstacleProxy.cpp

@@ -10,9 +10,10 @@
 
 #include "StdInc.h"
 #include "ObstacleProxy.h"
-#include "../mapObjects/CObjectClassesHandler.h"
-#include "../mapObjects/CObjectHandler.h"
 #include "../mapping/CMap.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
+#include "../mapObjects/ObjectTemplate.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -213,4 +214,4 @@ void EditorObstaclePlacer::placeObstacles(CRandomGenerator & rand)
 	finalInsertion(map->getEditManager(), obstacles);
 }
 
-VCMI_LIB_NAMESPACE_END
+VCMI_LIB_NAMESPACE_END

+ 4 - 3
lib/registerTypes/RegisterTypes.h

@@ -13,15 +13,16 @@
 #include "../NetPacksLobby.h"
 #include "../VCMI_Lib.h"
 #include "../CArtHandler.h"
+#include "../CCreatureSet.h"
 #include "../CPlayerState.h"
 #include "../CHeroHandler.h"
 #include "../CTownHandler.h"
 #include "../CModHandler.h" //needed?
-#include "../mapObjects/CObjectClassesHandler.h"
-#include "../mapObjects/CRewardableConstructor.h"
-#include "../mapObjects/CommonConstructors.h"
+#include "../mapObjectConstructors/CRewardableConstructor.h"
+#include "../mapObjectConstructors/CommonConstructors.h"
 #include "../mapObjects/MapObjects.h"
 #include "../mapObjects/CGTownBuilding.h"
+#include "../mapObjects/ObjectTemplate.h"
 #include "../battle/CObstacleInstance.h"
 #include "../bonuses/CBonusSystemNode.h"
 #include "../bonuses/Limiters.h"

+ 0 - 1
lib/registerTypes/TypesClientPacks1.cpp

@@ -22,7 +22,6 @@
 #include "../CTownHandler.h"
 #include "../mapping/CCampaignHandler.h"
 #include "../NetPacks.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 
 #include "../serializer/BinaryDeserializer.h"
 #include "../serializer/BinarySerializer.h"

+ 0 - 1
lib/registerTypes/TypesClientPacks2.cpp

@@ -24,7 +24,6 @@
 #include "../CTownHandler.h"
 #include "../mapping/CCampaignHandler.h"
 #include "../NetPacks.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 
 #include "../serializer/BinaryDeserializer.h"
 #include "../serializer/BinarySerializer.h"

+ 0 - 1
lib/registerTypes/TypesLobbyPacks.cpp

@@ -27,7 +27,6 @@
 #include "../TerrainHandler.h"
 #include "../mapping/CCampaignHandler.h"
 #include "../NetPacks.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 #include "../rmg/CMapGenOptions.h"
 
 #include "../serializer/BinaryDeserializer.h"

+ 0 - 1
lib/registerTypes/TypesMapObjects1.cpp

@@ -22,7 +22,6 @@
 #include "../CTownHandler.h"
 #include "../mapping/CCampaignHandler.h"
 #include "../NetPacks.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 
 #include "../serializer/BinaryDeserializer.h"
 #include "../serializer/BinarySerializer.h"

+ 0 - 1
lib/registerTypes/TypesMapObjects2.cpp

@@ -24,7 +24,6 @@
 #include "../CTownHandler.h"
 #include "../mapping/CCampaignHandler.h"
 #include "../NetPacks.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 
 #include "../serializer/BinaryDeserializer.h"
 #include "../serializer/BinarySerializer.h"

+ 0 - 1
lib/registerTypes/TypesMapObjects3.cpp

@@ -22,7 +22,6 @@
 #include "../CTownHandler.h"
 #include "../mapping/CCampaignHandler.h"
 #include "../NetPacks.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 
 #include "../serializer/BinaryDeserializer.h"
 #include "../serializer/BinarySerializer.h"

+ 0 - 1
lib/registerTypes/TypesServerPacks.cpp

@@ -22,7 +22,6 @@
 #include "../CTownHandler.h"
 #include "../mapping/CCampaignHandler.h"
 #include "../NetPacks.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 
 #include "../serializer/BinaryDeserializer.h"
 #include "../serializer/BinarySerializer.h"

+ 1 - 0
lib/rewardable/Configuration.h

@@ -12,6 +12,7 @@
 
 #include "Limiter.h"
 #include "Reward.h"
+#include "NetPacksBase.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 3 - 0
lib/rewardable/Info.cpp

@@ -14,15 +14,18 @@
 #include "Reward.h"
 #include "Configuration.h"
 
+#include "../CCreatureSet.h"
 #include "../CRandomGenerator.h"
 #include "../StringConstants.h"
 #include "../CCreatureHandler.h"
 #include "../CModHandler.h"
+#include "../NetPacksBase.h"
 #include "../JsonRandom.h"
 #include "../IGameCallback.h"
 #include "../CGeneralTextHandler.h"
 #include "../JsonNode.h"
 #include "../IGameCallback.h"
+#include "../mapObjects/IObjectInterface.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 1 - 1
lib/rewardable/Info.h

@@ -11,7 +11,7 @@
 #pragma once
 
 #include "../JsonNode.h"
-#include "../mapObjects/CObjectClassesHandler.h"
+#include "../mapObjectConstructors/IObjectInfo.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 2 - 1
lib/rewardable/Interface.h

@@ -10,7 +10,6 @@
 
 #pragma once
 
-#include "../mapObjects/CObjectHandler.h"
 #include "../CCreatureSet.h"
 #include "../ResourceSet.h"
 #include "../spells/ExternalCaster.h"
@@ -18,6 +17,8 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+class IGameCallback;
+
 namespace Rewardable
 {
 

+ 15 - 0
lib/rewardable/Limiter.cpp

@@ -10,12 +10,27 @@
 
 #include "StdInc.h"
 #include "Limiter.h"
+
 #include "../IGameCallback.h"
 #include "../CGameStateFwd.h"
 #include "../CPlayerState.h"
+#include "../mapObjects/CGHeroInstance.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+Rewardable::Limiter::Limiter()
+	: dayOfWeek(0)
+	, daysPassed(0)
+	, heroExperience(0)
+	, heroLevel(0)
+	, manaPercentage(0)
+	, manaPoints(0)
+	, primary(GameConstants::PRIMARY_SKILLS, 0)
+{
+}
+
+Rewardable::Limiter::~Limiter() = default;
+
 bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
 {
 	if(dayOfWeek != 0)

+ 7 - 10
lib/rewardable/Limiter.h

@@ -10,10 +10,14 @@
 
 #pragma once
 
-#include "../mapObjects/CGHeroInstance.h"
+#include "../GameConstants.h"
+#include "../ResourceSet.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+class CGHeroInstance;
+class CStackBasicDescriptor;
+
 namespace Rewardable {
 
 struct Limiter;
@@ -66,15 +70,8 @@ struct DLL_LINKAGE Limiter
 	/// sub-limiters, none should pass for this limiter to pass
 	LimitersList noneOf;
 
-	Limiter():
-		dayOfWeek(0),
-		daysPassed(0),
-		heroExperience(0),
-		heroLevel(0),
-		manaPercentage(0),
-		manaPoints(0),
-		primary(GameConstants::PRIMARY_SKILLS, 0)
-	{}
+	Limiter();
+	~Limiter();
 
 	bool heroAllowed(const CGHeroInstance * hero) const;
 

+ 17 - 0
lib/rewardable/Reward.cpp

@@ -11,8 +11,25 @@
 #include "StdInc.h"
 #include "Reward.h"
 
+#include "../mapObjects/CGHeroInstance.h"
+
 VCMI_LIB_NAMESPACE_BEGIN
 
+Rewardable::Reward::Reward()
+	: heroExperience(0)
+	, heroLevel(0)
+	, manaDiff(0)
+	, manaPercentage(-1)
+	, movePoints(0)
+	, movePercentage(-1)
+	, primary(4, 0)
+	, removeObject(false)
+	, spellCast(SpellID::NONE, SecSkillLevel::NONE)
+{
+}
+
+Rewardable::Reward::~Reward() = default;
+
 si32 Rewardable::Reward::calculateManaPoints(const CGHeroInstance * hero) const
 {
 	si32 manaScaled = hero->mana;

+ 10 - 12
lib/rewardable/Reward.h

@@ -10,10 +10,17 @@
 
 #pragma once
 
-#include "../mapObjects/CGHeroInstance.h"
+#include "../ResourceSet.h"
+#include "../bonuses/Bonus.h"
+#include "../CCreatureSet.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+struct Bonus;
+struct Component;
+class CStackBasicDescriptor;
+class CGHeroInstance;
+
 namespace Rewardable
 {
 
@@ -78,17 +85,8 @@ struct DLL_LINKAGE Reward
 
 	si32 calculateManaPoints(const CGHeroInstance * h) const;
 
-	Reward() :
-		heroExperience(0),
-		heroLevel(0),
-		manaDiff(0),
-		manaPercentage(-1),
-		movePoints(0),
-		movePercentage(-1),
-		primary(4, 0),
-		removeObject(false),
-		spellCast(SpellID::NONE, SecSkillLevel::NONE)
-	{}
+	Reward();
+	~Reward();
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{

+ 2 - 1
lib/rmg/CMapGenerator.cpp

@@ -14,12 +14,13 @@
 #include "../mapping/MapFormat.h"
 #include "../VCMI_Lib.h"
 #include "../CGeneralTextHandler.h"
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../mapping/CMapEditManager.h"
 #include "../CTownHandler.h"
 #include "../StringConstants.h"
 #include "../filesystem/Filesystem.h"
 #include "CZonePlacer.h"
-#include "../mapObjects/CObjectClassesHandler.h"
 #include "TileInfo.h"
 #include "Zone.h"
 #include "Functions.h"

+ 2 - 2
lib/rmg/Functions.cpp

@@ -17,8 +17,8 @@
 #include "../TerrainHandler.h"
 #include "../CTownHandler.h"
 #include "../mapping/CMap.h"
-#include "../mapObjects/CommonConstructors.h"
-#include "../mapObjects/MapObjects.h" //needed to resolve templates for CommonConstructors.h
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../VCMI_Lib.h"
 
 VCMI_LIB_NAMESPACE_BEGIN

+ 3 - 3
lib/rmg/RmgObject.cpp

@@ -11,12 +11,12 @@
 #include "StdInc.h"
 #include "RmgObject.h"
 #include "RmgMap.h"
-#include "../mapObjects/CObjectHandler.h"
 #include "../mapping/CMapEditManager.h"
 #include "../mapping/CMap.h"
 #include "../VCMI_Lib.h"
-#include "../mapObjects/CommonConstructors.h"
-#include "../mapObjects/MapObjects.h" //needed to resolve templates for CommonConstructors.h
+#include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../mapObjectConstructors/CObjectClassesHandler.h"
+#include "../mapObjects/ObjectTemplate.h"
 #include "Functions.h"
 #include "../TerrainHandler.h"
 

+ 2 - 1
lib/rmg/modificators/ConnectionsPlacer.cpp

@@ -13,8 +13,9 @@
 #include "../CMapGenerator.h"
 #include "../RmgMap.h"
 #include "../../TerrainHandler.h"
+#include "../../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../../mapping/CMapEditManager.h"
-#include "../../mapObjects/CObjectClassesHandler.h"
 #include "../RmgObject.h"
 #include "ObjectManager.h"
 #include "../Functions.h"

+ 2 - 1
lib/rmg/modificators/MinePlacer.cpp

@@ -10,8 +10,9 @@
 #include "ConnectionsPlacer.h"
 #include "../CMapGenerator.h"
 #include "../RmgMap.h"
+#include "../../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../../mapping/CMapEditManager.h"
-#include "../../mapObjects/CObjectClassesHandler.h"
 #include "../RmgPath.h"
 #include "../RmgObject.h"
 #include "ObjectManager.h"

部分文件因文件數量過多而無法顯示