2
0

CModHandler.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #include "StdInc.h"
  2. #include "CModHandler.h"
  3. #include "JsonNode.h"
  4. #include "Filesystem\CResourceLoader.h" //TODO: reorganize
  5. /*
  6. * CModHandler.h, part of VCMI engine
  7. *
  8. * Authors: listed in file AUTHORS in main folder
  9. *
  10. * License: GNU General Public License v2.0 or later
  11. * Full text of license available in license.txt file, in main folder
  12. *
  13. */
  14. class CArtHandler;
  15. class CHeroHandler;
  16. class CCreatureHandler;
  17. class CSpellHandler;
  18. class CBuildingHandler;
  19. class CObjectHandler;
  20. class CDefObjInfoHandler;
  21. class CTownHandler;
  22. class CGeneralTextHandler;
  23. CModHandler::CModHandler()
  24. {
  25. VLC->modh = this;
  26. loadConfigFromFile ("defaultMods");
  27. //CResourceHandler::loadModsFilesystems(); //scan for all mods
  28. //TODO: mod filesystem is already initialized at LibClasses launch
  29. //TODO: load default (last?) config
  30. }
  31. artID CModHandler::addNewArtifact (CArtifact * art)
  32. {
  33. int id = artifacts.size();
  34. artifacts.push_back (art);
  35. return id;
  36. }
  37. creID CModHandler::addNewCreature (CCreature * cre)
  38. {
  39. int id = creatures.size();
  40. creatures.push_back (cre);
  41. return id;
  42. }
  43. void CModHandler::loadConfigFromFile (std::string name)
  44. {
  45. const JsonNode config(ResourceID("config/" + name + ".json"));
  46. auto hardcodedFeatures = config["hardcodedFeatures"];
  47. settings.CREEP_SIZE = hardcodedFeatures["CREEP_SIZE"].Float();
  48. settings.WEEKLY_GROWTH = hardcodedFeatures["WEEKLY_GROWTH_PERCENT"].Float();
  49. settings.NEUTRAL_STACK_EXP = hardcodedFeatures["NEUTRAL_STACK_EXP_DAILY"].Float();
  50. settings.MAX_BUILDING_PER_TURN = hardcodedFeatures["MAX_BUILDING_PER_TURN"].Float();
  51. settings.DWELLINGS_ACCUMULATE_CREATURES = hardcodedFeatures["DWELLINGS_ACCUMULATE_CREATURES"].Bool();
  52. settings.ALL_CREATURES_GET_DOUBLE_MONTHS = hardcodedFeatures["ALL_CREATURES_GET_DOUBLE_MONTHS"].Bool();
  53. auto gameModules = config["modules"];
  54. modules.STACK_EXP = gameModules["STACK_EXPERIENCE"].Bool();
  55. modules.STACK_ARTIFACT = gameModules["STACK_ARTIFACTS"].Bool();
  56. modules.COMMANDERS = gameModules["COMMANDERS"].Bool();
  57. modules.MITHRIL = gameModules["MITHRIL"].Bool();
  58. //auto mods = config["activeMods"]; //TODO: load only mods from the list
  59. auto resourceLoader = CResourceHandler::get();
  60. auto iterator = resourceLoader->getIterator([](const ResourceID & ident) -> bool
  61. {
  62. std::string name = ident.getName();
  63. return ident.getType() == EResType::TEXT
  64. && std::count(name.begin(), name.end(), '/') == 3
  65. && boost::algorithm::starts_with(name, "ALL/MODS/")
  66. && boost::algorithm::ends_with(name, "MOD"); //all mods have "mod.json" name - does it make sense?
  67. });
  68. std::set<std::string> foundMods;
  69. while (iterator.hasNext())
  70. {
  71. foundMods.insert(iterator->getName());
  72. ++iterator;
  73. }
  74. BOOST_FOREACH (auto mod, foundMods)
  75. {
  76. tlog3 << "\t\tFound mod file: " << mod << "\n";
  77. const JsonNode config (ResourceID("mod"));
  78. const JsonNode *value = &config["creatures"];
  79. if (!value->isNull())
  80. {
  81. BOOST_FOREACH (auto creature, value->Vector())
  82. {
  83. auto cre = loadCreature (creature);
  84. addNewCreature (cre);
  85. }
  86. }
  87. }
  88. }
  89. void CModHandler::saveConfigToFile (std::string name)
  90. {
  91. //JsonNode savedConf = config;
  92. //JsonNode schema(ResourceID("config/defaultSettings.json"));
  93. //savedConf.Struct().erase("session");
  94. //savedConf.minimize(schema);
  95. CResourceHandler::get()->createResource("config/" + name +".json");
  96. std::ofstream file(CResourceHandler::get()->getResourceName(ResourceID("config/" + name +".json")), std::ofstream::trunc);
  97. //file << savedConf;
  98. }
  99. CCreature * CModHandler::loadCreature (const JsonNode &node)
  100. {
  101. CCreature * cre = new CCreature();
  102. cre->idNumber = creatures.size();
  103. const JsonNode *value; //optional value
  104. //TODO: ref name
  105. auto name = node["name"];
  106. cre->nameSing = name["singular"].String();
  107. cre->namePl = name["plural"].String();
  108. //TODO: map name->id
  109. auto cost = node["cost"];
  110. if (cost.getType() == JsonNode::DATA_FLOAT) //gold
  111. {
  112. cre->cost[Res::GOLD] = cost.Float();
  113. }
  114. else
  115. {
  116. int i = 0;
  117. BOOST_FOREACH (auto val, cost.Vector())
  118. {
  119. cre->cost[i++] = val.Float();
  120. }
  121. }
  122. cre->level = node["level"].Float();
  123. cre->faction = -1; //TODO: node["faction"].String() to id or just node["faction"].Float();
  124. cre->fightValue = node["fightValue"].Float();
  125. cre->AIValue = node["aiValue"].Float();
  126. cre->growth = node["growth"].Float();
  127. cre->addBonus(node["hitPoints"].Float(), Bonus::STACK_HEALTH);
  128. cre->addBonus(node["speed"].Float(), Bonus::STACKS_SPEED);
  129. cre->addBonus(node["attack"].Float(), Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK);
  130. cre->addBonus(node["defense"].Float(), Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE);
  131. auto vec = node["damage"].Vector();
  132. cre->addBonus(vec[0].Float(), Bonus::CREATURE_DAMAGE, 1);
  133. cre->addBonus(vec[1].Float(), Bonus::CREATURE_DAMAGE, 2);
  134. //optional
  135. value = &node["shots"];
  136. if (!value->isNull())
  137. cre->addBonus(value->Float(), Bonus::SHOTS);
  138. value = &node["spellPoints"];
  139. if (!value->isNull())
  140. cre->addBonus(value->Float(), Bonus::CASTS);
  141. cre->doubleWide = value->Bool();
  142. value = &node["abilities"];
  143. if (!value->isNull())
  144. {
  145. BOOST_FOREACH (const JsonNode &bonus, value->Vector())
  146. {
  147. cre->addNewBonus(ParseBonus(bonus));
  148. }
  149. }
  150. //graphics
  151. auto graphics = node["graphics"];
  152. cre->animDefName = graphics["animation"].String();
  153. cre->timeBetweenFidgets = graphics["timeBetweenFidgets"].Float();
  154. cre->troopCountLocationOffset = graphics["troopCountLocationOffset"].Float();
  155. cre->attackClimaxFrame = graphics["attackClimaxFrame"].Float();
  156. auto animationTime = graphics["animationTime"];
  157. cre->walkAnimationTime = animationTime["walk"].Float();
  158. cre->attackAnimationTime = animationTime["attack"].Float();
  159. cre->flightAnimationDistance = animationTime["flight"].Float(); //?
  160. //TODO: background?
  161. auto missle = graphics["missle"];
  162. auto offsets = missle["offset"];
  163. cre->upperRightMissleOffsetX = offsets["upperX"].Float();
  164. cre->upperRightMissleOffsetY = offsets["upperY"].Float();
  165. cre->rightMissleOffsetX = offsets["middleX"].Float();
  166. cre->rightMissleOffsetY = offsets["middleY"].Float();
  167. cre->lowerRightMissleOffsetX = offsets["lowerX"].Float();
  168. cre->lowerRightMissleOffsetY = offsets["lowerY"].Float();
  169. int i = 0;
  170. BOOST_FOREACH (auto angle, missle["frameAngles"].Vector())
  171. {
  172. cre->missleFrameAngles[i++] = angle.Float();
  173. }
  174. //we need to know creature id to add it
  175. VLC->creh->idToProjectile[cre->idNumber] = value->String();
  176. auto sounds = node["sound"];
  177. #define GET_SOUND_VALUE(value_name) do { value = &node[#value_name]; if (!value->isNull()) cre->sounds.value_name = sounds[#value_name].String(); } while(0)
  178. GET_SOUND_VALUE(attack);
  179. GET_SOUND_VALUE(defend);
  180. GET_SOUND_VALUE(killed);
  181. GET_SOUND_VALUE(move);
  182. GET_SOUND_VALUE(shoot);
  183. GET_SOUND_VALUE(wince);
  184. GET_SOUND_VALUE(ext1);
  185. GET_SOUND_VALUE(ext2);
  186. GET_SOUND_VALUE(startMoving);
  187. GET_SOUND_VALUE(endMoving);
  188. #undef GET_SOUND_VALUE
  189. creatures.push_back(cre);
  190. return cre;
  191. }
  192. void CModHandler::recreateHandlers()
  193. {
  194. //TODO: consider some template magic to unify all handlers?
  195. //VLC->arth->artifacts.clear();
  196. //VLC->creh->creatures.clear(); //TODO: what about items from original game?
  197. BOOST_FOREACH (auto creature, creatures)
  198. {
  199. VLC->creh->creatures.push_back (creature);
  200. }
  201. BOOST_FOREACH (auto mod, activeMods) //inactive part
  202. {
  203. BOOST_FOREACH (auto art, allMods[mod].artifacts)
  204. {
  205. VLC->arth->artifacts.push_back (artifacts[art]);
  206. //TODO: recreate types / limiters based on string id
  207. }
  208. BOOST_FOREACH (auto creature, allMods[mod].creatures)
  209. {
  210. VLC->creh->creatures.push_back (creatures[creature]);
  211. //TODO VLC->creh->notUsedMonster.push_back (creatures[creature]);
  212. //TODO: recreate upgrades and other properties based on string id
  213. }
  214. }
  215. }
  216. CModHandler::~CModHandler()
  217. {
  218. }