CMapService.cpp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553
  1. #include "StdInc.h"
  2. #include "CMapService.h"
  3. #include "../Filesystem/CResourceLoader.h"
  4. #include "../Filesystem/CBinaryReader.h"
  5. #include "../Filesystem/CCompressedStream.h"
  6. #include "../Filesystem/CMemoryStream.h"
  7. #include "CMap.h"
  8. #include <boost/crc.hpp>
  9. #include "../vcmi_endian.h"
  10. #include "../CStopWatch.h"
  11. #include "../VCMI_Lib.h"
  12. #include "../CSpellHandler.h"
  13. #include "../CCreatureHandler.h"
  14. #include "../CObjectHandler.h"
  15. #include "../CDefObjInfoHandler.h"
  16. std::unique_ptr<CMap> CMapService::loadMap(const std::string & name)
  17. {
  18. auto stream = getStreamFromFS(name);
  19. return getMapLoader(stream)->loadMap();
  20. }
  21. std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const std::string & name)
  22. {
  23. auto stream = getStreamFromFS(name);
  24. return getMapLoader(stream)->loadMapHeader();
  25. }
  26. std::unique_ptr<CMap> CMapService::loadMap(const ui8 * buffer, int size)
  27. {
  28. auto stream = getStreamFromMem(buffer, size);
  29. return getMapLoader(stream)->loadMap();
  30. }
  31. std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ui8 * buffer, int size)
  32. {
  33. auto stream = getStreamFromMem(buffer, size);
  34. return getMapLoader(stream)->loadMapHeader();
  35. }
  36. std::unique_ptr<CInputStream> CMapService::getStreamFromFS(const std::string & name)
  37. {
  38. return CResourceHandler::get()->load(ResourceID(name, EResType::MAP));
  39. }
  40. std::unique_ptr<CInputStream> CMapService::getStreamFromMem(const ui8 * buffer, int size)
  41. {
  42. return std::unique_ptr<CInputStream>(new CMemoryStream(buffer, size));
  43. }
  44. std::unique_ptr<IMapLoader> CMapService::getMapLoader(std::unique_ptr<CInputStream> & stream)
  45. {
  46. // Read map header
  47. CBinaryReader reader(stream.get());
  48. ui32 header = reader.readUInt32();
  49. reader.getStream()->seek(0);
  50. // Check which map format is used
  51. // gzip header is 3 bytes only in size
  52. switch(header & 0xffffff)
  53. {
  54. // gzip header magic number, reversed for LE
  55. case 0x00088B1F:
  56. stream = std::unique_ptr<CInputStream>(new CCompressedStream(std::move(stream), true));
  57. return std::unique_ptr<IMapLoader>(new CMapLoaderH3M(stream.get()));
  58. case EMapFormat::WOG :
  59. case EMapFormat::AB :
  60. case EMapFormat::ROE :
  61. case EMapFormat::SOD :
  62. return std::unique_ptr<IMapLoader>(new CMapLoaderH3M(stream.get()));
  63. default :
  64. throw std::runtime_error("Unknown map format");
  65. }
  66. }
  67. const bool CMapLoaderH3M::IS_PROFILING_ENABLED = false;
  68. CMapLoaderH3M::CMapLoaderH3M(CInputStream * stream) : map(nullptr), buffer(nullptr), pos(-1), size(-1)
  69. {
  70. initBuffer(stream);
  71. }
  72. CMapLoaderH3M::~CMapLoaderH3M()
  73. {
  74. delete buffer;
  75. }
  76. void CMapLoaderH3M::initBuffer(CInputStream * stream)
  77. {
  78. // Read map data into memory completely
  79. // TODO Replace with CBinaryReader later... (no need for reading whole
  80. // file in memory at once, storing pos & size separately...)
  81. stream->seek(0);
  82. size = stream->getSize();
  83. buffer = new ui8[size];
  84. stream->read(buffer, size);
  85. }
  86. std::unique_ptr<CMap> CMapLoaderH3M::loadMap()
  87. {
  88. // Init map object by parsing the input buffer
  89. map = new CMap();
  90. mapHeader = std::unique_ptr<CMapHeader>(dynamic_cast<CMapHeader *>(map));
  91. init();
  92. return std::unique_ptr<CMap>(dynamic_cast<CMap *>(mapHeader.release()));;
  93. }
  94. std::unique_ptr<CMapHeader> CMapLoaderH3M::loadMapHeader()
  95. {
  96. // Read header
  97. mapHeader = std::unique_ptr<CMapHeader>(new CMapHeader);
  98. readHeader();
  99. return std::move(mapHeader);
  100. }
  101. void CMapLoaderH3M::init()
  102. {
  103. // Compute checksum
  104. boost::crc_32_type result;
  105. result.process_bytes(buffer, size);
  106. map->checksum = result.checksum();
  107. CStopWatch sw;
  108. struct MapLoadingTime
  109. {
  110. std::string name;
  111. si64 time;
  112. MapLoadingTime(std::string name, si64 time) : name(name),
  113. time(time)
  114. {
  115. }
  116. };
  117. std::vector<MapLoadingTime> times;
  118. readHeader();
  119. times.push_back(MapLoadingTime("header", sw.getDiff()));
  120. readDisposedHeroes();
  121. times.push_back(MapLoadingTime("disposed heroes", sw.getDiff()));
  122. readAllowedArtifacts();
  123. times.push_back(MapLoadingTime("allowed artifacts", sw.getDiff()));
  124. readAllowedSpellsAbilities();
  125. times.push_back(MapLoadingTime("allowed spells and abilities", sw.getDiff()));
  126. readRumors();
  127. times.push_back(MapLoadingTime("rumors", sw.getDiff()));
  128. readPredefinedHeroes();
  129. times.push_back(MapLoadingTime("predefined heroes", sw.getDiff()));
  130. readTerrain();
  131. times.push_back(MapLoadingTime("terrain", sw.getDiff()));
  132. readDefInfo();
  133. times.push_back(MapLoadingTime("def info", sw.getDiff()));
  134. readObjects();
  135. times.push_back(MapLoadingTime("objects", sw.getDiff()));
  136. readEvents();
  137. times.push_back(MapLoadingTime("events", sw.getDiff()));
  138. // Calculate blocked / visitable positions
  139. for(int f = 0; f < map->objects.size(); ++f)
  140. {
  141. if(!map->objects[f]->defInfo) continue;
  142. addBlockVisibleTiles(map->objects[f]);
  143. }
  144. times.push_back(MapLoadingTime("blocked/visitable tiles", sw.getDiff()));
  145. // Print profiling times
  146. if(IS_PROFILING_ENABLED)
  147. {
  148. BOOST_FOREACH(MapLoadingTime & mlt, times)
  149. {
  150. tlog0 << "\tReading " << mlt.name << " took " << mlt.time << " ms." << std::endl;
  151. }
  152. }
  153. }
  154. void CMapLoaderH3M::readHeader()
  155. {
  156. pos = 0;
  157. // Check map for validity
  158. if(size < 50 || !buffer[4])
  159. {
  160. throw std::runtime_error("Corrupted map file.");
  161. }
  162. // Map version
  163. mapHeader->version = (EMapFormat::EMapFormat)(read_le_u32(buffer + pos));
  164. pos += 4;
  165. if(mapHeader->version != EMapFormat::ROE && mapHeader->version != EMapFormat::AB && mapHeader->version != EMapFormat::SOD
  166. && mapHeader->version != EMapFormat::WOG)
  167. {
  168. throw std::runtime_error("Invalid map format!");
  169. }
  170. // Read map name, description, dimensions,...
  171. mapHeader->areAnyPlayers = static_cast<bool>(readChar(buffer, pos));
  172. mapHeader->height = mapHeader->width = (read_le_u32(buffer + pos));
  173. pos += 4;
  174. mapHeader->twoLevel = static_cast<bool>(readChar(buffer, pos));
  175. mapHeader->name = readString(buffer, pos);
  176. mapHeader->description = readString(buffer, pos);
  177. mapHeader->difficulty = readChar(buffer, pos);
  178. if(mapHeader->version != EMapFormat::ROE)
  179. {
  180. mapHeader->levelLimit = readChar(buffer, pos);
  181. }
  182. else
  183. {
  184. mapHeader->levelLimit = 0;
  185. }
  186. readPlayerInfo();
  187. readVictoryLossConditions();
  188. readTeamInfo();
  189. readAllowedHeroes();
  190. }
  191. void CMapLoaderH3M::readPlayerInfo()
  192. {
  193. mapHeader->players.resize(8);
  194. for(int i = 0; i < 8; ++i)
  195. {
  196. mapHeader->players[i].canHumanPlay = static_cast<bool>(buffer[pos++]);
  197. mapHeader->players[i].canComputerPlay = static_cast<bool>(buffer[pos++]);
  198. // If nobody can play with this player
  199. if((!(mapHeader->players[i].canHumanPlay || mapHeader->players[i].canComputerPlay)))
  200. {
  201. switch(mapHeader->version)
  202. {
  203. case EMapFormat::SOD:
  204. case EMapFormat::WOG:
  205. pos += 13;
  206. break;
  207. case EMapFormat::AB:
  208. pos += 12;
  209. break;
  210. case EMapFormat::ROE:
  211. pos += 6;
  212. break;
  213. }
  214. continue;
  215. }
  216. mapHeader->players[i].aiTactic = static_cast<EAiTactic::EAiTactic>(buffer[pos++]);
  217. if(mapHeader->version == EMapFormat::SOD || mapHeader->version == EMapFormat::WOG)
  218. {
  219. mapHeader->players[i].p7 = buffer[pos++];
  220. }
  221. else
  222. {
  223. mapHeader->players[i].p7 = -1;
  224. }
  225. // Factions this player can choose
  226. ui16 allowedFactions = buffer[pos++];
  227. if(mapHeader->version != EMapFormat::ROE)
  228. {
  229. allowedFactions += (buffer[pos++]) * 256;
  230. }
  231. mapHeader->players[i].allowedFactions.clear();
  232. for(int fact = 0; fact < 16; ++fact)
  233. {
  234. if(allowedFactions & (1 << fact))
  235. {
  236. mapHeader->players[i].allowedFactions.insert(fact);
  237. }
  238. }
  239. mapHeader->players[i].isFactionRandom = static_cast<bool>(buffer[pos++]);
  240. mapHeader->players[i].hasMainTown = static_cast<bool>(buffer[pos++]);
  241. if(mapHeader->players[i].hasMainTown)
  242. {
  243. if(mapHeader->version != EMapFormat::ROE)
  244. {
  245. mapHeader->players[i].generateHeroAtMainTown = static_cast<bool>(buffer[pos++]);
  246. mapHeader->players[i].generateHero = static_cast<bool>(buffer[pos++]);
  247. }
  248. else
  249. {
  250. mapHeader->players[i].generateHeroAtMainTown = true;
  251. mapHeader->players[i].generateHero = false;
  252. }
  253. mapHeader->players[i].posOfMainTown.x = buffer[pos++];
  254. mapHeader->players[i].posOfMainTown.y = buffer[pos++];
  255. mapHeader->players[i].posOfMainTown.z = buffer[pos++];
  256. }
  257. mapHeader->players[i].hasHero = buffer[pos++];
  258. mapHeader->players[i].customHeroID = buffer[pos++];
  259. if(mapHeader->players[i].customHeroID != 0xff)
  260. {
  261. mapHeader->players[i].mainHeroPortrait = buffer[pos++];
  262. if (mapHeader->players[i].mainHeroPortrait == 0xff)
  263. mapHeader->players[i].mainHeroPortrait = -1; //correct 1-byte -1 (0xff) into 4-byte -1
  264. mapHeader->players[i].mainHeroName = readString(buffer, pos);
  265. }
  266. else
  267. mapHeader->players[i].customHeroID = -1; //correct 1-byte -1 (0xff) into 4-byte -1
  268. if(mapHeader->version != EMapFormat::ROE)
  269. {
  270. mapHeader->players[i].powerPlaceholders = buffer[pos++]; //unknown byte
  271. int heroCount = buffer[pos++];
  272. pos += 3;
  273. for(int pp = 0; pp < heroCount; ++pp)
  274. {
  275. SHeroName vv;
  276. vv.heroId = buffer[pos++];
  277. int hnl = buffer[pos++];
  278. pos += 3;
  279. for(int zz = 0; zz < hnl; ++zz)
  280. {
  281. vv.heroName += buffer[pos++];
  282. }
  283. mapHeader->players[i].heroesNames.push_back(vv);
  284. }
  285. }
  286. }
  287. }
  288. void CMapLoaderH3M::readVictoryLossConditions()
  289. {
  290. mapHeader->victoryCondition.obj = nullptr;
  291. mapHeader->victoryCondition.condition = (EVictoryConditionType::EVictoryConditionType)buffer[pos++];
  292. // Specific victory conditions
  293. if(mapHeader->victoryCondition.condition != EVictoryConditionType::WINSTANDARD)
  294. {
  295. // Read victory conditions
  296. int nr = 0;
  297. switch(mapHeader->victoryCondition.condition)
  298. {
  299. case EVictoryConditionType::ARTIFACT:
  300. {
  301. mapHeader->victoryCondition.objectId = buffer[pos + 2];
  302. nr = (mapHeader->version == EMapFormat::ROE ? 1 : 2);
  303. break;
  304. }
  305. case EVictoryConditionType::GATHERTROOP:
  306. {
  307. mapHeader->victoryCondition.objectId = buffer[pos + 2];
  308. mapHeader->victoryCondition.count = read_le_u32(buffer + pos + (mapHeader->version == EMapFormat::ROE ? 3 : 4));
  309. nr = (mapHeader->version == EMapFormat::ROE ? 5 : 6);
  310. break;
  311. }
  312. case EVictoryConditionType::GATHERRESOURCE:
  313. {
  314. mapHeader->victoryCondition.objectId = buffer[pos + 2];
  315. mapHeader->victoryCondition.count = read_le_u32(buffer + pos + 3);
  316. nr = 5;
  317. break;
  318. }
  319. case EVictoryConditionType::BUILDCITY:
  320. {
  321. mapHeader->victoryCondition.pos.x = buffer[pos + 2];
  322. mapHeader->victoryCondition.pos.y = buffer[pos + 3];
  323. mapHeader->victoryCondition.pos.z = buffer[pos + 4];
  324. mapHeader->victoryCondition.count = buffer[pos + 5];
  325. mapHeader->victoryCondition.objectId = buffer[pos + 6];
  326. nr = 5;
  327. break;
  328. }
  329. case EVictoryConditionType::BUILDGRAIL:
  330. {
  331. if(buffer[pos + 4] > 2)
  332. {
  333. mapHeader->victoryCondition.pos = int3(-1,-1,-1);
  334. }
  335. else
  336. {
  337. mapHeader->victoryCondition.pos.x = buffer[pos + 2];
  338. mapHeader->victoryCondition.pos.y = buffer[pos + 3];
  339. mapHeader->victoryCondition.pos.z = buffer[pos + 4];
  340. }
  341. nr = 3;
  342. break;
  343. }
  344. case EVictoryConditionType::BEATHERO:
  345. case EVictoryConditionType::CAPTURECITY:
  346. case EVictoryConditionType::BEATMONSTER:
  347. {
  348. mapHeader->victoryCondition.pos.x = buffer[pos + 2];
  349. mapHeader->victoryCondition.pos.y = buffer[pos + 3];
  350. mapHeader->victoryCondition.pos.z = buffer[pos + 4];
  351. nr = 3;
  352. break;
  353. }
  354. case EVictoryConditionType::TAKEDWELLINGS:
  355. case EVictoryConditionType::TAKEMINES:
  356. {
  357. nr = 0;
  358. break;
  359. }
  360. case EVictoryConditionType::TRANSPORTITEM:
  361. {
  362. mapHeader->victoryCondition.objectId = buffer[pos + 2];
  363. mapHeader->victoryCondition.pos.x = buffer[pos + 3];
  364. mapHeader->victoryCondition.pos.y = buffer[pos + 4];
  365. mapHeader->victoryCondition.pos.z = buffer[pos + 5];
  366. nr = 4;
  367. break;
  368. }
  369. default:
  370. assert(0);
  371. }
  372. mapHeader->victoryCondition.allowNormalVictory = static_cast<bool>(buffer[pos++]);
  373. mapHeader->victoryCondition.appliesToAI = static_cast<bool>(buffer[pos++]);
  374. pos += nr;
  375. }
  376. // Read loss conditions
  377. mapHeader->lossCondition.typeOfLossCon = (ELossConditionType::ELossConditionType)buffer[pos++];
  378. switch(mapHeader->lossCondition.typeOfLossCon)
  379. {
  380. case ELossConditionType::LOSSCASTLE:
  381. case ELossConditionType::LOSSHERO:
  382. {
  383. mapHeader->lossCondition.pos.x = buffer[pos++];
  384. mapHeader->lossCondition.pos.y = buffer[pos++];
  385. mapHeader->lossCondition.pos.z = buffer[pos++];
  386. break;
  387. }
  388. case ELossConditionType::TIMEEXPIRES:
  389. {
  390. mapHeader->lossCondition.timeLimit = read_le_u16(buffer + pos);
  391. pos += 2;
  392. break;
  393. }
  394. }
  395. }
  396. void CMapLoaderH3M::readTeamInfo()
  397. {
  398. mapHeader->howManyTeams = buffer[pos++];
  399. if(mapHeader->howManyTeams > 0)
  400. {
  401. // Teams
  402. for(int i = 0; i < 8; ++i)
  403. {
  404. mapHeader->players[i].team = buffer[pos++];
  405. }
  406. }
  407. else
  408. {
  409. // No alliances
  410. for(int i = 0; i < GameConstants::PLAYER_LIMIT; i++)
  411. {
  412. if(mapHeader->players[i].canComputerPlay || mapHeader->players[i].canHumanPlay)
  413. {
  414. mapHeader->players[i].team = mapHeader->howManyTeams++;
  415. }
  416. }
  417. }
  418. }
  419. void CMapLoaderH3M::readAllowedHeroes()
  420. {
  421. int pom = pos;
  422. mapHeader->allowedHeroes.resize(GameConstants::HEROES_QUANTITY, false);
  423. for(; pos < pom + (mapHeader->version == EMapFormat::ROE ? 16 : 20) ; ++pos)
  424. {
  425. ui8 c = buffer[pos];
  426. for(int yy = 0; yy < 8; ++yy)
  427. {
  428. if((pos - pom) * 8 + yy < GameConstants::HEROES_QUANTITY)
  429. {
  430. if(c == (c | static_cast<ui8>(std::pow(2., yy))))
  431. {
  432. mapHeader->allowedHeroes[(pos - pom) * 8 + yy] = true;
  433. }
  434. }
  435. }
  436. }
  437. // Probably reserved for further heroes
  438. if(mapHeader->version > EMapFormat::ROE)
  439. {
  440. int placeholdersQty = read_le_u32(buffer + pos);
  441. pos += 4;
  442. for(int p = 0; p < placeholdersQty; ++p)
  443. {
  444. mapHeader->placeholdedHeroes.push_back(buffer[pos++]);
  445. }
  446. }
  447. }
  448. void CMapLoaderH3M::readDisposedHeroes()
  449. {
  450. // Reading disposed heroes (20 bytes)
  451. ui8 disp = 0;
  452. if(map->version >= EMapFormat::SOD)
  453. {
  454. disp = buffer[pos++];
  455. map->disposedHeroes.resize(disp);
  456. for(int g = 0; g < disp; ++g)
  457. {
  458. map->disposedHeroes[g].heroId = buffer[pos++];
  459. map->disposedHeroes[g].portrait = buffer[pos++];
  460. int lenbuf = read_le_u32(buffer + pos);
  461. pos += 4;
  462. for(int zz = 0; zz < lenbuf; zz++)
  463. {
  464. map->disposedHeroes[g].name += buffer[pos++];
  465. }
  466. map->disposedHeroes[g].players = buffer[pos++];
  467. }
  468. }
  469. //omitting NULLS
  470. pos += 31;
  471. }
  472. void CMapLoaderH3M::readAllowedArtifacts()
  473. {
  474. map->allowedArtifact.resize(GameConstants::ARTIFACTS_QUANTITY);
  475. for(ui32 x = 0; x < map->allowedArtifact.size(); x++)
  476. {
  477. map->allowedArtifact[x] = true;
  478. }
  479. // Reading allowed artifacts: 17 or 18 bytes
  480. if(map->version != EMapFormat::ROE)
  481. {
  482. // Starting i for loop
  483. int ist = pos;
  484. for(; pos < ist + (map->version == EMapFormat::AB ? 17 : 18); ++pos)
  485. {
  486. ui8 c = buffer[pos];
  487. for(int yy = 0; yy < 8; ++yy)
  488. {
  489. if((pos - ist) * 8 + yy < GameConstants::ARTIFACTS_QUANTITY)
  490. {
  491. if(c == (c | static_cast<ui8>(std::pow(2., yy))))
  492. {
  493. map->allowedArtifact[(pos - ist) * 8 + yy] = false;
  494. }
  495. }
  496. }
  497. }
  498. }
  499. // ban combo artifacts
  500. if (map->version == EMapFormat::ROE || map->version == EMapFormat::AB)
  501. {
  502. BOOST_FOREACH(CArtifact * artifact, VLC->arth->artifacts)
  503. {
  504. // combo
  505. if (artifact->constituents)
  506. {
  507. map->allowedArtifact[artifact->id] = false;
  508. }
  509. }
  510. if (map->version == EMapFormat::ROE)
  511. {
  512. // Armageddon's Blade
  513. map->allowedArtifact[128] = false;
  514. }
  515. }
  516. // Messy, but needed
  517. if(map->victoryCondition.condition == EVictoryConditionType::ARTIFACT
  518. || map->victoryCondition.condition == EVictoryConditionType::TRANSPORTITEM)
  519. {
  520. map->allowedArtifact[map->victoryCondition.objectId] = false;
  521. }
  522. }
  523. void CMapLoaderH3M::readAllowedSpellsAbilities()
  524. {
  525. // Read allowed spells
  526. map->allowedSpell.resize(GameConstants::SPELLS_QUANTITY);
  527. for(ui32 x = 0; x < map->allowedSpell.size(); x++)
  528. {
  529. map->allowedSpell[x] = true;
  530. }
  531. // Read allowed abilities
  532. map->allowedAbilities.resize(GameConstants::SKILL_QUANTITY);
  533. for(ui32 x = 0; x < map->allowedAbilities.size(); x++)
  534. {
  535. map->allowedAbilities[x] = true;
  536. }
  537. if(map->version >= EMapFormat::SOD)
  538. {
  539. // Reading allowed spells (9 bytes)
  540. int ist = pos;
  541. for(; pos < ist + 9; ++pos)
  542. {
  543. ui8 c = buffer[pos];
  544. for(int yy = 0; yy < 8; ++yy)
  545. {
  546. if((pos - ist) * 8 + yy < GameConstants::SPELLS_QUANTITY)
  547. {
  548. if(c == (c | static_cast<ui8>(std::pow(2., yy))))
  549. {
  550. map->allowedSpell[(pos - ist) * 8 + yy] = false;
  551. }
  552. }
  553. }
  554. }
  555. // Allowed hero's abilities (4 bytes)
  556. ist = pos;
  557. for(; pos < ist + 4; ++pos)
  558. {
  559. ui8 c = buffer[pos];
  560. for(int yy = 0; yy < 8; ++yy)
  561. {
  562. if((pos - ist) * 8 + yy < GameConstants::SKILL_QUANTITY)
  563. {
  564. if(c == (c | static_cast<ui8>(std::pow(2., yy))))
  565. {
  566. map->allowedAbilities[(pos - ist) * 8 + yy] = false;
  567. }
  568. }
  569. }
  570. }
  571. }
  572. }
  573. void CMapLoaderH3M::readRumors()
  574. {
  575. int rumNr = read_le_u32(buffer + pos);
  576. pos += 4;
  577. for(int it = 0; it < rumNr; it++)
  578. {
  579. Rumor ourRumor;
  580. // Read rumor name and text
  581. int nameL = read_le_u32(buffer + pos);
  582. pos += 4;
  583. for(int zz = 0; zz < nameL; zz++)
  584. {
  585. ourRumor.name += buffer[pos++];
  586. }
  587. nameL = read_le_u32(buffer + pos);
  588. pos += 4;
  589. for(int zz = 0; zz < nameL; zz++)
  590. {
  591. ourRumor.text += buffer[pos++];
  592. }
  593. map->rumors.push_back(ourRumor);
  594. }
  595. }
  596. void CMapLoaderH3M::readPredefinedHeroes()
  597. {
  598. switch(map->version)
  599. {
  600. case EMapFormat::WOG:
  601. case EMapFormat::SOD:
  602. {
  603. // Disposed heroes
  604. for(int z = 0; z < GameConstants::HEROES_QUANTITY; z++)
  605. {
  606. int custom = buffer[pos++];
  607. if(!custom) continue;
  608. CGHeroInstance * hero = new CGHeroInstance();
  609. hero->ID = Obj::HERO;
  610. hero->subID = z;
  611. // True if hore's experience is greater than 0
  612. if(readChar(buffer, pos))
  613. {
  614. hero->exp = read_le_u32(buffer + pos);
  615. pos += 4;
  616. }
  617. else
  618. {
  619. hero->exp = 0;
  620. }
  621. // True if hero has specified abilities
  622. if(readChar(buffer, pos))
  623. {
  624. int howMany = read_le_u32(buffer + pos);
  625. pos += 4;
  626. hero->secSkills.resize(howMany);
  627. for(int yy = 0; yy < howMany; ++yy)
  628. {
  629. hero->secSkills[yy].first = buffer[pos];
  630. ++pos;
  631. hero->secSkills[yy].second = buffer[pos];
  632. ++pos;
  633. }
  634. }
  635. loadArtifactsOfHero(hero);
  636. // custom bio
  637. if(readChar(buffer, pos))
  638. {
  639. hero->biography = readString(buffer, pos);
  640. }
  641. // 0xFF is default, 00 male, 01 female
  642. hero->sex = buffer[pos++];
  643. // are spells
  644. if(readChar(buffer, pos))
  645. {
  646. int ist = pos;
  647. for(; pos < ist + 9; ++pos)
  648. {
  649. ui8 c = buffer[pos];
  650. for(int yy = 0; yy < 8; ++yy)
  651. {
  652. if((pos - ist) * 8 + yy < GameConstants::SPELLS_QUANTITY)
  653. {
  654. if(c == (c | static_cast<ui8>(std::pow(2., yy))))
  655. {
  656. hero->spells.insert((pos - ist) * 8 + yy);
  657. }
  658. }
  659. }
  660. }
  661. }
  662. // customPrimSkills
  663. if(readChar(buffer, pos))
  664. {
  665. for(int xx = 0; xx < GameConstants::PRIMARY_SKILLS; xx++)
  666. {
  667. hero->pushPrimSkill(xx, buffer[pos++]);
  668. }
  669. }
  670. map->predefinedHeroes.push_back(hero);
  671. }
  672. break;
  673. }
  674. case EMapFormat::ROE:
  675. pos+=0;
  676. break;
  677. }
  678. }
  679. void CMapLoaderH3M::loadArtifactsOfHero(CGHeroInstance * hero)
  680. {
  681. bool artSet = buffer[pos];
  682. ++pos;
  683. // True if artifact set is not default (hero has some artifacts)
  684. if(artSet)
  685. {
  686. for(int pom = 0; pom < 16; pom++)
  687. {
  688. loadArtifactToSlot(hero, pom);
  689. }
  690. // misc5 art //17
  691. if(map->version >= EMapFormat::SOD)
  692. {
  693. if(!loadArtifactToSlot(hero, ArtifactPosition::MACH4))
  694. {
  695. // catapult by default
  696. hero->putArtifact(ArtifactPosition::MACH4, createArtifact(GameConstants::ID_CATAPULT));
  697. }
  698. }
  699. loadArtifactToSlot(hero, ArtifactPosition::SPELLBOOK);
  700. // 19 //???what is that? gap in file or what? - it's probably fifth slot..
  701. if(map->version > EMapFormat::ROE)
  702. {
  703. loadArtifactToSlot(hero, ArtifactPosition::MISC5);
  704. }
  705. else
  706. {
  707. ++pos;
  708. }
  709. // bag artifacts //20
  710. // number of artifacts in hero's bag
  711. int amount = read_le_u16(buffer + pos);
  712. pos += 2;
  713. for(int ss = 0; ss < amount; ++ss)
  714. {
  715. loadArtifactToSlot(hero, GameConstants::BACKPACK_START + hero->artifactsInBackpack.size());
  716. }
  717. }
  718. }
  719. bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot)
  720. {
  721. const int artmask = map->version == EMapFormat::ROE ? 0xff : 0xffff;
  722. int aid;
  723. if(map->version == EMapFormat::ROE)
  724. {
  725. aid = buffer[pos];
  726. pos++;
  727. }
  728. else
  729. {
  730. aid = read_le_u16(buffer + pos);
  731. pos += 2;
  732. }
  733. bool isArt = aid != artmask;
  734. if(isArt)
  735. {
  736. if(vstd::contains(VLC->arth->bigArtifacts, aid) && slot >= GameConstants::BACKPACK_START)
  737. {
  738. tlog3 << "Warning: A big artifact (war machine) in hero's backpack, ignoring..." << std::endl;
  739. return false;
  740. }
  741. if(aid == 0 && slot == ArtifactPosition::MISC5)
  742. {
  743. //TODO: check how H3 handles it -> art 0 in slot 18 in AB map
  744. tlog3 << "Spellbook to MISC5 slot? Putting it spellbook place. AB format peculiarity ? (format "
  745. << static_cast<int>(map->version) << ")" << std::endl;
  746. slot = ArtifactPosition::SPELLBOOK;
  747. }
  748. hero->putArtifact(slot, createArtifact(aid));
  749. }
  750. return isArt;
  751. }
  752. CArtifactInstance * CMapLoaderH3M::createArtifact(int aid, int spellID /*= -1*/)
  753. {
  754. CArtifactInstance * a = nullptr;
  755. if(aid >= 0)
  756. {
  757. if(spellID < 0)
  758. {
  759. a = CArtifactInstance::createNewArtifactInstance(aid);
  760. }
  761. else
  762. {
  763. a = CArtifactInstance::createScroll(VLC->spellh->spells[spellID]);
  764. }
  765. }
  766. else
  767. {
  768. a = new CArtifactInstance();
  769. }
  770. addNewArtifactInstance(a);
  771. //TODO make it nicer
  772. if(a->artType && a->artType->constituents)
  773. {
  774. CCombinedArtifactInstance * comb = dynamic_cast<CCombinedArtifactInstance *>(a);
  775. BOOST_FOREACH(CCombinedArtifactInstance::ConstituentInfo & ci, comb->constituentsInfo)
  776. {
  777. addNewArtifactInstance(ci.art);
  778. }
  779. }
  780. return a;
  781. }
  782. void CMapLoaderH3M::addNewArtifactInstance(CArtifactInstance * art)
  783. {
  784. art->id = map->artInstances.size();
  785. map->artInstances.push_back(art);
  786. }
  787. void CMapLoaderH3M::readTerrain()
  788. {
  789. // Allocate memory for terrain data
  790. map->terrain = new TerrainTile**[map->width];
  791. for(int ii = 0; ii < map->width; ii++)
  792. {
  793. map->terrain[ii] = new TerrainTile*[map->height];
  794. for(int jj = 0; jj < map->height; jj++)
  795. {
  796. map->terrain[ii][jj] = new TerrainTile[map->twoLevel ? 2 : 1];
  797. }
  798. }
  799. // Read terrain
  800. for(int a = 0; a < 2; ++a)
  801. {
  802. if(a == 1 && !map->twoLevel)
  803. {
  804. break;
  805. }
  806. for(int c = 0; c < map->width; c++)
  807. {
  808. for(int z = 0; z < map->height; z++)
  809. {
  810. map->terrain[z][c][a].terType = static_cast<ETerrainType::ETerrainType>(buffer[pos++]);
  811. map->terrain[z][c][a].terView = buffer[pos++];
  812. map->terrain[z][c][a].riverType = static_cast<ERiverType::ERiverType>(buffer[pos++]);
  813. map->terrain[z][c][a].riverDir = buffer[pos++];
  814. map->terrain[z][c][a].roadType = static_cast<ERoadType::ERoadType>(buffer[pos++]);
  815. map->terrain[z][c][a].roadDir = buffer[pos++];
  816. map->terrain[z][c][a].extTileFlags = buffer[pos++];
  817. map->terrain[z][c][a].blocked = (map->terrain[z][c][a].terType == ETerrainType::ROCK ? 1 : 0); //underground tiles are always blocked
  818. map->terrain[z][c][a].visitable = 0;
  819. }
  820. }
  821. }
  822. }
  823. void CMapLoaderH3M::readDefInfo()
  824. {
  825. int defAmount = read_le_u32(buffer + pos);
  826. pos += 4;
  827. map->customDefs.reserve(defAmount + 8);
  828. // Read custom defs
  829. for(int idd = 0; idd < defAmount; ++idd)
  830. {
  831. CGDefInfo * defInfo = new CGDefInfo();
  832. // Read name
  833. int nameLength = read_le_u32(buffer + pos);
  834. pos += 4;
  835. defInfo->name.reserve(nameLength);
  836. for(int cd = 0; cd < nameLength; ++cd)
  837. {
  838. defInfo->name += buffer[pos++];
  839. }
  840. std::transform(defInfo->name.begin(),defInfo->name.end(),defInfo->name.begin(),(int(*)(int))toupper);
  841. ui8 bytes[12];
  842. for(int v = 0; v < 12; ++v)
  843. {
  844. bytes[v] = buffer[pos++];
  845. }
  846. defInfo->terrainAllowed = read_le_u16(buffer + pos);
  847. pos += 2;
  848. defInfo->terrainMenu = read_le_u16(buffer + pos);
  849. pos += 2;
  850. defInfo->id = read_le_u32(buffer + pos);
  851. pos += 4;
  852. defInfo->subid = read_le_u32(buffer + pos);
  853. pos += 4;
  854. defInfo->type = buffer[pos++];
  855. defInfo->printPriority = buffer[pos++];
  856. for(int zi = 0; zi < 6; ++zi)
  857. {
  858. defInfo->blockMap[zi] = reverse(bytes[zi]);
  859. }
  860. for(int zi = 0; zi < 6; ++zi)
  861. {
  862. defInfo->visitMap[zi] = reverse(bytes[6 + zi]);
  863. }
  864. pos += 16;
  865. if(defInfo->id != Obj::HERO && defInfo->id != 70)
  866. {
  867. CGDefInfo * h = VLC->dobjinfo->gobjs[defInfo->id][defInfo->subid];
  868. if(!h)
  869. {
  870. //remove fake entry
  871. VLC->dobjinfo->gobjs[defInfo->id].erase(defInfo->subid);
  872. if(VLC->dobjinfo->gobjs[defInfo->id].size())
  873. {
  874. VLC->dobjinfo->gobjs.erase(defInfo->id);
  875. }
  876. tlog2 << "\t\tWarning: no defobjinfo entry for object ID="
  877. << defInfo->id << " subID=" << defInfo->subid << std::endl;
  878. }
  879. else
  880. {
  881. defInfo->visitDir = VLC->dobjinfo->gobjs[defInfo->id][defInfo->subid]->visitDir;
  882. }
  883. }
  884. else
  885. {
  886. defInfo->visitDir = 0xff;
  887. }
  888. if(defInfo->id == Obj::EVENT)
  889. {
  890. std::memset(defInfo->blockMap, 255, 6);
  891. }
  892. //calculating coverageMap
  893. defInfo->fetchInfoFromMSK();
  894. map->customDefs.push_back(defInfo);
  895. }
  896. //add holes - they always can appear
  897. for(int i = 0; i < 8 ; ++i)
  898. {
  899. map->customDefs.push_back(VLC->dobjinfo->gobjs[124][i]);
  900. }
  901. }
  902. void CMapLoaderH3M::readObjects()
  903. {
  904. int howManyObjs = read_le_u32(buffer + pos);
  905. pos += 4;
  906. for(int ww = 0; ww < howManyObjs; ++ww)
  907. {
  908. CGObjectInstance * nobj = 0;
  909. int3 objPos;
  910. objPos.x = buffer[pos++];
  911. objPos.y = buffer[pos++];
  912. objPos.z = buffer[pos++];
  913. int defnum = read_le_u32(buffer + pos);
  914. pos += 4;
  915. int idToBeGiven = map->objects.size();
  916. CGDefInfo * defInfo = map->customDefs.at(defnum);
  917. pos += 5;
  918. switch(defInfo->id)
  919. {
  920. case Obj::EVENT:
  921. {
  922. CGEvent * evnt = new CGEvent();
  923. nobj = evnt;
  924. bool guardMess = buffer[pos];
  925. ++pos;
  926. if(guardMess)
  927. {
  928. int messLong = read_le_u32(buffer + pos);
  929. pos += 4;
  930. if(messLong > 0)
  931. {
  932. for(int yy = 0; yy < messLong; ++yy)
  933. {
  934. evnt->message += buffer[pos + yy];
  935. }
  936. pos += messLong;
  937. }
  938. if(buffer[pos++])
  939. {
  940. readCreatureSet(evnt, 7, map->version > EMapFormat::ROE);
  941. }
  942. pos += 4;
  943. }
  944. evnt->gainedExp = read_le_u32(buffer + pos);
  945. pos += 4;
  946. evnt->manaDiff = read_le_u32(buffer + pos);
  947. pos += 4;
  948. evnt->moraleDiff = static_cast<char>(buffer[pos]);
  949. ++pos;
  950. evnt->luckDiff = static_cast<char>(buffer[pos]);
  951. ++pos;
  952. evnt->resources.resize(GameConstants::RESOURCE_QUANTITY);
  953. for(int x = 0; x < 7; ++x)
  954. {
  955. evnt->resources[x] = read_le_u32(buffer + pos);
  956. pos += 4;
  957. }
  958. evnt->primskills.resize(GameConstants::PRIMARY_SKILLS);
  959. for(int x = 0; x < 4; ++x)
  960. {
  961. evnt->primskills[x] = buffer[pos];
  962. ++pos;
  963. }
  964. int gabn; // Number of gained abilities
  965. gabn = buffer[pos];
  966. ++pos;
  967. for(int oo = 0; oo < gabn; ++oo)
  968. {
  969. evnt->abilities.push_back(buffer[pos]);
  970. ++pos;
  971. evnt->abilityLevels.push_back(buffer[pos]);
  972. ++pos;
  973. }
  974. int gart = buffer[pos]; // Number of gained artifacts
  975. ++pos;
  976. for(int oo = 0; oo < gart; ++oo)
  977. {
  978. if(map->version == EMapFormat::ROE)
  979. {
  980. evnt->artifacts.push_back(buffer[pos]);
  981. ++pos;
  982. }
  983. else
  984. {
  985. evnt->artifacts.push_back(read_le_u16(buffer + pos));
  986. pos += 2;
  987. }
  988. }
  989. int gspel = buffer[pos]; // Number of gained spells
  990. ++pos;
  991. for(int oo = 0; oo < gspel; ++oo)
  992. {
  993. evnt->spells.push_back(buffer[pos]);
  994. ++pos;
  995. }
  996. int gcre = buffer[pos]; //number of gained creatures
  997. ++pos;
  998. readCreatureSet(&evnt->creatures, gcre, map->version > EMapFormat::ROE);
  999. pos += 8;
  1000. evnt->availableFor = buffer[pos];
  1001. ++pos;
  1002. evnt->computerActivate = buffer[pos];
  1003. ++pos;
  1004. evnt->removeAfterVisit = buffer[pos];
  1005. ++pos;
  1006. evnt->humanActivate = true;
  1007. pos += 4;
  1008. break;
  1009. }
  1010. case 34: case 70: case 62: //34 - hero; 70 - random hero; 62 - prison
  1011. {
  1012. nobj = readHero(idToBeGiven);
  1013. break;
  1014. }
  1015. case 4: //Arena
  1016. case 51: //Mercenary Camp
  1017. case 23: //Marletto Tower
  1018. case 61: // Star Axis
  1019. case 32: // Garden of Revelation
  1020. case 100: //Learning Stone
  1021. case 102: //Tree of Knowledge
  1022. case 41: //Library of Enlightenment
  1023. case 47: //School of Magic
  1024. case 107: //School of War
  1025. {
  1026. nobj = new CGVisitableOPH();
  1027. break;
  1028. }
  1029. case 55: //mystical garden
  1030. case 112://windmill
  1031. case 109://water wheel
  1032. {
  1033. nobj = new CGVisitableOPW();
  1034. break;
  1035. }
  1036. case 43: //teleport
  1037. case 44: //teleport
  1038. case 45: //teleport
  1039. case 103://subterranean gate
  1040. case 111://Whirlpool
  1041. {
  1042. nobj = new CGTeleport();
  1043. break;
  1044. }
  1045. case 12: //campfire
  1046. case 29: //Flotsam
  1047. case 82: //Sea Chest
  1048. case 86: //Shipwreck Survivor
  1049. case 101://treasure chest
  1050. {
  1051. nobj = new CGPickable();
  1052. break;
  1053. }
  1054. case 54: //Monster
  1055. case 71: case 72: case 73: case 74: case 75: // Random Monster 1 - 4
  1056. case 162: case 163: case 164: // Random Monster 5 - 7
  1057. {
  1058. CGCreature * cre = new CGCreature();
  1059. nobj = cre;
  1060. if(map->version > EMapFormat::ROE)
  1061. {
  1062. cre->identifier = read_le_u32(buffer + pos);
  1063. pos += 4;
  1064. map->questIdentifierToId[cre->identifier] = idToBeGiven;
  1065. }
  1066. CStackInstance * hlp = new CStackInstance();
  1067. hlp->count = read_le_u16(buffer + pos);
  1068. pos += 2;
  1069. //type will be set during initialization
  1070. cre->putStack(0, hlp);
  1071. cre->character = buffer[pos];
  1072. ++pos;
  1073. bool isMesTre = buffer[pos]; //true if there is message or treasury
  1074. ++pos;
  1075. if(isMesTre)
  1076. {
  1077. cre->message = readString(buffer, pos);
  1078. cre->resources.resize(GameConstants::RESOURCE_QUANTITY);
  1079. for(int j = 0; j < 7; ++j)
  1080. {
  1081. cre->resources[j] = read_le_u32(buffer + pos);
  1082. pos += 4;
  1083. }
  1084. int artID;
  1085. if (map->version == EMapFormat::ROE)
  1086. {
  1087. artID = buffer[pos];
  1088. ++pos;
  1089. }
  1090. else
  1091. {
  1092. artID = read_le_u16(buffer + pos);
  1093. pos += 2;
  1094. }
  1095. if(map->version == EMapFormat::ROE)
  1096. {
  1097. if(artID != 0xff)
  1098. {
  1099. cre->gainedArtifact = artID;
  1100. }
  1101. else
  1102. {
  1103. cre->gainedArtifact = -1;
  1104. }
  1105. }
  1106. else
  1107. {
  1108. if(artID != 0xffff)
  1109. {
  1110. cre->gainedArtifact = artID;
  1111. }
  1112. else
  1113. {
  1114. cre->gainedArtifact = -1;
  1115. }
  1116. }
  1117. }
  1118. cre->neverFlees = buffer[pos];
  1119. ++pos;
  1120. cre->notGrowingTeam = buffer[pos];
  1121. ++pos;
  1122. pos += 2;
  1123. break;
  1124. }
  1125. case 59: case 91: //ocean bottle and sign
  1126. {
  1127. CGSignBottle * sb = new CGSignBottle();
  1128. nobj = sb;
  1129. sb->message = readString(buffer, pos);
  1130. pos += 4;
  1131. break;
  1132. }
  1133. case 83: //seer's hut
  1134. {
  1135. nobj = readSeerHut();
  1136. addQuest(nobj);
  1137. break;
  1138. }
  1139. case 113: //witch hut
  1140. {
  1141. CGWitchHut * wh = new CGWitchHut();
  1142. nobj = wh;
  1143. // in reo we cannot specify it - all are allowed (I hope)
  1144. if(map->version > EMapFormat::ROE)
  1145. {
  1146. int ist=pos;
  1147. for(; pos < ist + 4; ++pos)
  1148. {
  1149. ui8 c = buffer[pos];
  1150. for(int yy = 0; yy < 8; ++yy)
  1151. {
  1152. if((pos - ist) * 8 + yy < GameConstants::SKILL_QUANTITY)
  1153. {
  1154. if(c == (c | static_cast<ui8>(std::pow(2., yy))))
  1155. {
  1156. wh->allowedAbilities.push_back((pos - ist) * 8 + yy);
  1157. }
  1158. }
  1159. }
  1160. }
  1161. }
  1162. else
  1163. {
  1164. // RoE map
  1165. for(int gg = 0; gg < GameConstants::SKILL_QUANTITY; ++gg)
  1166. {
  1167. wh->allowedAbilities.push_back(gg);
  1168. }
  1169. }
  1170. break;
  1171. }
  1172. case 81: //scholar
  1173. {
  1174. CGScholar * sch = new CGScholar();
  1175. nobj = sch;
  1176. sch->bonusType = buffer[pos++];
  1177. sch->bonusID = buffer[pos++];
  1178. pos += 6;
  1179. break;
  1180. }
  1181. case 33: case 219: //garrison
  1182. {
  1183. CGGarrison * gar = new CGGarrison();
  1184. nobj = gar;
  1185. nobj->setOwner(buffer[pos++]);
  1186. pos += 3;
  1187. readCreatureSet(gar, 7, map->version > EMapFormat::ROE);
  1188. if(map->version > EMapFormat::ROE)
  1189. {
  1190. gar->removableUnits = buffer[pos];
  1191. ++pos;
  1192. }
  1193. else
  1194. {
  1195. gar->removableUnits = true;
  1196. }
  1197. pos += 8;
  1198. break;
  1199. }
  1200. case 5: //artifact
  1201. case 65: case 66: case 67: case 68: case 69: //random artifact
  1202. case 93: //spell scroll
  1203. {
  1204. int artID = -1;
  1205. int spellID = -1;
  1206. CGArtifact * art = new CGArtifact();
  1207. nobj = art;
  1208. bool areSettings = buffer[pos++];
  1209. if(areSettings)
  1210. {
  1211. art->message = readString(buffer, pos);
  1212. bool areGuards = buffer[pos++];
  1213. if(areGuards)
  1214. {
  1215. readCreatureSet(art, 7, map->version > EMapFormat::ROE);
  1216. }
  1217. pos += 4;
  1218. }
  1219. if(defInfo->id == 93)
  1220. {
  1221. spellID = read_le_u32(buffer + pos);
  1222. pos += 4;
  1223. artID = 1;
  1224. }
  1225. else if(defInfo->id == 5)
  1226. {
  1227. //specific artifact
  1228. artID = defInfo->subid;
  1229. }
  1230. art->storedArtifact = createArtifact(artID, spellID);
  1231. break;
  1232. }
  1233. case 76: case 79: //random resource; resource
  1234. {
  1235. CGResource * res = new CGResource();
  1236. nobj = res;
  1237. bool isMessGuard = buffer[pos];
  1238. ++pos;
  1239. if(isMessGuard)
  1240. {
  1241. res->message = readString(buffer, pos);
  1242. if(buffer[pos++])
  1243. {
  1244. readCreatureSet(res, 7, map->version > EMapFormat::ROE);
  1245. }
  1246. pos += 4;
  1247. }
  1248. res->amount = read_le_u32(buffer + pos);
  1249. pos += 4;
  1250. if(defInfo->subid == 6)
  1251. {
  1252. // Gold is multiplied by 100.
  1253. res->amount *= 100;
  1254. }
  1255. pos += 4;
  1256. break;
  1257. }
  1258. case 77: case 98: //random town; town
  1259. {
  1260. nobj = readTown(defInfo->subid);
  1261. break;
  1262. }
  1263. case 53:
  1264. case 220://mine (?)
  1265. {
  1266. nobj = new CGMine();
  1267. nobj->setOwner(buffer[pos++]);
  1268. pos += 3;
  1269. break;
  1270. }
  1271. case 17: case 18: case 19: case 20: //dwellings
  1272. {
  1273. nobj = new CGDwelling();
  1274. nobj->setOwner(buffer[pos++]);
  1275. pos += 3;
  1276. break;
  1277. }
  1278. case 78: //Refugee Camp
  1279. case 106: //War Machine Factory
  1280. {
  1281. nobj = new CGDwelling();
  1282. break;
  1283. }
  1284. case 88: case 89: case 90: //spell shrine
  1285. {
  1286. CGShrine * shr = new CGShrine();
  1287. nobj = shr;
  1288. shr->spell = buffer[pos];
  1289. pos += 4;
  1290. break;
  1291. }
  1292. case 6: //pandora's box
  1293. {
  1294. CGPandoraBox * box = new CGPandoraBox();
  1295. nobj = box;
  1296. bool messg = buffer[pos];
  1297. ++pos;
  1298. if(messg)
  1299. {
  1300. box->message = readString(buffer, pos);
  1301. if(buffer[pos++])
  1302. {
  1303. readCreatureSet(box, 7, map->version > EMapFormat::ROE);
  1304. }
  1305. pos += 4;
  1306. }
  1307. box->gainedExp = read_le_u32(buffer + pos);
  1308. pos += 4;
  1309. box->manaDiff = read_le_u32(buffer + pos);
  1310. pos += 4;
  1311. box->moraleDiff = static_cast<si8>(buffer[pos]);
  1312. ++pos;
  1313. box->luckDiff = static_cast<si8>(buffer[pos]);
  1314. ++pos;
  1315. box->resources.resize(GameConstants::RESOURCE_QUANTITY);
  1316. for(int x = 0; x < 7; ++x)
  1317. {
  1318. box->resources[x] = read_le_u32(buffer + pos);
  1319. pos += 4;
  1320. }
  1321. box->primskills.resize(GameConstants::PRIMARY_SKILLS);
  1322. for(int x = 0; x < 4; ++x)
  1323. {
  1324. box->primskills[x] = buffer[pos];
  1325. ++pos;
  1326. }
  1327. int gabn; //number of gained abilities
  1328. gabn = buffer[pos];
  1329. ++pos;
  1330. for(int oo = 0; oo < gabn; ++oo)
  1331. {
  1332. box->abilities.push_back(buffer[pos]);
  1333. ++pos;
  1334. box->abilityLevels.push_back(buffer[pos]);
  1335. ++pos;
  1336. }
  1337. int gart = buffer[pos]; //number of gained artifacts
  1338. ++pos;
  1339. for(int oo = 0; oo < gart; ++oo)
  1340. {
  1341. if(map->version > EMapFormat::ROE)
  1342. {
  1343. box->artifacts.push_back(read_le_u16(buffer + pos));
  1344. pos += 2;
  1345. }
  1346. else
  1347. {
  1348. box->artifacts.push_back(buffer[pos]);
  1349. ++pos;
  1350. }
  1351. }
  1352. int gspel = buffer[pos]; //number of gained spells
  1353. ++pos;
  1354. for(int oo = 0; oo < gspel; ++oo)
  1355. {
  1356. box->spells.push_back(buffer[pos]);
  1357. ++pos;
  1358. }
  1359. int gcre = buffer[pos]; //number of gained creatures
  1360. ++pos;
  1361. readCreatureSet(&box->creatures, gcre, map->version > EMapFormat::ROE);
  1362. pos += 8;
  1363. break;
  1364. }
  1365. case 36: //grail
  1366. {
  1367. map->grailPos = objPos;
  1368. map->grailRadious = read_le_u32(buffer + pos);
  1369. pos += 4;
  1370. continue;
  1371. }
  1372. //dwellings
  1373. case 216: //same as castle + level range
  1374. case 217: //same as castle
  1375. case 218: //level range
  1376. {
  1377. nobj = new CGDwelling();
  1378. CSpecObjInfo * spec = nullptr;
  1379. switch(defInfo->id)
  1380. {
  1381. break; case 216: spec = new CCreGenLeveledCastleInfo();
  1382. break; case 217: spec = new CCreGenAsCastleInfo();
  1383. break; case 218: spec = new CCreGenLeveledInfo();
  1384. }
  1385. spec->player = read_le_u32(buffer + pos);
  1386. pos += 4;
  1387. //216 and 217
  1388. if (auto castleSpec = dynamic_cast<CCreGenAsCastleInfo *>(spec))
  1389. {
  1390. castleSpec->identifier = read_le_u32(buffer + pos);
  1391. pos += 4;
  1392. if(!castleSpec->identifier)
  1393. {
  1394. castleSpec->asCastle = false;
  1395. castleSpec->castles[0] = buffer[pos];
  1396. ++pos;
  1397. castleSpec->castles[1] = buffer[pos];
  1398. ++pos;
  1399. }
  1400. else
  1401. {
  1402. castleSpec->asCastle = true;
  1403. }
  1404. }
  1405. //216 and 218
  1406. if (auto lvlSpec = dynamic_cast<CCreGenLeveledInfo *>(spec))
  1407. {
  1408. lvlSpec->minLevel = std::max(buffer[pos], ui8(1));
  1409. ++pos;
  1410. lvlSpec->maxLevel = std::min(buffer[pos], ui8(7));
  1411. ++pos;
  1412. }
  1413. nobj->setOwner(spec->player);
  1414. static_cast<CGDwelling *>(nobj)->info = spec;
  1415. break;
  1416. }
  1417. case 215:
  1418. {
  1419. CGQuestGuard * guard = new CGQuestGuard();
  1420. addQuest(guard);
  1421. readQuest(guard);
  1422. nobj = guard;
  1423. break;
  1424. }
  1425. case 28: //faerie ring
  1426. case 14: //Swan pond
  1427. case 38: //idol of fortune
  1428. case 30: //Fountain of Fortune
  1429. case 64: //Rally Flag
  1430. case 56: //oasis
  1431. case 96: //temple
  1432. case 110://Watering Hole
  1433. case 31: //Fountain of Youth
  1434. case 11: //Buoy
  1435. case 52: //Mermaid
  1436. case 94: //Stables
  1437. {
  1438. nobj = new CGBonusingObject();
  1439. break;
  1440. }
  1441. case 49: //Magic Well
  1442. {
  1443. nobj = new CGMagicWell();
  1444. break;
  1445. }
  1446. case 15: //Cover of darkness
  1447. case 58: //Redwood Observatory
  1448. case 60: //Pillar of Fire
  1449. {
  1450. nobj = new CGObservatory();
  1451. break;
  1452. }
  1453. case 22: //Corpse
  1454. case 39: //Lean To
  1455. case 105://Wagon
  1456. case 108://Warrior's Tomb
  1457. {
  1458. nobj = new CGOnceVisitable();
  1459. break;
  1460. }
  1461. case 8: //Boat
  1462. {
  1463. nobj = new CGBoat();
  1464. break;
  1465. }
  1466. case 92: //Sirens
  1467. {
  1468. nobj = new CGSirens();
  1469. break;
  1470. }
  1471. case 87: //Shipyard
  1472. {
  1473. nobj = new CGShipyard();
  1474. nobj->setOwner(read_le_u32(buffer + pos));
  1475. pos += 4;
  1476. break;
  1477. }
  1478. case 214: //hero placeholder
  1479. {
  1480. CGHeroPlaceholder * hp = new CGHeroPlaceholder();
  1481. nobj = hp;
  1482. int a = buffer[pos++]; //unknown byte, seems to be always 0 (if not - scream!)
  1483. tlog2 << "Unhandled Hero Placeholder detected: " << a << std::endl;
  1484. int htid = buffer[pos++]; //hero type id
  1485. nobj->subID = htid;
  1486. if(htid == 0xff)
  1487. {
  1488. hp->power = buffer[pos++];
  1489. }
  1490. else
  1491. {
  1492. hp->power = 0;
  1493. }
  1494. break;
  1495. }
  1496. case 10: //Keymaster
  1497. {
  1498. nobj = new CGKeymasterTent();
  1499. break;
  1500. }
  1501. case 9: //Border Guard
  1502. {
  1503. nobj = new CGBorderGuard();
  1504. addQuest(nobj);
  1505. break;
  1506. }
  1507. case 212: //Border Gate
  1508. {
  1509. nobj = new CGBorderGate();
  1510. addQuest (nobj);
  1511. break;
  1512. }
  1513. case 27: case 37: //Eye and Hut of Magi
  1514. {
  1515. nobj = new CGMagi();
  1516. break;
  1517. }
  1518. case 16: case 24: case 25: case 84: case 85: //treasure bank
  1519. {
  1520. nobj = new CBank();
  1521. break;
  1522. }
  1523. case 63: //Pyramid
  1524. {
  1525. nobj = new CGPyramid();
  1526. break;
  1527. }
  1528. case 13: //Cartographer
  1529. {
  1530. nobj = new CCartographer();
  1531. break;
  1532. }
  1533. case 48: //Magic Spring
  1534. {
  1535. nobj = new CGMagicSpring();
  1536. break;
  1537. }
  1538. case 97: //den of thieves
  1539. {
  1540. nobj = new CGDenOfthieves();
  1541. break;
  1542. }
  1543. case 57: //Obelisk
  1544. {
  1545. nobj = new CGObelisk();
  1546. break;
  1547. }
  1548. case 42: //Lighthouse
  1549. {
  1550. nobj = new CGLighthouse();
  1551. nobj->tempOwner = read_le_u32(buffer + pos);
  1552. pos += 4;
  1553. break;
  1554. }
  1555. case 2: //Altar of Sacrifice
  1556. case 99: //Trading Post
  1557. case 213: //Freelancer's Guild
  1558. case 221: //Trading Post (snow)
  1559. {
  1560. nobj = new CGMarket();
  1561. break;
  1562. }
  1563. case 104: //University
  1564. {
  1565. nobj = new CGUniversity();
  1566. break;
  1567. }
  1568. case 7: //Black Market
  1569. {
  1570. nobj = new CGBlackMarket();
  1571. break;
  1572. }
  1573. default: //any other object
  1574. {
  1575. nobj = new CGObjectInstance();
  1576. break;
  1577. }
  1578. }
  1579. nobj->pos = objPos;
  1580. nobj->ID = defInfo->id;
  1581. nobj->id = idToBeGiven;
  1582. if(nobj->ID != Obj::HERO && nobj->ID != Obj::HERO_PLACEHOLDER && nobj->ID != Obj::PRISON)
  1583. {
  1584. nobj->subID = defInfo->subid;
  1585. }
  1586. nobj->defInfo = defInfo;
  1587. assert(idToBeGiven == map->objects.size());
  1588. map->objects.push_back(nobj);
  1589. if(nobj->ID == Obj::TOWN)
  1590. {
  1591. map->towns.push_back(static_cast<CGTownInstance *>(nobj));
  1592. }
  1593. if(nobj->ID == Obj::HERO)
  1594. {
  1595. map->heroes.push_back(static_cast<CGHeroInstance*>(nobj));
  1596. }
  1597. }
  1598. std::sort(map->heroes.begin(), map->heroes.end(), [](const ConstTransitivePtr<CGHeroInstance> & a, const ConstTransitivePtr<CGHeroInstance> & b)
  1599. {
  1600. return a->subID < b->subID;
  1601. });
  1602. }
  1603. void CMapLoaderH3M::readCreatureSet(CCreatureSet * out, int number, bool version)
  1604. {
  1605. const int bytesPerCre = version ? 4 : 3;
  1606. const int maxID = version ? 0xffff : 0xff;
  1607. for(int ir = 0; ir < number; ++ir)
  1608. {
  1609. int creID;
  1610. int count;
  1611. if(version)
  1612. {
  1613. creID = read_le_u16(buffer + pos + ir * bytesPerCre);
  1614. count = read_le_u16(buffer + pos + ir * bytesPerCre + 2);
  1615. }
  1616. else
  1617. {
  1618. creID = buffer[pos + ir * bytesPerCre];
  1619. count = read_le_u16(buffer + pos + ir * bytesPerCre + 1);
  1620. }
  1621. // Empty slot
  1622. if(creID == maxID) continue;
  1623. CStackInstance * hlp = new CStackInstance();
  1624. hlp->count = count;
  1625. if(creID > maxID - 0xf)
  1626. {
  1627. //this will happen when random object has random army
  1628. creID = maxID + 1 - creID + VLC->creh->creatures.size();
  1629. hlp->idRand = creID;
  1630. }
  1631. else
  1632. {
  1633. hlp->setType(creID);
  1634. }
  1635. out->putStack(ir, hlp);
  1636. }
  1637. pos += number * bytesPerCre;
  1638. out->validTypes(true);
  1639. }
  1640. CGObjectInstance * CMapLoaderH3M::readHero(int idToBeGiven)
  1641. {
  1642. CGHeroInstance * nhi = new CGHeroInstance();
  1643. int identifier = 0;
  1644. if(map->version > EMapFormat::ROE)
  1645. {
  1646. identifier = read_le_u32(buffer + pos);
  1647. pos += 4;
  1648. map->questIdentifierToId[identifier] = idToBeGiven;
  1649. }
  1650. ui8 owner = buffer[pos++];
  1651. nhi->subID = buffer[pos++];
  1652. for(int j = 0; j < map->predefinedHeroes.size(); ++j)
  1653. {
  1654. if(map->predefinedHeroes[j]->subID == nhi->subID)
  1655. {
  1656. tlog0 << "Hero " << nhi->subID << " will be taken from the predefined heroes list." << std::endl;
  1657. delete nhi;
  1658. nhi = map->predefinedHeroes[j];
  1659. break;
  1660. }
  1661. }
  1662. nhi->setOwner(owner);
  1663. nhi->portrait = nhi->subID;
  1664. for(int j = 0; j < map->disposedHeroes.size(); ++j)
  1665. {
  1666. if(map->disposedHeroes[j].heroId == nhi->subID)
  1667. {
  1668. nhi->name = map->disposedHeroes[j].name;
  1669. nhi->portrait = map->disposedHeroes[j].portrait;
  1670. break;
  1671. }
  1672. }
  1673. // True if hero has nonstandard name
  1674. if(readChar(buffer, pos))
  1675. {
  1676. nhi->name = readString(buffer, pos);
  1677. }
  1678. if(map->version > EMapFormat::AB)
  1679. {
  1680. // True if hero's experience is greater than 0
  1681. if(readChar(buffer, pos))
  1682. {
  1683. nhi->exp = read_le_u32(buffer + pos);
  1684. pos += 4;
  1685. }
  1686. else
  1687. {
  1688. nhi->exp = 0xffffffff;
  1689. }
  1690. }
  1691. else
  1692. {
  1693. nhi->exp = read_le_u32(buffer + pos);
  1694. pos += 4;
  1695. //0 means "not set" in <=AB maps
  1696. if(!nhi->exp)
  1697. {
  1698. nhi->exp = 0xffffffff;
  1699. }
  1700. }
  1701. bool portrait = buffer[pos];
  1702. ++pos;
  1703. if(portrait)
  1704. {
  1705. nhi->portrait = buffer[pos++];
  1706. }
  1707. // True if hero has specified abilities
  1708. if(readChar(buffer, pos))
  1709. {
  1710. int howMany = read_le_u32(buffer + pos);
  1711. pos += 4;
  1712. nhi->secSkills.resize(howMany);
  1713. for(int yy = 0; yy < howMany; ++yy)
  1714. {
  1715. nhi->secSkills[yy].first = buffer[pos++];
  1716. nhi->secSkills[yy].second = buffer[pos++];
  1717. }
  1718. }
  1719. // True if hero has nonstandard garrison
  1720. if(readChar(buffer, pos))
  1721. {
  1722. readCreatureSet(nhi, 7, map->version > EMapFormat::ROE);
  1723. }
  1724. nhi->formation = buffer[pos];
  1725. ++pos;
  1726. loadArtifactsOfHero(nhi);
  1727. nhi->patrol.patrolRadious = buffer[pos];
  1728. ++pos;
  1729. if(nhi->patrol.patrolRadious == 0xff)
  1730. {
  1731. nhi->patrol.patrolling = false;
  1732. }
  1733. else
  1734. {
  1735. nhi->patrol.patrolling = true;
  1736. }
  1737. if(map->version > EMapFormat::ROE)
  1738. {
  1739. // True if hero has nonstandard (mapmaker defined) biography
  1740. if(readChar(buffer, pos))
  1741. {
  1742. nhi->biography = readString(buffer, pos);
  1743. }
  1744. nhi->sex = buffer[pos];
  1745. ++pos;
  1746. // Remove trash
  1747. if (nhi->sex != 0xFF)
  1748. {
  1749. nhi->sex &= 1;
  1750. }
  1751. }
  1752. else
  1753. {
  1754. nhi->sex = 0xFF;
  1755. }
  1756. // Spells
  1757. if(map->version > EMapFormat::AB)
  1758. {
  1759. bool areSpells = buffer[pos];
  1760. ++pos;
  1761. if(areSpells)
  1762. {
  1763. nhi->spells.insert(0xffffffff); //placeholder "preset spells"
  1764. int ist = pos;
  1765. for(; pos < ist + 9; ++pos)
  1766. {
  1767. ui8 c = buffer[pos];
  1768. for(int yy = 0; yy < 8; ++yy)
  1769. {
  1770. if((pos - ist) * 8 + yy < GameConstants::SPELLS_QUANTITY)
  1771. {
  1772. if(c == (c | static_cast<ui8>(std::pow(2., yy))))
  1773. {
  1774. nhi->spells.insert((pos - ist) * 8 + yy);
  1775. }
  1776. }
  1777. }
  1778. }
  1779. }
  1780. }
  1781. else if(map->version == EMapFormat::AB)
  1782. {
  1783. //we can read one spell
  1784. ui8 buff = buffer[pos];
  1785. ++pos;
  1786. if(buff != 254)
  1787. {
  1788. nhi->spells.insert(0xffffffff); //placeholder "preset spells"
  1789. if(buff < 254) //255 means no spells
  1790. {
  1791. nhi->spells.insert(buff);
  1792. }
  1793. }
  1794. }
  1795. if(map->version > EMapFormat::AB)
  1796. {
  1797. //customPrimSkills
  1798. if(readChar(buffer, pos))
  1799. {
  1800. for(int xx = 0; xx < GameConstants::PRIMARY_SKILLS; ++xx)
  1801. {
  1802. nhi->pushPrimSkill(xx, buffer[pos++]);
  1803. }
  1804. }
  1805. }
  1806. pos += 16;
  1807. return nhi;
  1808. }
  1809. CGSeerHut * CMapLoaderH3M::readSeerHut()
  1810. {
  1811. CGSeerHut * hut = new CGSeerHut();
  1812. if(map->version > EMapFormat::ROE)
  1813. {
  1814. readQuest(hut);
  1815. }
  1816. else
  1817. {
  1818. //RoE
  1819. int artID = buffer[pos];
  1820. ++pos;
  1821. if (artID != 255)
  1822. {
  1823. //not none quest
  1824. hut->quest->m5arts.push_back (artID);
  1825. hut->quest->missionType = CQuest::MISSION_ART;
  1826. }
  1827. else
  1828. {
  1829. hut->quest->missionType = CQuest::MISSION_NONE;
  1830. }
  1831. hut->quest->lastDay = -1; //no timeout
  1832. hut->quest->isCustomFirst = hut->quest->isCustomNext = hut->quest->isCustomComplete = false;
  1833. }
  1834. if (hut->quest->missionType)
  1835. {
  1836. ui8 rewardType = buffer[pos];
  1837. ++pos;
  1838. hut->rewardType = rewardType;
  1839. switch(rewardType)
  1840. {
  1841. case 1:
  1842. {
  1843. hut->rVal = read_le_u32(buffer + pos);
  1844. pos += 4;
  1845. break;
  1846. }
  1847. case 2:
  1848. {
  1849. hut->rVal = read_le_u32(buffer + pos);
  1850. pos += 4;
  1851. break;
  1852. }
  1853. case 3:
  1854. {
  1855. hut->rVal = buffer[pos];
  1856. ++pos;
  1857. break;
  1858. }
  1859. case 4:
  1860. {
  1861. hut->rVal = buffer[pos];
  1862. ++pos;
  1863. break;
  1864. }
  1865. case 5:
  1866. {
  1867. hut->rID = buffer[pos];
  1868. ++pos;
  1869. // Only the first 3 bytes are used. Skip the 4th.
  1870. hut->rVal = read_le_u32(buffer + pos) & 0x00ffffff;
  1871. pos += 4;
  1872. break;
  1873. }
  1874. case 6:
  1875. {
  1876. hut->rID = buffer[pos];
  1877. ++pos;
  1878. hut->rVal = buffer[pos];
  1879. ++pos;
  1880. break;
  1881. }
  1882. case 7:
  1883. {
  1884. hut->rID = buffer[pos];
  1885. ++pos;
  1886. hut->rVal = buffer[pos];
  1887. ++pos;
  1888. break;
  1889. }
  1890. case 8:
  1891. {
  1892. if (map->version == EMapFormat::ROE)
  1893. {
  1894. hut->rID = buffer[pos];
  1895. ++pos;
  1896. }
  1897. else
  1898. {
  1899. hut->rID = read_le_u16(buffer + pos);
  1900. pos += 2;
  1901. }
  1902. break;
  1903. }
  1904. case 9:
  1905. {
  1906. hut->rID = buffer[pos];
  1907. ++pos;
  1908. break;
  1909. }
  1910. case 10:
  1911. {
  1912. if(map->version > EMapFormat::ROE)
  1913. {
  1914. hut->rID = read_le_u16(buffer + pos);
  1915. pos += 2;
  1916. hut->rVal = read_le_u16(buffer + pos);
  1917. pos += 2;
  1918. }
  1919. else
  1920. {
  1921. hut->rID = buffer[pos];
  1922. ++pos;
  1923. hut->rVal = read_le_u16(buffer + pos);
  1924. pos += 2;
  1925. }
  1926. break;
  1927. }
  1928. }
  1929. pos += 2;
  1930. }
  1931. else
  1932. {
  1933. // missionType==255
  1934. pos += 3;
  1935. }
  1936. return hut;
  1937. }
  1938. void CMapLoaderH3M::readQuest(IQuestObject * guard)
  1939. {
  1940. guard->quest->missionType = buffer[pos];
  1941. ++pos;
  1942. switch(guard->quest->missionType)
  1943. {
  1944. case 0:
  1945. return;
  1946. case 2:
  1947. {
  1948. guard->quest->m2stats.resize(4);
  1949. for(int x = 0; x < 4; ++x)
  1950. {
  1951. guard->quest->m2stats[x] = buffer[pos++];
  1952. }
  1953. }
  1954. break;
  1955. case 1:
  1956. case 3:
  1957. case 4:
  1958. {
  1959. guard->quest->m13489val = read_le_u32(buffer + pos);
  1960. pos += 4;
  1961. break;
  1962. }
  1963. case 5:
  1964. {
  1965. int artNumber = buffer[pos];
  1966. ++pos;
  1967. for(int yy = 0; yy < artNumber; ++yy)
  1968. {
  1969. int artid = read_le_u16(buffer + pos);
  1970. pos += 2;
  1971. guard->quest->m5arts.push_back(artid);
  1972. map->allowedArtifact[artid] = false; //these are unavailable for random generation
  1973. }
  1974. break;
  1975. }
  1976. case 6:
  1977. {
  1978. int typeNumber = buffer[pos];
  1979. ++pos;
  1980. guard->quest->m6creatures.resize(typeNumber);
  1981. for(int hh = 0; hh < typeNumber; ++hh)
  1982. {
  1983. guard->quest->m6creatures[hh].type = VLC->creh->creatures[read_le_u16(buffer + pos)];
  1984. pos += 2;
  1985. guard->quest->m6creatures[hh].count = read_le_u16(buffer + pos);
  1986. pos += 2;
  1987. }
  1988. break;
  1989. }
  1990. case 7:
  1991. {
  1992. guard->quest->m7resources.resize(7);
  1993. for(int x = 0; x < 7; ++x)
  1994. {
  1995. guard->quest->m7resources[x] = read_le_u32(buffer + pos);
  1996. pos += 4;
  1997. }
  1998. break;
  1999. }
  2000. case 8:
  2001. case 9:
  2002. {
  2003. guard->quest->m13489val = buffer[pos];
  2004. ++pos;
  2005. break;
  2006. }
  2007. }
  2008. int limit = read_le_u32(buffer + pos);
  2009. pos += 4;
  2010. if(limit == (static_cast<int>(0xffffffff)))
  2011. {
  2012. guard->quest->lastDay = -1;
  2013. }
  2014. else
  2015. {
  2016. guard->quest->lastDay = limit;
  2017. }
  2018. guard->quest->firstVisitText = readString(buffer, pos);
  2019. guard->quest->nextVisitText = readString(buffer, pos);
  2020. guard->quest->completedText = readString(buffer, pos);
  2021. guard->quest->isCustomFirst = guard->quest->firstVisitText.size() > 0;
  2022. guard->quest->isCustomNext = guard->quest->nextVisitText.size() > 0;
  2023. guard->quest->isCustomComplete = guard->quest->completedText.size() > 0;
  2024. }
  2025. void CMapLoaderH3M::addQuest(CGObjectInstance * quest)
  2026. {
  2027. auto q = dynamic_cast<IQuestObject *>(quest);
  2028. q->quest->qid = map->quests.size();
  2029. map->quests.push_back(q->quest);
  2030. }
  2031. CGTownInstance * CMapLoaderH3M::readTown(int castleID)
  2032. {
  2033. CGTownInstance * nt = new CGTownInstance();
  2034. nt->identifier = 0;
  2035. if(map->version > EMapFormat::ROE)
  2036. {
  2037. nt->identifier = read_le_u32(buffer + pos);
  2038. pos += 4;
  2039. }
  2040. nt->tempOwner = buffer[pos];
  2041. ++pos;
  2042. if(readChar(buffer, pos))
  2043. {
  2044. // Has name
  2045. nt->name = readString(buffer, pos);
  2046. }
  2047. // True if garrison isn't empty
  2048. if(readChar(buffer, pos))
  2049. {
  2050. readCreatureSet(nt, 7, map->version > EMapFormat::ROE);
  2051. }
  2052. nt->formation = buffer[pos];
  2053. ++pos;
  2054. // Custom buildings info
  2055. if(readChar(buffer, pos))
  2056. {
  2057. // Built buildings
  2058. for(int byte = 0; byte < 6; ++byte)
  2059. {
  2060. for(int bit = 0; bit < 8; ++bit)
  2061. {
  2062. if(buffer[pos] & (1 << bit))
  2063. {
  2064. nt->builtBuildings.insert(byte * 8 + bit);
  2065. }
  2066. }
  2067. ++pos;
  2068. }
  2069. // Forbidden buildings
  2070. for(int byte = 6; byte < 12; ++byte)
  2071. {
  2072. for(int bit = 0; bit < 8; ++bit)
  2073. {
  2074. if(buffer[pos] & (1 << bit))
  2075. {
  2076. nt->forbiddenBuildings.insert((byte - 6) * 8 + bit);
  2077. }
  2078. }
  2079. ++pos;
  2080. }
  2081. nt->builtBuildings = convertBuildings(nt->builtBuildings, castleID);
  2082. nt->forbiddenBuildings = convertBuildings(nt->forbiddenBuildings, castleID);
  2083. }
  2084. // Standard buildings
  2085. else
  2086. {
  2087. if(readChar(buffer, pos))
  2088. {
  2089. // Has fort
  2090. nt->builtBuildings.insert(EBuilding::FORT);
  2091. }
  2092. //means that set of standard building should be included
  2093. nt->builtBuildings.insert(-50);
  2094. }
  2095. int ist = pos;
  2096. if(map->version > EMapFormat::ROE)
  2097. {
  2098. for(; pos < ist + 9; ++pos)
  2099. {
  2100. ui8 c = buffer[pos];
  2101. for(int yy = 0; yy < 8; ++yy)
  2102. {
  2103. if((pos - ist) * 8 + yy < GameConstants::SPELLS_QUANTITY)
  2104. {
  2105. if(c != (c | static_cast<ui8>(std::pow(2., yy))))
  2106. {
  2107. nt->obligatorySpells.push_back((pos - ist) * 8 + yy);
  2108. }
  2109. }
  2110. }
  2111. }
  2112. }
  2113. ist = pos;
  2114. for(; pos < ist + 9; ++pos)
  2115. {
  2116. ui8 c = buffer[pos];
  2117. for(int yy = 0; yy < 8; ++yy)
  2118. {
  2119. if((pos - ist) * 8 + yy < GameConstants::SPELLS_QUANTITY)
  2120. {
  2121. if(c != (c | static_cast<ui8>(std::pow(2., yy))))
  2122. {
  2123. nt->possibleSpells.push_back((pos - ist) * 8 + yy);
  2124. }
  2125. }
  2126. }
  2127. }
  2128. // Read castle events
  2129. int numberOfEvent = read_le_u32(buffer + pos);
  2130. pos += 4;
  2131. for(int gh = 0; gh < numberOfEvent; ++gh)
  2132. {
  2133. CCastleEvent * nce = new CCastleEvent();
  2134. nce->town = nt;
  2135. nce->name = readString(buffer, pos);
  2136. nce->message = readString(buffer, pos);
  2137. for(int x = 0; x < 7; ++x)
  2138. {
  2139. nce->resources[x] = read_le_u32(buffer + pos);
  2140. pos += 4;
  2141. }
  2142. nce->players = buffer[pos];
  2143. ++pos;
  2144. if(map->version > EMapFormat::AB)
  2145. {
  2146. nce->humanAffected = buffer[pos];
  2147. ++pos;
  2148. }
  2149. else
  2150. {
  2151. nce->humanAffected = true;
  2152. }
  2153. nce->computerAffected = buffer[pos];
  2154. ++pos;
  2155. nce->firstOccurence = read_le_u16(buffer + pos);
  2156. pos += 2;
  2157. nce->nextOccurence = buffer[pos];
  2158. ++pos;
  2159. pos += 17;
  2160. // New buildings
  2161. for(int byte = 0; byte < 6; ++byte)
  2162. {
  2163. for(int bit = 0; bit < 8; ++bit)
  2164. {
  2165. if(buffer[pos] & (1 << bit))
  2166. {
  2167. nce->buildings.insert(byte * 8 + bit);
  2168. }
  2169. }
  2170. ++pos;
  2171. }
  2172. nce->buildings = convertBuildings(nce->buildings, castleID, false);
  2173. nce->creatures.resize(7);
  2174. for(int vv = 0; vv < 7; ++vv)
  2175. {
  2176. nce->creatures[vv] = read_le_u16(buffer + pos);
  2177. pos += 2;
  2178. }
  2179. pos += 4;
  2180. nt->events.push_back(nce);
  2181. }
  2182. if(map->version > EMapFormat::AB)
  2183. {
  2184. nt->alignment = buffer[pos];
  2185. ++pos;
  2186. }
  2187. else
  2188. {
  2189. nt->alignment = 0xff;
  2190. }
  2191. pos += 3;
  2192. nt->builded = 0;
  2193. nt->destroyed = 0;
  2194. nt->garrisonHero = nullptr;
  2195. return nt;
  2196. }
  2197. std::set<si32> CMapLoaderH3M::convertBuildings(const std::set<si32> h3m, int castleID, bool addAuxiliary /*= true*/)
  2198. {
  2199. std::map<int, int> mapa;
  2200. std::set<si32> ret;
  2201. // Note: this file is parsed many times.
  2202. const JsonNode config(ResourceID("config/buildings5.json"));
  2203. BOOST_FOREACH(const JsonNode & entry, config["table"].Vector())
  2204. {
  2205. int town = entry["town"].Float();
  2206. if (town == castleID || town == -1)
  2207. {
  2208. mapa[entry["h3"].Float()] = entry["vcmi"].Float();
  2209. }
  2210. }
  2211. for(auto i = h3m.begin(); i != h3m.end(); ++i)
  2212. {
  2213. if(mapa[*i] >= 0)
  2214. {
  2215. ret.insert(mapa[*i]);
  2216. }
  2217. // horde buildings
  2218. else if(mapa[*i] >= (-GameConstants::CREATURES_PER_TOWN))
  2219. {
  2220. int level = (mapa[*i]);
  2221. //(-30)..(-36) - horde buildings (for game loading only), don't see other way to handle hordes in random towns
  2222. ret.insert(level - 30);
  2223. }
  2224. else
  2225. {
  2226. tlog3 << "Conversion warning: unknown building " << *i << " in castle "
  2227. << castleID << std::endl;
  2228. }
  2229. }
  2230. if(addAuxiliary)
  2231. {
  2232. //village hall is always present
  2233. ret.insert(EBuilding::VILLAGE_HALL);
  2234. }
  2235. if(ret.find(EBuilding::CITY_HALL) != ret.end())
  2236. {
  2237. ret.insert(EBuilding::EXTRA_CITY_HALL);
  2238. }
  2239. if(ret.find(EBuilding::TOWN_HALL) != ret.end())
  2240. {
  2241. ret.insert(EBuilding::EXTRA_TOWN_HALL);
  2242. }
  2243. if(ret.find(EBuilding::CAPITOL) != ret.end())
  2244. {
  2245. ret.insert(EBuilding::EXTRA_CAPITOL);
  2246. }
  2247. return ret;
  2248. }
  2249. void CMapLoaderH3M::readEvents()
  2250. {
  2251. int numberOfEvents = read_le_u32(buffer + pos);
  2252. pos += 4;
  2253. for(int yyoo = 0; yyoo < numberOfEvents; ++yyoo)
  2254. {
  2255. CMapEvent * ne = new CMapEvent();
  2256. ne->name = std::string();
  2257. ne->message = std::string();
  2258. int nameLen = read_le_u32(buffer + pos);
  2259. pos += 4;
  2260. for(int qq = 0; qq < nameLen; ++qq)
  2261. {
  2262. ne->name += buffer[pos];
  2263. ++pos;
  2264. }
  2265. int messLen = read_le_u32(buffer + pos);
  2266. pos += 4;
  2267. for(int qq = 0; qq < messLen; ++qq)
  2268. {
  2269. ne->message +=buffer[pos];
  2270. ++pos;
  2271. }
  2272. for(int k = 0; k < 7; ++k)
  2273. {
  2274. ne->resources[k] = read_le_u32(buffer + pos);
  2275. pos += 4;
  2276. }
  2277. ne->players = buffer[pos];
  2278. ++pos;
  2279. if(map->version > EMapFormat::AB)
  2280. {
  2281. ne->humanAffected = buffer[pos];
  2282. ++pos;
  2283. }
  2284. else
  2285. {
  2286. ne->humanAffected = true;
  2287. }
  2288. ne->computerAffected = buffer[pos];
  2289. ++pos;
  2290. ne->firstOccurence = read_le_u16(buffer + pos);
  2291. pos += 2;
  2292. ne->nextOccurence = buffer[pos];
  2293. ++pos;
  2294. char unknown[17];
  2295. memcpy(unknown, buffer + pos, 17);
  2296. pos += 17;
  2297. map->events.push_back(ne);
  2298. }
  2299. }
  2300. void CMapLoaderH3M::addBlockVisibleTiles(CGObjectInstance * obj)
  2301. {
  2302. for(int fx = 0; fx < 8; ++fx)
  2303. {
  2304. for(int fy = 0; fy < 6; ++fy)
  2305. {
  2306. int xVal = obj->pos.x + fx - 7;
  2307. int yVal = obj->pos.y + fy - 5;
  2308. int zVal = obj->pos.z;
  2309. if(xVal >= 0 && xVal < map->width && yVal >= 0 && yVal < map->height)
  2310. {
  2311. TerrainTile & curt = map->terrain[xVal][yVal][zVal];
  2312. if(((obj->defInfo->visitMap[fy] >> (7 - fx)) & 1))
  2313. {
  2314. curt.visitableObjects.push_back(obj);
  2315. curt.visitable = true;
  2316. }
  2317. if(!((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1))
  2318. {
  2319. curt.blockingObjects.push_back(obj);
  2320. curt.blocked = true;
  2321. }
  2322. }
  2323. }
  2324. }
  2325. }
  2326. ui8 CMapLoaderH3M::reverse(ui8 arg)
  2327. {
  2328. ui8 ret = 0;
  2329. for(int i = 0; i < 8; ++i)
  2330. {
  2331. if((arg & (1 << i)) >> i)
  2332. {
  2333. ret |= (128 >> i);
  2334. }
  2335. }
  2336. return ret;
  2337. }