CMapService.cpp 55 KB

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