2
0

MapFormatH3M.cpp 49 KB

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