CModHandler.cpp 7.7 KB

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