mapHandler.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. /*
  2. * mapHandler.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 "mapHandler.h"
  12. #include "MapRendererContext.h"
  13. #include "MapView.h"
  14. #include "../render/CAnimation.h"
  15. #include "../render/CFadeAnimation.h"
  16. #include "../render/Colors.h"
  17. #include "../gui/CGuiHandler.h"
  18. #include "../renderSDL/SDL_Extensions.h"
  19. #include "../CGameInfo.h"
  20. #include "../render/Graphics.h"
  21. #include "../render/IImage.h"
  22. #include "../render/Canvas.h"
  23. #include "../CMusicHandler.h"
  24. #include "../CPlayerInterface.h"
  25. #include "../../CCallback.h"
  26. #include "../../lib/mapObjects/CGHeroInstance.h"
  27. #include "../../lib/mapObjects/CObjectClassesHandler.h"
  28. #include "../../lib/mapping/CMap.h"
  29. #include "../../lib/Color.h"
  30. #include "../../lib/CConfigHandler.h"
  31. #include "../../lib/CGeneralTextHandler.h"
  32. #include "../../lib/CStopWatch.h"
  33. #include "../../lib/CRandomGenerator.h"
  34. #include "../../lib/RoadHandler.h"
  35. #include "../../lib/RiverHandler.h"
  36. #include "../../lib/TerrainHandler.h"
  37. /*
  38. std::shared_ptr<IImage> CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const
  39. {
  40. int ownerIndex = 0;
  41. if(owner < PlayerColor::PLAYER_LIMIT)
  42. {
  43. ownerIndex = owner.getNum() * 19;
  44. }
  45. else if (owner == PlayerColor::NEUTRAL)
  46. {
  47. ownerIndex = PlayerColor::PLAYER_LIMIT.getNum() * 19;
  48. }
  49. switch(id)
  50. {
  51. case Obj::MONOLITH_ONE_WAY_ENTRANCE:
  52. case Obj::MONOLITH_ONE_WAY_EXIT:
  53. case Obj::MONOLITH_TWO_WAY:
  54. return info->icons->getImage((int)EWorldViewIcon::TELEPORT);
  55. case Obj::SUBTERRANEAN_GATE:
  56. return info->icons->getImage((int)EWorldViewIcon::GATE);
  57. case Obj::ARTIFACT:
  58. return info->icons->getImage((int)EWorldViewIcon::ARTIFACT);
  59. case Obj::TOWN:
  60. return info->icons->getImage((int)EWorldViewIcon::TOWN + ownerIndex);
  61. case Obj::HERO:
  62. return info->icons->getImage((int)EWorldViewIcon::HERO + ownerIndex);
  63. case Obj::MINE:
  64. return info->icons->getImage((int)EWorldViewIcon::MINE_WOOD + subId + ownerIndex);
  65. case Obj::RESOURCE:
  66. return info->icons->getImage((int)EWorldViewIcon::RES_WOOD + subId + ownerIndex);
  67. }
  68. return std::shared_ptr<IImage>();
  69. }
  70. */
  71. /*
  72. void CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
  73. {
  74. auto drawIcon = [this,targetSurf](Obj id, si32 subId, PlayerColor owner)
  75. {
  76. auto wvIcon = this->objectToIcon(id, subId, owner);
  77. if(nullptr != wvIcon)
  78. {
  79. // centering icon on the object
  80. Point dest(realPos.x + tileSize / 2 - wvIcon->width() / 2, realPos.y + tileSize / 2 - wvIcon->height() / 2);
  81. wvIcon->draw(targetSurf, dest.x, dest.y);
  82. }
  83. };
  84. auto & objects = tile.objects;
  85. for(auto & object : objects)
  86. {
  87. const CGObjectInstance * obj = object.obj;
  88. if(!obj)
  89. continue;
  90. const bool sameLevel = obj->pos.z == pos.z;
  91. //FIXME: Don't read options in a loop :v
  92. const bool isVisible = settings["session"]["spectate"].Bool() ? true : (*info->visibilityMap)[pos.z][pos.x][pos.y];
  93. const bool isVisitable = obj->visitableAt(pos.x, pos.y);
  94. if(sameLevel && isVisible && isVisitable)
  95. drawIcon(obj->ID, obj->subID, obj->tempOwner);
  96. }
  97. }
  98. */
  99. /*
  100. void CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf)
  101. {
  102. if(nullptr == info->additionalIcons)
  103. return;
  104. const int3 bottomRight = pos + tileCount;
  105. for(const ObjectPosInfo & iconInfo : *(info->additionalIcons))
  106. {
  107. if( iconInfo.pos.z != pos.z)
  108. continue;
  109. if((iconInfo.pos.x < topTile.x) || (iconInfo.pos.y < topTile.y))
  110. continue;
  111. if((iconInfo.pos.x > bottomRight.x) || (iconInfo.pos.y > bottomRight.y))
  112. continue;
  113. realPos.x = initPos.x + (iconInfo.pos.x - topTile.x) * tileSize;
  114. realPos.y = initPos.y + (iconInfo.pos.y - topTile.y) * tileSize;
  115. auto wvIcon = this->objectToIcon(iconInfo.id, iconInfo.subId, iconInfo.owner);
  116. if(nullptr != wvIcon)
  117. {
  118. // centering icon on the object
  119. Point dest(realPos.x + tileSize / 2 - wvIcon->width() / 2, realPos.y + tileSize / 2 - wvIcon->height() / 2);
  120. wvIcon->draw(targetSurf, dest.x, dest.y);
  121. }
  122. }
  123. }
  124. */
  125. /*
  126. void CMapPuzzleViewBlitter::drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
  127. {
  128. CMapBlitter::drawObjects(targetSurf, tile);
  129. // grail X mark
  130. if(pos.x == info->grailPos.x && pos.y == info->grailPos.y)
  131. {
  132. const auto mark = graphics->heroMoveArrows->getImage(0);
  133. mark->draw(targetSurf,realTileRect.x,realTileRect.y);
  134. }
  135. }
  136. */
  137. /*
  138. void CMapPuzzleViewBlitter::postProcessing(SDL_Surface * targetSurf) const
  139. {
  140. CSDL_Ext::applyEffect(targetSurf, info->drawBounds, static_cast<int>(!ADVOPT.puzzleSepia));
  141. }
  142. */
  143. /*
  144. bool CMapPuzzleViewBlitter::canDrawObject(const CGObjectInstance * obj) const
  145. {
  146. if (!CMapBlitter::canDrawObject(obj))
  147. return false;
  148. //don't print flaggable objects in puzzle mode
  149. if (obj->isVisitable())
  150. return false;
  151. if(std::find(unblittableObjects.begin(), unblittableObjects.end(), obj->ID) != unblittableObjects.end())
  152. return false;
  153. return true;
  154. }
  155. */
  156. /*
  157. CMapPuzzleViewBlitter::CMapPuzzleViewBlitter(CMapHandler * parent)
  158. : CMapNormalBlitter(parent)
  159. {
  160. unblittableObjects.push_back(Obj::HOLE);
  161. }
  162. */
  163. /*
  164. void CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingInfo * info)
  165. {
  166. init(info);
  167. auto prevClip = clip(targetSurf);
  168. pos = int3(0, 0, topTile.z);
  169. for (realPos.x = initPos.x, pos.x = topTile.x; pos.x < topTile.x + tileCount.x; pos.x++, realPos.x += tileSize)
  170. {
  171. if (pos.x < 0 || pos.x >= parent->sizes.x)
  172. continue;
  173. for (realPos.y = initPos.y, pos.y = topTile.y; pos.y < topTile.y + tileCount.y; pos.y++, realPos.y += tileSize)
  174. {
  175. if (pos.y < 0 || pos.y >= parent->sizes.y)
  176. continue;
  177. const bool isVisible = canDrawCurrentTile();
  178. realTileRect.x = realPos.x;
  179. realTileRect.y = realPos.y;
  180. const TerrainTile2 & tile = parent->ttiles[pos.z][pos.x][pos.y];
  181. const TerrainTile & tinfo = parent->map->getTile(pos);
  182. const TerrainTile * tinfoUpper = pos.y > 0 ? &parent->map->getTile(int3(pos.x, pos.y - 1, pos.z)) : nullptr;
  183. if(isVisible || info->showAllTerrain)
  184. {
  185. drawTileTerrain(targetSurf, tinfo, tile);
  186. if(tinfo.riverType->getId() != River::NO_RIVER)
  187. drawRiver(targetSurf, tinfo);
  188. drawRoad(targetSurf, tinfo, tinfoUpper);
  189. }
  190. if(isVisible)
  191. drawObjects(targetSurf, tile);
  192. }
  193. }
  194. for (realPos.x = initPos.x, pos.x = topTile.x; pos.x < topTile.x + tileCount.x; pos.x++, realPos.x += tileSize)
  195. {
  196. for (realPos.y = initPos.y, pos.y = topTile.y; pos.y < topTile.y + tileCount.y; pos.y++, realPos.y += tileSize)
  197. {
  198. realTileRect.x = realPos.x;
  199. realTileRect.y = realPos.y;
  200. if (pos.x < 0 || pos.x >= parent->sizes.x ||
  201. pos.y < 0 || pos.y >= parent->sizes.y)
  202. {
  203. drawFrame(targetSurf);
  204. }
  205. else
  206. {
  207. const TerrainTile2 & tile = parent->ttiles[pos.z][pos.x][pos.y];
  208. if(!settings["session"]["spectate"].Bool() && !(*info->visibilityMap)[topTile.z][pos.x][pos.y] && !info->showAllTerrain)
  209. drawFow(targetSurf);
  210. // overlay needs to be drawn over fow, because of artifacts-aura-like spells
  211. drawTileOverlay(targetSurf, tile);
  212. // drawDebugVisitables()
  213. if (settings["session"]["showBlock"].Bool())
  214. {
  215. if(parent->map->getTile(int3(pos.x, pos.y, pos.z)).blocked) //temporary hiding blocked positions
  216. {
  217. static std::shared_ptr<IImage> block;
  218. if (!block)
  219. block = IImage::createFromFile("blocked");
  220. block->draw(targetSurf, realTileRect.x, realTileRect.y);
  221. }
  222. }
  223. if (settings["session"]["showVisit"].Bool())
  224. {
  225. if(parent->map->getTile(int3(pos.x, pos.y, pos.z)).visitable) //temporary hiding visitable positions
  226. {
  227. static std::shared_ptr<IImage> visit;
  228. if (!visit)
  229. visit = IImage::createFromFile("visitable");
  230. visit->draw(targetSurf, realTileRect.x, realTileRect.y);
  231. }
  232. }
  233. }
  234. }
  235. }
  236. drawOverlayEx(targetSurf);
  237. // drawDebugGrid()
  238. if (settings["gameTweaks"]["showGrid"].Bool())
  239. {
  240. for (realPos.x = initPos.x, pos.x = topTile.x; pos.x < topTile.x + tileCount.x; pos.x++, realPos.x += tileSize)
  241. {
  242. for (realPos.y = initPos.y, pos.y = topTile.y; pos.y < topTile.y + tileCount.y; pos.y++, realPos.y += tileSize)
  243. {
  244. constexpr ColorRGBA color(0x55, 0x55, 0x55);
  245. if (realPos.y >= info->drawBounds.y &&
  246. realPos.y < info->drawBounds.y + info->drawBounds.h)
  247. for(int i = 0; i < tileSize; i++)
  248. if (realPos.x + i >= info->drawBounds.x &&
  249. realPos.x + i < info->drawBounds.x + info->drawBounds.w)
  250. CSDL_Ext::putPixelWithoutRefresh(targetSurf, realPos.x + i, realPos.y, color.r, color.g, color.b);
  251. if (realPos.x >= info->drawBounds.x &&
  252. realPos.x < info->drawBounds.x + info->drawBounds.w)
  253. for(int i = 0; i < tileSize; i++)
  254. if (realPos.y + i >= info->drawBounds.y &&
  255. realPos.y + i < info->drawBounds.y + info->drawBounds.h)
  256. CSDL_Ext::putPixelWithoutRefresh(targetSurf, realPos.x, realPos.y + i, color.r, color.g, color.b);
  257. }
  258. }
  259. }
  260. postProcessing(targetSurf);
  261. CSDL_Ext::setClipRect(targetSurf, prevClip);
  262. }
  263. */
  264. /*
  265. bool CMapHandler::updateObjectsFade()
  266. {
  267. for (auto iter = fadeAnims.begin(); iter != fadeAnims.end(); )
  268. {
  269. int3 pos = (*iter).second.first;
  270. CFadeAnimation * anim = (*iter).second.second;
  271. anim->update();
  272. if (anim->isFading())
  273. ++iter;
  274. else // fade finished
  275. {
  276. auto &objs = ttiles[pos.z][pos.x][pos.y].objects;
  277. for (auto objIter = objs.begin(); objIter != objs.end(); ++objIter)
  278. {
  279. if ((*objIter).fadeAnimKey == (*iter).first)
  280. {
  281. logAnim->trace("Fade anim finished for obj at %s; remaining: %d", pos.toString(), fadeAnims.size() - 1);
  282. if (anim->fadingMode == CFadeAnimation::EMode::OUT)
  283. objs.erase(objIter); // if this was fadeout, remove the object from the map
  284. else
  285. (*objIter).fadeAnimKey = -1; // for fadein, just remove its connection to the finished fade
  286. break;
  287. }
  288. }
  289. delete (*iter).second.second;
  290. iter = fadeAnims.erase(iter);
  291. }
  292. }
  293. return !fadeAnims.empty();
  294. }
  295. */
  296. /*
  297. bool CMapHandler::startObjectFade(TerrainTileObject & obj, bool in, int3 pos)
  298. {
  299. SDL_Surface * fadeBitmap;
  300. assert(obj.obj);
  301. auto objData = normalBlitter->findObjectBitmap(obj.obj, 0);
  302. if (objData.objBitmap)
  303. {
  304. if (objData.isMoving) // ignore fading of moving objects (for now?)
  305. {
  306. logAnim->debug("Ignoring fade of moving object");
  307. return false;
  308. }
  309. fadeBitmap = CSDL_Ext::newSurface(32, 32); // TODO cache these bitmaps instead of creating new ones?
  310. Rect objSrcRect(obj.rect.x, obj.rect.y, 32, 32);
  311. objData.objBitmap->draw(fadeBitmap,0,0,&objSrcRect);
  312. if (objData.flagBitmap)
  313. {
  314. if (obj.obj->pos.x - 1 == pos.x && obj.obj->pos.y - 1 == pos.y) // -1 to draw flag in top-center instead of right-bottom; kind of a hack
  315. {
  316. Rect flagSrcRect(32, 0, 32, 32);
  317. objData.flagBitmap->draw(fadeBitmap,0,0, &flagSrcRect);
  318. }
  319. }
  320. auto anim = new CFadeAnimation();
  321. anim->init(in ? CFadeAnimation::EMode::IN : CFadeAnimation::EMode::OUT, fadeBitmap, true);
  322. fadeAnims[++fadeAnimCounter] = std::pair<int3, CFadeAnimation*>(pos, anim);
  323. obj.fadeAnimKey = fadeAnimCounter;
  324. logAnim->trace("Fade anim started for obj %d at %s; anim count: %d", obj.obj->ID, pos.toString(), fadeAnims.size());
  325. return true;
  326. }
  327. return false;
  328. }
  329. */
  330. /*
  331. bool CMapHandler::printObject(const CGObjectInstance * obj, bool fadein)
  332. {
  333. auto animation = graphics->getAnimation(obj);
  334. if(!animation)
  335. return false;
  336. auto bitmap = animation->getImage(0);
  337. if(!bitmap)
  338. return false;
  339. const int tilesW = bitmap->width()/32;
  340. const int tilesH = bitmap->height()/32;
  341. auto ttilesWidth = ttiles.shape()[1];
  342. auto ttilesHeight = ttiles.shape()[2];
  343. for(int fx=0; fx<tilesW; ++fx)
  344. {
  345. for(int fy=0; fy<tilesH; ++fy)
  346. {
  347. Rect cr;
  348. cr.w = 32;
  349. cr.h = 32;
  350. cr.x = fx*32;
  351. cr.y = fy*32;
  352. if((obj->pos.x + fx - tilesW + 1) >= 0 &&
  353. (obj->pos.x + fx - tilesW + 1) < ttilesWidth - frameW &&
  354. (obj->pos.y + fy - tilesH + 1) >= 0 &&
  355. (obj->pos.y + fy - tilesH + 1) < ttilesHeight - frameH)
  356. {
  357. int3 pos(obj->pos.x + fx - tilesW + 1, obj->pos.y + fy - tilesH + 1, obj->pos.z);
  358. TerrainTile2 & curt = ttiles[pos.z][pos.x][pos.y];
  359. TerrainTileObject toAdd(obj, cr, obj->visitableAt(pos.x, pos.y));
  360. if (fadein && ADVOPT.objectFading)
  361. {
  362. startObjectFade(toAdd, true, pos);
  363. }
  364. auto i = curt.objects.begin();
  365. for(; i != curt.objects.end(); i++)
  366. {
  367. if(objectBlitOrderSorter(toAdd, *i))
  368. {
  369. curt.objects.insert(i, toAdd);
  370. i = curt.objects.begin(); //to validate and avoid adding it second time
  371. break;
  372. }
  373. }
  374. if(i == curt.objects.end())
  375. curt.objects.insert(i, toAdd);
  376. }
  377. }
  378. }
  379. return true;
  380. }
  381. */
  382. /*
  383. bool CMapHandler::hideObject(const CGObjectInstance * obj, bool fadeout)
  384. {
  385. for(size_t z = 0; z < map->levels(); z++)
  386. {
  387. for(size_t x = 0; x < map->width; x++)
  388. {
  389. for(size_t y = 0; y < map->height; y++)
  390. {
  391. auto &objs = ttiles[(int)z][(int)x][(int)y].objects;
  392. for(size_t i = 0; i < objs.size(); i++)
  393. {
  394. if (objs[i].obj && objs[i].obj->id == obj->id)
  395. {
  396. if (fadeout && ADVOPT.objectFading) // object should be faded == erase is delayed until the end of fadeout
  397. {
  398. if (startObjectFade(objs[i], false, int3((si32)x, (si32)y, (si32)z)))
  399. objs[i].obj = nullptr;
  400. else
  401. objs.erase(objs.begin() + i);
  402. }
  403. else
  404. objs.erase(objs.begin() + i);
  405. break;
  406. }
  407. }
  408. }
  409. }
  410. }
  411. return true;
  412. }
  413. */
  414. bool CMapHandler::hasActiveAnimations()
  415. {
  416. return false; // !fadeAnims.empty(); // don't allow movement during fade animation
  417. }
  418. /*
  419. void CMapHandler::updateWater() //shift colors in palettes of water tiles
  420. {
  421. for(auto & elem : terrainImages["lava"])
  422. {
  423. for(auto img : elem)
  424. img->shiftPalette(246, 9);
  425. }
  426. for(auto & elem : terrainImages["water"])
  427. {
  428. for(auto img : elem)
  429. {
  430. img->shiftPalette(229, 12);
  431. img->shiftPalette(242, 14);
  432. }
  433. }
  434. for(auto & elem : riverImages["clrrvr"])
  435. {
  436. for(auto img : elem)
  437. {
  438. img->shiftPalette(183, 12);
  439. img->shiftPalette(195, 6);
  440. }
  441. }
  442. for(auto & elem : riverImages["mudrvr"])
  443. {
  444. for(auto img : elem)
  445. {
  446. img->shiftPalette(228, 12);
  447. img->shiftPalette(183, 6);
  448. img->shiftPalette(240, 6);
  449. }
  450. }
  451. for(auto & elem : riverImages["lavrvr"])
  452. {
  453. for(auto img : elem)
  454. img->shiftPalette(240, 9);
  455. }
  456. }
  457. */
  458. bool CMapHandler::hasObjectHole(const int3 & pos) const
  459. {
  460. //const TerrainTile2 & tt = ttiles[pos.z][pos.x][pos.y];
  461. //for(auto & elem : tt.objects)
  462. //{
  463. // if(elem.obj && elem.obj->ID == Obj::HOLE)
  464. // return true;
  465. //}
  466. return false;
  467. }
  468. void CMapHandler::getTerrainDescr(const int3 & pos, std::string & out, bool isRMB) const
  469. {
  470. const TerrainTile & t = map->getTile(pos);
  471. if(t.hasFavorableWinds())
  472. {
  473. out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS, 0);
  474. return;
  475. }
  476. //const TerrainTile2 & tt = ttiles[pos.z][pos.x][pos.y];
  477. bool isTile2Terrain = false;
  478. out.clear();
  479. //for(auto & elem : tt.objects)
  480. //{
  481. // if(elem.obj)
  482. // {
  483. // out = elem.obj->getObjectName();
  484. // if(elem.obj->ID == Obj::HOLE)
  485. // return;
  486. // isTile2Terrain = elem.obj->isTile2Terrain();
  487. // break;
  488. // }
  489. //}
  490. if(!isTile2Terrain || out.empty())
  491. out = t.terType->getNameTranslated();
  492. if(t.getDiggingStatus(false) == EDiggingStatus::CAN_DIG)
  493. {
  494. out = boost::str(boost::format(isRMB ? "%s\r\n%s" : "%s %s") // New line for the Message Box, space for the Status Bar
  495. % out
  496. % CGI->generaltexth->allTexts[330]); // 'digging ok'
  497. }
  498. }
  499. bool CMapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b)
  500. {
  501. if (!a)
  502. return true;
  503. if (!b)
  504. return false;
  505. if (a->appearance->printPriority != b->appearance->printPriority)
  506. return a->appearance->printPriority > b->appearance->printPriority;
  507. if(a->pos.y != b->pos.y)
  508. return a->pos.y < b->pos.y;
  509. if(b->ID==Obj::HERO && a->ID!=Obj::HERO)
  510. return true;
  511. if(b->ID!=Obj::HERO && a->ID==Obj::HERO)
  512. return false;
  513. if(!a->isVisitable() && b->isVisitable())
  514. return true;
  515. if(!b->isVisitable() && a->isVisitable())
  516. return false;
  517. if(a->pos.x < b->pos.x)
  518. return true;
  519. return false;
  520. }
  521. TerrainTileObject::TerrainTileObject(const CGObjectInstance * obj_, Rect rect_, bool visitablePos)
  522. : obj(obj_),
  523. rect(rect_),
  524. fadeAnimKey(-1)
  525. {
  526. // We store information about ambient sound is here because object might disappear while sound is updating
  527. if(obj->getAmbientSound())
  528. {
  529. // All tiles of static objects are sound sources. E.g Volcanos and special terrains
  530. // For visitable object only their visitable tile is sound source
  531. if(!CCS->soundh->ambientCheckVisitable() || !obj->isVisitable() || visitablePos)
  532. ambientSound = obj->getAmbientSound();
  533. }
  534. }
  535. TerrainTileObject::~TerrainTileObject()
  536. {
  537. }
  538. CMapHandler::CMapHandler(const CMap * map)
  539. : map(map)
  540. {
  541. }
  542. const CMap * CMapHandler::getMap()
  543. {
  544. return map;
  545. }
  546. bool CMapHandler::isInMap( const int3 & tile)
  547. {
  548. return map->isInTheMap(tile);
  549. }
  550. std::vector<std::string> CMapHandler::getAmbientSounds(const int3 & tile)
  551. {
  552. std::vector<std::string> result;
  553. //for(auto & ttObj : ttiles[tile.z][tile.x][tile.y].objects)
  554. //{
  555. // if(ttObj.ambientSound)
  556. // result.push_back(ttObj.ambientSound.get());
  557. //}
  558. if(map->isCoastalTile(tile))
  559. result.emplace_back("LOOPOCEA");
  560. return result;
  561. }
  562. void CMapHandler::onObjectFadeIn(const CGObjectInstance * obj)
  563. {
  564. onObjectInstantAdd(obj);
  565. }
  566. void CMapHandler::onObjectFadeOut(const CGObjectInstance * obj)
  567. {
  568. onObjectInstantRemove(obj);
  569. }
  570. void CMapHandler::onObjectInstantAdd(const CGObjectInstance * obj)
  571. {
  572. MapRendererContext context;
  573. for (auto * observer : observers)
  574. observer->onObjectInstantAdd(context, obj);
  575. }
  576. void CMapHandler::onObjectInstantRemove(const CGObjectInstance * obj)
  577. {
  578. MapRendererContext context;
  579. for (auto * observer : observers)
  580. observer->onObjectInstantRemove(context, obj);
  581. }
  582. void CMapHandler::onHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  583. {
  584. assert(obj->pos == dest);
  585. onObjectInstantRemove(obj);
  586. onObjectInstantAdd(obj);
  587. }
  588. void CMapHandler::onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  589. {
  590. assert(obj->pos == dest);
  591. onObjectInstantRemove(obj);
  592. onObjectInstantAdd(obj);
  593. }
  594. void CMapHandler::onHeroRotated(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
  595. {
  596. //TODO
  597. }
  598. void CMapHandler::addMapObserver(IMapObjectObserver * object)
  599. {
  600. observers.push_back(object);
  601. }
  602. void CMapHandler::removeMapObserver(IMapObjectObserver * object)
  603. {
  604. vstd::erase(observers, object);
  605. }
  606. IMapObjectObserver::IMapObjectObserver()
  607. {
  608. CGI->mh->addMapObserver(this);
  609. }
  610. IMapObjectObserver::~IMapObjectObserver()
  611. {
  612. CGI->mh->removeMapObserver(this);
  613. }