MapData.h 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306
  1. /*
  2. FinalSun/FinalAlert 2 Mission Editor
  3. Copyright (C) 1999-2024 Electronic Arts, Inc.
  4. Authored by Matthias Wagner
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. */
  16. // Map->h: Interface for the class CMap.
  17. //
  18. // CMap holds all information for the current map
  19. //
  20. //////////////////////////////////////////////////////////////////////
  21. #include "structs.h"
  22. #include <vector>
  23. #include "variables.h"
  24. #include "macros.h"
  25. #include "ovrlinline.h"
  26. #include "Tube.h"
  27. extern TILEDATA** tiledata;
  28. extern DWORD* tiledata_count;
  29. extern ofstream errstream;
  30. extern map<int, int> tilesets_start;
  31. extern CIniFile* tiles;
  32. extern CFinalSunApp theApp;
  33. extern int shoreset;
  34. extern CIniFile rules;
  35. extern TILEDATA* un_tiledata;
  36. extern CIniFile g_data;
  37. extern int ramp2set;
  38. extern int pave2set;
  39. extern int ramp2set_start;
  40. extern int pave2set_start;
  41. extern int rampset_start;
  42. extern int rampset;
  43. #if !defined(AFX_MAP_H__9278CAC0_D4E7_11D3_B63B_444553540001__INCLUDED_)
  44. #define AFX_MAP_H__9278CAC0_D4E7_11D3_B63B_444553540001__INCLUDED_
  45. #include "IniFile.h" // Hinzugefügt von der Klassenansicht
  46. #if _MSC_VER > 1000
  47. #pragma once
  48. #endif // _MSC_VER > 1000
  49. #include <array>
  50. #define MAPDATA_UPDATE_FROM_INI 0
  51. #define MAPDATA_UPDATE_TO_INI 1
  52. #define MAPDATA_UPDATE_TO_INI_ALL 2
  53. #define MAPDATA_UPDATE_TO_INI_ALL_PREVIEW 4
  54. #define MAPDATA_UPDATE_TO_INI_ALL_COMPRESSED 8
  55. struct NODEDATA
  56. {
  57. NODEDATA();
  58. int type;
  59. int index;
  60. CString house;
  61. };
  62. // mapfielddata is the data of every field in an extracted isomappack!
  63. struct MAPFIELDDATA
  64. {
  65. unsigned short wX;
  66. unsigned short wY;
  67. WORD wGround;
  68. BYTE bData[3];
  69. BYTE bHeight;
  70. BYTE bData2[1];
  71. };
  72. #define MAPFIELDDATA_SIZE 11
  73. /*
  74. struct TILEDATA{};
  75. contains the information needed for one field of the map.
  76. */
  77. struct FIELDDATA
  78. {
  79. FIELDDATA();
  80. short unit; // unit number
  81. short infantry[SUBPOS_COUNT]; // infantry number
  82. short aircraft; // aircraft number
  83. short structure; // structure number
  84. short structuretype; // structure type id
  85. short terrain; // terrain number
  86. int terraintype; // terrain type id
  87. #ifdef SMUDGE_SUPP
  88. short smudge;
  89. int smudgetype;
  90. #endif
  91. short waypoint; // waypoint number
  92. NODEDATA node; // node info
  93. BYTE overlay; // overlay number
  94. BYTE overlaydata; // overlay data info
  95. WORD wGround; // ground type (tile)
  96. WORD bMapData; // add. data
  97. BYTE bSubTile;
  98. BYTE bHeight; // height of tile
  99. BYTE bMapData2; // add. data2
  100. short celltag; // celltag uses
  101. //std::uint16_t wTubeId; // tube ID
  102. //char cTubePart; // 0 is start, 1 is exit, and 2-101 are tube parts
  103. unsigned bReserved : 1; // for program usage
  104. unsigned bHide : 1;
  105. unsigned bRedrawTerrain : 1; // force redraw
  106. unsigned bCliffHack : 1;
  107. unsigned bRNDImage : 4; // for using a,b,c of tmp tiles
  108. };
  109. struct SNAPSHOTDATA
  110. {
  111. SNAPSHOTDATA();
  112. int left;
  113. int top;
  114. int bottom;
  115. int right;
  116. BOOL* bRedrawTerrain;
  117. BYTE* overlay;
  118. BYTE* overlaydata;
  119. WORD* wGround;
  120. WORD* bMapData;
  121. BYTE* bSubTile;
  122. BYTE* bHeight;
  123. BYTE* bMapData2;
  124. BYTE* bRNDData;
  125. //CIniFile mapfile;
  126. };
  127. class CMapData
  128. {
  129. public:
  130. BOOL m_noAutoObjectUpdate;
  131. void SetFielddataAt(DWORD dwPos, FIELDDATA* lpFd)
  132. {
  133. if (dwPos >= fielddata_size) return;
  134. RemoveOvrlMoney(fielddata[dwPos].overlay, fielddata[dwPos].overlaydata);
  135. fielddata[dwPos] = (*lpFd);
  136. AddOvrlMoney(fielddata[dwPos].overlay, fielddata[dwPos].overlaydata);
  137. };
  138. DWORD GetMapPos(int mapX, int mapY) const
  139. {
  140. return mapX + mapY * m_IsoSize;
  141. }
  142. DWORD GetMapPos(const MapCoords& coords) const
  143. {
  144. return coords.x + coords.y * m_IsoSize;
  145. }
  146. bool hasLat(WORD wTileSet) const;
  147. void HideField(DWORD dwPos, BOOL bHide);
  148. void SetReserved(DWORD dwPos, BYTE val);
  149. DWORD GetTileID(DWORD dwTileSet, int iTile);
  150. int GetNecessarySlope(DWORD dwPos);
  151. void CreateSlopesAt(DWORD dwPos)
  152. {
  153. //OutputDebugString("CreateSlopes()\n");
  154. FIELDDATA m = *GetFielddataAt(dwPos);
  155. if (m.wGround == 0xFFFF) m.wGround = 0;
  156. TILEDATA& d = (*tiledata)[m.wGround];
  157. int ns = -1;
  158. int i, e, p = 0;
  159. int h[3][3];
  160. for (i = 0;i < 3; i++)
  161. {
  162. for (e = 0;e < 3;e++)
  163. {
  164. int pos = dwPos + (i - 1) + (e - 1) * m_IsoSize;
  165. if (pos < 0 || pos >= m_IsoSize * m_IsoSize)
  166. {
  167. h[i][e] = 0;
  168. }
  169. else
  170. {
  171. FIELDDATA m2 = *GetFielddataAt(pos);
  172. h[i][e] = m.bHeight - m2.bHeight;
  173. }
  174. }
  175. }
  176. // check if the current tile must be heightened anyway
  177. if (!theApp.m_Options.bDisableSlopeCorrection && d.bMorphable)
  178. {
  179. if ((h[0][1] < 0 && h[2][1] < 0) || (h[1][0] < 0 && h[1][2] < 0)
  180. || (h[1][0] < 0 && h[0][2] < 0 && h[0][1] >= 0)
  181. || (h[1][0] < 0 && h[2][2] < 0 && h[2][1] >= 0)
  182. || (h[0][1] < 0 && h[2][0] < 0 && h[1][0] >= 0)
  183. || (h[0][1] < 0 && h[2][2] < 0 && h[1][2] >= 0)
  184. || (h[1][2] < 0 && h[0][0] < 0 && h[0][1] >= 0)
  185. || (h[1][2] < 0 && h[2][0] < 0 && h[2][1] >= 0)
  186. || (h[2][1] < 0 && h[0][0] < 0 && h[1][0] >= 0)
  187. || (h[2][1] < 0 && h[0][2] < 0 && h[1][2] >= 0)
  188. || (h[1][0] < 0 && h[0][1] < 0 && h[0][0] >= 0)
  189. || (h[0][1] < 0 && h[1][2] < 0 && h[0][2] >= 0)
  190. || (h[1][2] < 0 && h[2][1] < 0 && h[2][2] >= 0)
  191. || (h[2][1] < 0 && h[1][0] < 0 && h[2][0] >= 0)
  192. )
  193. {
  194. SetHeightAt(dwPos, m.bHeight + 1);
  195. for (i = -1;i < 2;i++)
  196. for (e = -1;e < 2;e++)
  197. CreateSlopesAt(dwPos + i + e * m_IsoSize);
  198. return;
  199. }
  200. }
  201. BOOL checkOtherSlopes = FALSE;
  202. if (h[0][0] == -1 && h[2][2] == -1 && h[2][0] >= 0 && h[0][2] >= 0 && h[1][0] >= 0 && h[1][2] >= 0 && h[0][1] >= 0 && h[2][1] >= 0) ns = SLOPE_UP_LEFTTOP_AND_RIGHTBOTTOM;
  203. if (h[0][2] == -1 && h[2][0] == -1 && h[0][0] >= 0 && h[2][2] >= 0 && h[0][1] >= 0 && h[1][0] >= 0 && h[1][2] >= 0 && h[2][1] >= 0) ns = SLOPE_UP_LEFTBOTTOM_AND_RIGHTTOP;
  204. if (ns == -1)
  205. if (h[1][0] == -1 && h[0][1] != -1 && h[1][2] != -1 && h[2][1] != -1)
  206. {
  207. ns = SLOPE_UP_LEFT;
  208. }
  209. else if (h[0][1] == -1 && h[1][0] != -1 && h[2][1] != -1 && h[1][2] != -1)
  210. {
  211. ns = SLOPE_UP_TOP;
  212. }
  213. else if (h[1][2] == -1 && h[0][1] != -1 && h[1][0] != -1 && h[2][1] != -1)
  214. {
  215. ns = SLOPE_UP_RIGHT;
  216. }
  217. else if (h[2][1] == -1 && h[0][1] != -1 && h[1][0] != -1 && h[1][2] != -1)
  218. {
  219. ns = SLOPE_UP_BOTTOM;
  220. }
  221. if (ns == -1)
  222. {
  223. if (h[0][0] == -2) ns = SLOPE_DOWN_BOTTOM;
  224. if (h[2][0] == -2) ns = SLOPE_DOWN_RIGHT;
  225. if (h[0][2] == -2) ns = SLOPE_DOWN_LEFT;
  226. if (h[2][2] == -2) ns = SLOPE_DOWN_TOP;
  227. }
  228. if (ns == -1 && h[0][0] == -1)
  229. {
  230. if (h[1][0] == -1 && h[0][1] == -1) ns = SLOPE_DOWN_RIGHTBOTTOM;
  231. else if (h[1][0] == 0 && h[0][1] == 0) ns = SLOPE_UP_LEFTTOP;
  232. //else if(h[2][2]==1) ns=SLOPE_DOWN_BOTTOM;
  233. }
  234. if (ns == -1 && h[2][0] == -1)
  235. {
  236. if (h[1][0] == -1 && h[2][1] == -1) ns = SLOPE_DOWN_RIGHTTOP;
  237. else if (h[1][0] == 0 && h[2][1] == 0) ns = SLOPE_UP_LEFTBOTTOM;
  238. //else if(h[0][2]==1) ns=SLOPE_DOWN_RIGHT;
  239. }
  240. if (ns == -1 && h[0][2] == -1)
  241. {
  242. if (h[1][2] == -1 && h[0][1] == -1) ns = SLOPE_DOWN_LEFTBOTTOM;
  243. else if (h[1][2] == 0 && h[0][1] == 0) ns = SLOPE_UP_RIGHTTOP;
  244. //else if(h[2][0]==1) ns=SLOPE_DOWN_LEFT;
  245. }
  246. if (ns == -1 && h[2][2] == -1)
  247. {
  248. if (h[1][2] == -1 && h[2][1] == -1) ns = SLOPE_DOWN_LEFTTOP;
  249. else if (h[1][2] == 0 && h[2][1] == 0) ns = SLOPE_UP_RIGHTBOTTOM;
  250. //else if(h[0][0]==1) ns=SLOPE_DOWN_TOP;
  251. }
  252. if (ns == -1 && h[1][0] == -1 && h[2][1] == -1) ns = SLOPE_DOWN_RIGHTTOP;
  253. if (ns == -1 && h[1][2] == -1 && h[2][1] == -1) ns = SLOPE_DOWN_LEFTTOP;
  254. if (ns == -1 && h[1][0] == -1 && h[0][1] == -1) ns = SLOPE_DOWN_RIGHTBOTTOM;
  255. if (ns == -1 && h[1][2] == -1 && h[0][1] == -1) ns = SLOPE_DOWN_LEFTBOTTOM;
  256. int rampbase = rampset_start;//atoi((*tiles).sections["General"].values["RampBase"]);
  257. int rampsmooth = atoi((*tiles).sections["General"].AccessValueByName("RampSmooth"));
  258. if (ns == -1 && (d.wTileSet == rampset || d.wTileSet == rampsmooth) && d.bMorphable)
  259. {
  260. SetTileAt(dwPos, 0, 0);
  261. }
  262. if (tiledata == &un_tiledata)
  263. {
  264. int r = ramp2set;
  265. int m = pave2set;
  266. if (ns == -1 && (d.wTileSet == r || d.wTileSet == m) && d.bMorphable)
  267. {
  268. SetTileAt(dwPos, pave2set_start/*GetTileID(m,0)*/, 0);
  269. }
  270. }
  271. if (d.bMorphable && ns != -1)
  272. {
  273. if (tiledata == &un_tiledata) // NEW URBAN FIX FOR URBAN PAVEMENT
  274. {
  275. //[NewUrbanInfo]
  276. //Morphable2=114
  277. //Ramps2=117
  278. int r = ramp2set;
  279. int m = pave2set;
  280. if (d.wTileSet == r || d.wTileSet == m)
  281. rampbase = ramp2set_start;
  282. }
  283. SetTileAt(dwPos, rampbase + ns - 1, 0);
  284. }
  285. }
  286. void CreateMap(DWORD dwWidth, DWORD dwHeight, LPCTSTR lpTerrainType, DWORD dwGroundHeight);
  287. BOOL SetTileAt(DWORD dwPos, DWORD dwID, DWORD dwTile)
  288. {
  289. if (dwPos > fielddata_size) return FALSE;
  290. int replacement = 0; // MW fix: ignore for bridges
  291. if ((*tiledata)[dwID].bReplacementCount && atoi((*tiles).sections["General"].AccessValueByName("BridgeSet")) != (*tiledata)[dwID].wTileSet)
  292. {
  293. replacement = rand() * (1 + (*tiledata)[dwID].bReplacementCount) / RAND_MAX;
  294. }
  295. fielddata[dwPos].wGround = dwID;
  296. fielddata[dwPos].bSubTile = dwTile;
  297. fielddata[dwPos].bRNDImage = replacement;
  298. int e;
  299. fielddata[dwPos].bRedrawTerrain = FALSE;
  300. int xx, yy;
  301. for (xx = -2;xx < 0;xx++)
  302. {
  303. for (yy = -2;yy < 0;yy++)
  304. {
  305. int npos = dwPos + xx + yy * m_IsoSize;
  306. if (npos > 0 && fielddata[dwPos].bHeight - fielddata[npos].bHeight >= 4)
  307. {
  308. fielddata[dwPos].bRedrawTerrain = TRUE;
  309. break;
  310. }
  311. }
  312. if (fielddata[dwPos].bRedrawTerrain) break;
  313. }
  314. Mini_UpdatePos(dwPos % m_IsoSize, dwPos / m_IsoSize, IsMultiplayer());
  315. return TRUE;
  316. }
  317. void SetHeightAt(DWORD dwPos, BYTE bHeight)
  318. {
  319. int height = (char)bHeight;
  320. if (height > MAXHEIGHT) height = MAXHEIGHT; // too high else
  321. if (height < 0) height = 0;
  322. if (dwPos < fielddata_size) fielddata[dwPos].bHeight = height;
  323. }
  324. int GetBuildingID(LPCSTR lpBuildingName);
  325. void ImportRUL(LPCTSTR lpFilename);
  326. void ExportRulesChanges(const char* filename);
  327. void DeleteRulesSections();
  328. DWORD GetWaypointCount() const;
  329. DWORD GetCelltagCount() const;
  330. WCHAR* GetUnitName(LPCTSTR lpID) const;
  331. DWORD GetTerrainCount() const;
  332. DWORD GetAircraftCount() const;
  333. DWORD GetStructureCount() const;
  334. DWORD GetUnitCount() const;
  335. DWORD GetInfantryCount() const;
  336. void GetStdUnitData(DWORD dwIndex, STDOBJECTDATA* lpStdUnit) const;
  337. void GetStdAircraftData(DWORD dwIndex, STDOBJECTDATA* lpStdAircraft) const;
  338. void GetWaypointData(DWORD dwIndex, CString* lpID, DWORD* lpdwPos) const;
  339. BOOL IsGroundObjectAt(DWORD dwPos) const;
  340. BOOL AddTerrain(LPCTSTR lpType, DWORD dwPos, int suggestedIndex = -1);
  341. void GetTerrainData(DWORD dwIndex, CString* lpType) const;
  342. void GetTerrainData(DWORD dwIndex, TERRAIN* lpTerrain) const;
  343. BOOL AddUnit(UNIT* lpUnit, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, CString suggestedID = "");
  344. BOOL AddAircraft(AIRCRAFT* lpAircraft, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, CString suggestedID = "");
  345. void GetCelltagData(DWORD dwIndex, CString* lpTag, DWORD* lpdwPos) const;
  346. BOOL AddCelltag(LPCTSTR lpTag, DWORD dwPos);
  347. void GetAircraftData(DWORD dwIndex, AIRCRAFT* lpAircraft) const;
  348. void GetUnitData(DWORD dwIndex, UNIT* lpUnit) const;
  349. void GetInfantryData(DWORD dwIndex, INFANTRY* lpInfantry) const;
  350. void GetStdInfantryData(DWORD dwIndex, STDOBJECTDATA* lpStdInfantry) const;
  351. INT GetUnitTypeID(LPCTSTR lpType);
  352. void InitializeUnitTypes();
  353. BOOL AddStructure(STRUCTURE* lpStructure, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, CString suggestedID = "");
  354. BOOL AddInfantry(INFANTRY* lpInfantry, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, int suggestedIndex = -1);
  355. BOOL AddNode(NODE* lpNode, WORD dwPos);
  356. void GetStdStructureData(DWORD dwIndex, STDOBJECTDATA* lpStdStructure) const;
  357. void GetStructureData(DWORD dwIndex, STRUCTURE* lpStructure) const;
  358. BOOL AddWaypoint(CString lpID, DWORD dwPos);
  359. void DeleteNode(LPCTSTR lpHouse, DWORD dwIndex);
  360. void DeleteTerrain(DWORD dwIndex);
  361. void DeleteAircraft(DWORD dwIndex);
  362. void DeleteStructure(DWORD dwIndex);
  363. void DeleteUnit(DWORD dwIndex);
  364. void DeleteCelltag(DWORD dwIndex);
  365. void DeleteWaypoint(DWORD dwIndex);
  366. void DeleteInfantry(DWORD dwIndex);
  367. INT GetCelltagAt(DWORD dwPos) const
  368. {
  369. return fielddata[dwPos].celltag;
  370. }
  371. INT GetCelltagAt(MapCoords pos) const
  372. {
  373. return GetCelltagAt(GetMapPos(pos));
  374. }
  375. INT GetWaypointAt(DWORD dwPos) const
  376. {
  377. return fielddata[dwPos].waypoint;
  378. }
  379. INT GetWaypointAt(MapCoords pos) const
  380. {
  381. return GetWaypointAt(GetMapPos(pos));
  382. }
  383. INT GetTerrainAt(DWORD dwPos) const
  384. {
  385. return fielddata[dwPos].terrain;
  386. }
  387. INT GetTerrainAt(MapCoords pos) const
  388. {
  389. return GetTerrainAt(GetMapPos(pos));
  390. }
  391. INT GetAirAt(DWORD dwPos) const
  392. {
  393. return fielddata[dwPos].aircraft;
  394. }
  395. INT GetAirAt(MapCoords pos) const
  396. {
  397. return GetAirAt(GetMapPos(pos));
  398. }
  399. INT GetStructureAt(DWORD dwPos) const
  400. {
  401. if (fielddata[dwPos].structure > -1) return fielddata[dwPos].structure; return -1;
  402. }
  403. INT GetStructureAt(MapCoords pos) const
  404. {
  405. return GetStructureAt(GetMapPos(pos));
  406. }
  407. INT GetUnitAt(DWORD dwPos) const
  408. {
  409. return fielddata[dwPos].unit;
  410. }
  411. INT GetUnitAt(MapCoords pos) const
  412. {
  413. return GetUnitAt(GetMapPos(pos));
  414. }
  415. INT GetInfantryAt(DWORD dwPos, DWORD dwSubPos = 0xFFFFFFFF) const
  416. {
  417. if (dwSubPos == 0xFFFFFFFF)
  418. {
  419. int i;
  420. for (i = 0;i < SUBPOS_COUNT;i++)
  421. if (fielddata[dwPos].infantry[i] != -1)
  422. return fielddata[dwPos].infantry[i];
  423. return -1;
  424. }
  425. return fielddata[dwPos].infantry[dwSubPos];
  426. }
  427. INT GetInfantryAt(MapCoords pos, DWORD dwSubPos = 0xFFFFFFFF)
  428. {
  429. return GetInfantryAt(GetMapPos(pos), dwSubPos);
  430. }
  431. INT GetNodeAt(DWORD dwPos, CString& lpHouse) const;
  432. INT GetNodeAt(MapCoords pos, CString& lpHouse) const
  433. {
  434. return GetNodeAt(GetMapPos(pos), lpHouse);
  435. }
  436. INT GetHeightAt(DWORD dwPos) const
  437. {
  438. return fielddata[dwPos].bHeight;
  439. }
  440. INT GetHeightAt(const MapCoords& coords) const
  441. {
  442. return GetHeightAt(GetMapPos(coords));
  443. }
  444. const FIELDDATA* GetFielddataAt(DWORD dwPos) const
  445. {
  446. if (dwPos >= fielddata_size)
  447. {
  448. outside_f.bReserved = 1;
  449. return &outside_f;
  450. }
  451. return &fielddata[dwPos];
  452. };
  453. FIELDDATA* GetFielddataAt(DWORD dwPos)
  454. {
  455. if (dwPos >= fielddata_size)
  456. {
  457. outside_f.bReserved = 1;
  458. return &outside_f;
  459. }
  460. return &fielddata[dwPos];
  461. };
  462. const FIELDDATA* GetFielddataAt(const MapCoords& pos) const
  463. {
  464. auto dwPos = GetMapPos(pos);
  465. if (dwPos >= fielddata_size)
  466. {
  467. outside_f.bReserved = 1;
  468. return &outside_f;
  469. }
  470. return &fielddata[dwPos];
  471. };
  472. FIELDDATA* GetFielddataAt(const MapCoords& pos)
  473. {
  474. auto dwPos = GetMapPos(pos);
  475. if (dwPos >= fielddata_size)
  476. {
  477. outside_f.bReserved = 1;
  478. return &outside_f;
  479. }
  480. return &fielddata[dwPos];
  481. };
  482. BYTE GetOverlayDataAt(DWORD dwPos);
  483. void SetOverlayDataAt(DWORD dwPos, BYTE bValue);
  484. BYTE GetOverlayAt(DWORD dwPos);
  485. void SetOverlayAt(DWORD dwPos, BYTE bValue);
  486. void ClearOverlay();
  487. void ClearOverlayData();
  488. const std::vector<std::unique_ptr<CTube>>& GetTubes() const
  489. {
  490. return m_tubes;
  491. }
  492. DWORD GetIsoSize() const
  493. {
  494. return m_IsoSize;
  495. }
  496. void LoadMap(const std::string& file);
  497. void UpdateIniFile(DWORD dwFlags = MAPDATA_UPDATE_TO_INI);
  498. CIniFile& GetIniFile();
  499. CString GetAITriggerTypeID(DWORD dwAITriggerType);
  500. DWORD GetAITriggerTypeIndex(LPCTSTR lpID);
  501. WORD GetHouseIndex(LPCTSTR lpHouse);
  502. void GetAITriggerType(DWORD dwAITriggerType, AITRIGGERTYPE* pAITrg);
  503. DWORD GetAITriggerTypeCount();
  504. CString GetHouseID(WORD wHouse, BOOL bCountry = FALSE);
  505. WORD GetHousesCount(BOOL bCountries = FALSE);
  506. WORD GetHeight() const
  507. {
  508. return m_maprect.bottom;
  509. };
  510. WORD GetWidth() const
  511. {
  512. return m_maprect.right;
  513. };
  514. BOOL IsRulesSection(LPCTSTR lpSection);
  515. CMapData();
  516. virtual ~CMapData();
  517. void Pack(BOOL bCreatePreview = FALSE, BOOL bCompression = FALSE);
  518. void Unpack();
  519. void UpdateTreeInfo(LPCSTR lpTreeType = NULL);
  520. void UpdateBuildingInfo(LPCSTR lpUnitType = NULL);
  521. void CalcMapRect();
  522. // MW change: UpdateStructures() public, so that houses dialog can access it
  523. void UpdateStructures(BOOL bSave = FALSE);
  524. MapCoords ToMapCoords(ProjectedCoords xy) const;
  525. MapCoords ToMapCoords3d(ProjectedCoords xy, int mapZ) const;
  526. MapCoords ToMapCoords3d(ProjectedCoords xy, bool bAllowAccessBehindCliffs=false, bool ignoreHideFlagsAndOutside=false) const;
  527. ProjectedCoords ProjectCoords(MapCoords xy) const;
  528. ProjectedCoords ProjectCoords3d(MapCoords xy) const;
  529. ProjectedCoords ProjectCoords3d(MapCoords xy, int z) const;
  530. bool isInside(MapCoords xy) const;
  531. __forceinline CPoint GetMiniMapPos(MapCoords mapCoords)
  532. {
  533. int x, y;
  534. GetMiniMapPos(mapCoords.x, mapCoords.y, x, y);
  535. return CPoint(static_cast<LONG>(x), static_cast<LONG>(y));
  536. }
  537. private:
  538. void UpdateTubes(BOOL bSave);
  539. MAPFIELDDATA* GetMappackPointer(DWORD dwPos);
  540. void UpdateMapFieldData(BOOL bSave = FALSE);
  541. DWORD m_IsoSize;
  542. mutable FIELDDATA outside_f;
  543. BOOL isInitialized;
  544. void UpdateCelltags(BOOL bSave = FALSE);
  545. void UpdateOverlay(BOOL bSave = FALSE);
  546. void UpdateNodes(BOOL bSave = FALSE);
  547. void UpdateWaypoints(BOOL bSave = FALSE);
  548. void UpdateUnits(BOOL bSave = FALSE);
  549. void UpdateTerrain(BOOL bSave = FALSE, int num = -1);
  550. void UpdateInfantry(BOOL bSave = FALSE);
  551. void UpdateAircraft(BOOL bSave = FALSE);
  552. map<CString, int> buildingid;
  553. map<CString, int> terrainid;
  554. #ifdef SMUDGE_SUPP
  555. map<CString, int> smudgeid;
  556. #endif
  557. BYTE m_Overlay[262144]; // overlay byte values (extracted)
  558. BYTE m_OverlayData[262144]; // overlay data byte values (extracted)
  559. BYTE* m_mfd; // map field data buffer
  560. DWORD dwIsoMapSize;
  561. CIniFile m_mapfile;
  562. RECT m_maprect;
  563. RECT m_vismaprect;
  564. FIELDDATA* fielddata;
  565. int fielddata_size;
  566. SNAPSHOTDATA* m_snapshots;
  567. DWORD dwSnapShotCount;
  568. int m_cursnapshot;
  569. int m_money;
  570. vector<STRUCTUREPAINT> m_structurepaint;
  571. protected:
  572. void InitMinimap();
  573. vector<std::unique_ptr<CTube>> m_tubes;
  574. // vectors for terrain, infantry, structures and units, as those need to be displayed very fast.
  575. // we don´t need them for aircraft right now, as there won´t be many aircrafts on the map anyway.
  576. #ifdef SMUDGE_SUPP
  577. vector<SMUDGE> m_smudges;
  578. #endif
  579. vector<TERRAIN> m_terrain;
  580. vector<INFANTRY> m_infantry;
  581. vector<UNIT> m_units;
  582. vector<STRUCTURE> m_structures;
  583. // we use a dib to draw the minimap
  584. std::vector<BYTE> m_mini_colors;
  585. BITMAPINFO m_mini_biinfo;
  586. int m_mini_pitch;
  587. enum OverlayCreditsType
  588. {
  589. OverlayCredits_Riparius = 0,
  590. OverlayCredits_Cruentus = 1,
  591. OverlayCredits_Vinifera = 2,
  592. OverlayCredits_Aboreus = 3,
  593. OverlayCredits_NumOf
  594. };
  595. std::array<int, OverlayCredits_NumOf> m_overlayCredits;
  596. __forceinline void RemoveOvrlMoney(unsigned char ovrl, unsigned char ovrld)
  597. {
  598. if (ovrl >= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END)
  599. {
  600. m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Riparius];
  601. }
  602. if (ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END)
  603. {
  604. m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Cruentus];
  605. }
  606. if (ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END)
  607. {
  608. m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Vinifera];
  609. }
  610. if (ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END)
  611. {
  612. m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Aboreus];
  613. }
  614. }
  615. __forceinline void AddOvrlMoney(unsigned char ovrl, unsigned char ovrld)
  616. {
  617. if (ovrl >= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END)
  618. {
  619. m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Riparius];
  620. }
  621. if (ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END)
  622. {
  623. m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Cruentus];
  624. }
  625. if (ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END)
  626. {
  627. m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Vinifera];
  628. }
  629. if (ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END)
  630. {
  631. m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Aboreus];
  632. }
  633. }
  634. __forceinline void GetMiniMapPos(int i, int e, int& x, int& y)
  635. {
  636. const int pheight = m_mini_biinfo.bmiHeader.biHeight;
  637. const DWORD dwIsoSize = m_IsoSize;
  638. y = e / 2 + i / 2;
  639. x = dwIsoSize - i + e;
  640. int tx, ty;
  641. tx = GetWidth();
  642. ty = GetHeight();
  643. ty = ty / 2 + tx / 2;
  644. tx = dwIsoSize - GetWidth() + GetHeight();
  645. x -= tx;
  646. y -= ty;
  647. x += pheight;
  648. y += pheight / 2;
  649. }
  650. __forceinline void Mini_UpdatePos(const int i, const int e, bool isMultiplayer)
  651. {
  652. const int pwidth = m_mini_biinfo.bmiHeader.biWidth;
  653. const int pheight = m_mini_biinfo.bmiHeader.biHeight;
  654. if (m_mini_colors.empty() || !tiledata)
  655. return;
  656. const DWORD dwIsoSize = m_IsoSize;
  657. const int pitch = m_mini_pitch;
  658. int x = 0;
  659. int y = 0;
  660. GetMiniMapPos(i, e, x, y);
  661. y = pheight - y - 1;
  662. int xiso = i;
  663. int yiso = e;
  664. if (xiso >= m_IsoSize)
  665. xiso = m_IsoSize - 1;
  666. if (yiso >= m_IsoSize)
  667. yiso = m_IsoSize - 1;
  668. if (xiso < 0)
  669. xiso = 0;
  670. if (yiso < 0)
  671. yiso = 0;
  672. DWORD dwPos = xiso + yiso * dwIsoSize;
  673. int dwDrawPos = (x * 3 + y * pitch);
  674. int size = pitch * pheight;
  675. if (dwDrawPos >= size || x >= pwidth || y >= pheight || x < 0 || y < 0) return;
  676. if (dwPos >= m_IsoSize * m_IsoSize) return;
  677. if (dwDrawPos + 3 >= m_mini_colors.size()) return;
  678. RGBTRIPLE& col = (RGBTRIPLE&)m_mini_colors[dwDrawPos];
  679. RGBTRIPLE& col_r = (RGBTRIPLE&)m_mini_colors[(dwDrawPos + sizeof(RGBTRIPLE)) < size ? dwDrawPos + sizeof(RGBTRIPLE) : dwDrawPos];
  680. FIELDDATA td;
  681. td = *GetFielddataAt(dwPos);
  682. STDOBJECTDATA sod;
  683. sod.house = "";
  684. int ic;
  685. for (ic = 0;ic < SUBPOS_COUNT;ic++)
  686. {
  687. if (td.infantry[ic] >= 0)
  688. {
  689. GetStdInfantryData(td.infantry[ic], &sod);
  690. }
  691. }
  692. if (td.structure >= 0)
  693. {
  694. GetStdStructureData(td.structure, &sod);
  695. }
  696. if (td.aircraft >= 0)
  697. {
  698. GetStdAircraftData(td.aircraft, &sod);
  699. }
  700. if (td.unit >= 0)
  701. {
  702. GetStdUnitData(td.unit, &sod);
  703. }
  704. int ground = (td.wGround >= (*tiledata_count)) ? 0 : td.wGround;
  705. int subt = td.bSubTile;
  706. int ttype = 0;
  707. if (subt < (*tiledata)[ground].wTileCount) ttype = (*tiledata)[ground].tiles[subt].bTerrainType;
  708. // mw added check:
  709. if (subt >= (*tiledata)[ground].wTileCount) return;
  710. RGBTRIPLE& l = (*tiledata)[ground].tiles[subt].rgbLeft;
  711. RGBTRIPLE& r = (*tiledata)[ground].tiles[subt].rgbRight;
  712. int pos = GetHeightAt(dwPos);
  713. col.rgbtBlue = l.rgbtBlue;
  714. col.rgbtGreen = l.rgbtGreen;
  715. col.rgbtRed = l.rgbtRed;
  716. col_r.rgbtBlue = r.rgbtBlue;
  717. col_r.rgbtGreen = r.rgbtGreen;
  718. col_r.rgbtRed = r.rgbtRed;
  719. if (isGreenTiberium(td.overlay))
  720. {
  721. #ifndef RA2_MODE
  722. col.rgbtBlue = 0;
  723. col.rgbtGreen = 200;
  724. col.rgbtRed = 0;
  725. col_r = col;
  726. #else
  727. col.rgbtBlue = 0;
  728. col.rgbtGreen = 250;
  729. col.rgbtRed = 250;
  730. col_r = col;
  731. #endif
  732. }
  733. else if (td.overlay == OVRL_VEINS)
  734. {
  735. col.rgbtBlue = 120;
  736. col.rgbtGreen = 180;
  737. col.rgbtRed = 190;
  738. col_r = col;
  739. }
  740. else if (td.overlay == OVRL_VEINHOLE || td.overlay == OVRL_VEINHOLEBORDER)
  741. {
  742. col.rgbtBlue = 120;
  743. col.rgbtGreen = 160;
  744. col.rgbtRed = 165;
  745. col_r = col;
  746. }
  747. else if (td.overlay != 0xFF)
  748. {
  749. col.rgbtBlue = 20;
  750. col.rgbtGreen = 20;
  751. col.rgbtRed = 20;
  752. col_r = col;
  753. }
  754. if (sod.house.GetLength() > 0)
  755. {
  756. /*
  757. if(strstr(sod.house, houses[1].name))
  758. {
  759. col.rgbtRed=255;
  760. col.rgbtGreen=0;
  761. col.rgbtBlue=0;
  762. }
  763. else if(strstr(sod.house,houses[0].name))
  764. {
  765. col.rgbtRed=180;
  766. col.rgbtGreen=180;
  767. col.rgbtBlue=0;
  768. }
  769. else
  770. {
  771. col.rgbtRed=200;
  772. col.rgbtGreen=200;
  773. col.rgbtBlue=200;
  774. }*/
  775. COLORREF c = ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->GetColor(sod.house);
  776. col.rgbtRed = GetRValue(c);
  777. col.rgbtBlue = GetBValue(c);
  778. col.rgbtGreen = GetGValue(c);
  779. col_r = col;
  780. }
  781. // MW: ADD: make red start pos dots
  782. if (isMultiplayer)
  783. {
  784. CString id;
  785. DWORD p;
  786. int wp = td.waypoint;
  787. BOOL startpos = FALSE;
  788. int i, e;
  789. for (i = -1;i < 2;i++)
  790. {
  791. for (e = -1;e < 2;e++)
  792. {
  793. if (dwPos + i + e * m_IsoSize < fielddata_size)
  794. {
  795. int w = GetWaypointAt(dwPos + i + e * m_IsoSize);
  796. if (w >= 0)
  797. {
  798. GetWaypointData(w, &id, &p);
  799. if (atoi(id) < 8)
  800. {
  801. startpos = TRUE;
  802. break;
  803. }
  804. }
  805. }
  806. }
  807. if (startpos) break;
  808. }
  809. if (startpos)
  810. {
  811. col.rgbtBlue = 0;
  812. col.rgbtGreen = 0;
  813. col.rgbtRed = 255;
  814. col_r = col;
  815. }
  816. }
  817. }
  818. // helper function. Is val==iSet1 or val=iSet2?
  819. __forceinline BOOL st(int val, int iSet)
  820. {
  821. if (val == iSet) return TRUE;
  822. return FALSE;
  823. }
  824. public:
  825. void RedrawMinimap();
  826. BOOL GetInfantryINIData(int index, CString* lpINI);
  827. #ifdef SMUDGE_SUPP
  828. void UpdateSmudges(BOOL bSave = FALSE, int num = -1);
  829. void DeleteSmudge(DWORD dwIndex);
  830. BOOL AddSmudge(SMUDGE* lpSmudge);
  831. void GetSmudgeData(DWORD dwIndex, SMUDGE* lpData) const;
  832. void UpdateSmudgeInfo(LPCSTR lpSmudgeType = NULL);
  833. #endif
  834. BOOL IsYRMap();
  835. BOOL IsMapSection(LPCSTR lpSectionName);
  836. void ResizeMap(int iLeft, int iTop, DWORD dwNewWidth, DWORD dwNewHeight);
  837. void SmoothTiberium(DWORD dwPos);
  838. int GetPowerOfHouse(LPCTSTR lpHouse);
  839. int GetMoneyOnMap() const;
  840. int CalcMoneyOnMap();
  841. void GetMinimap(BYTE** lpData, BITMAPINFO* lpBI, int* pitch);
  842. void GetStructurePaint(int index, STRUCTUREPAINT* lpStructurePaint) const;
  843. void Paste(int x, int y, int z_mod);
  844. void Copy(int left = 0, int top = 0, int right = 0, int bottom = 0);
  845. CString GetTheater();
  846. BOOL IsMultiplayer();
  847. void CreateShore(int left, int top, int right, int bottom, BOOL bRemoveUseless = TRUE);
  848. void Redo();
  849. void SmoothAllAt(DWORD dwPos);
  850. __forceinline void SmoothAt(DWORD dwPos, int iSmoothSet, int iLatSet, int iTargetSet, BOOL bIgnoreShore = TRUE)
  851. {
  852. int i;
  853. int its, iss, ils;
  854. int iLatGround = tilesets_start[iLatSet];
  855. int iSmoothGround = tilesets_start[iSmoothSet];
  856. its = (*tiledata)[tilesets_start[iTargetSet]].tiles[0].bTerrainType;
  857. iss = (*tiledata)[iSmoothGround].tiles[0].bTerrainType;
  858. ils = (*tiledata)[iLatGround].tiles[0].bTerrainType;
  859. FIELDDATA m = *GetFielddataAt(dwPos);
  860. if (m.wGround == 0xFFFF) m.wGround = 0;
  861. // do we have that certain LAT tile here?
  862. if ((*tiledata)[m.wGround].wTileSet != iSmoothSet && (*tiledata)[m.wGround].wTileSet != iLatSet) return;
  863. //if(m.wGround==iLatGround) m.wGround=iSmoothGround;
  864. if (its == iss && (*tiledata)[m.wGround].wTileSet == iSmoothSet) m.wGround = iLatGround;
  865. if (its == iss) ils += 1;
  866. BOOL bOnlyLat = TRUE;
  867. //BOOL bNoLat=TRUE;
  868. int ns = -1;
  869. int e, p = 0;
  870. int ts[3][3]; // terrain info
  871. int set = (*tiledata)[m.wGround].wTileSet;
  872. for (i = 0;i < 3; i++)
  873. {
  874. for (e = 0;e < 3;e++)
  875. {
  876. int pos = dwPos + (i - 1) + (e - 1) * m_IsoSize;
  877. if (pos < 0 || pos >= fielddata_size)
  878. {
  879. ts[i][e] = 0;
  880. }
  881. else
  882. {
  883. FIELDDATA m2 = *GetFielddataAt(pos);
  884. if (m2.wGround == 0xFFFF) m2.wGround = 0;
  885. int cur_set = (*tiledata)[m2.wGround].wTileSet;
  886. //if(cur_set==iSmoothSet) bNoLat=FALSE;
  887. //
  888. if (its == iss && cur_set == iSmoothSet)
  889. {
  890. m2.wGround = iLatGround; cur_set = iLatSet;
  891. }
  892. if (cur_set == iSmoothSet || cur_set == iTargetSet) bOnlyLat = FALSE;
  893. /*if(cur_set != iSmoothSet && cur_set!= iLatSet && cur_set!=iTargetSet)
  894. {
  895. ts[i][e]=(*tiledata)[m2.wGround].tiles[m2.bSubTile].bTerrainType;
  896. if((*tiledata)[m2.wGround].wTileSet!=shoreset)
  897. {
  898. ts[i][e]=0;//ts[i][e]+1; // make sure you don´t smooth at it except it´s shore
  899. }
  900. //if(bIgnoreShore && (*tiledata)[m2.wGround].wTileSet==shoreset)
  901. // ts[i][e]=0;//ts[i][e]+1;
  902. }
  903. else*/ if (its == iss && cur_set != set)
  904. {
  905. if (cur_set == shoreset && !bIgnoreShore)
  906. ts[i][e] = its;
  907. else if (cur_set != iSmoothSet && cur_set != iTargetSet && cur_set != iLatSet)
  908. ts[i][e] = 0;
  909. else
  910. ts[i][e] = its;
  911. }
  912. else if (its == iss && cur_set == set)
  913. ts[i][e] = ils;
  914. else
  915. {
  916. ts[i][e] = (*tiledata)[m2.wGround].tiles[m2.bSubTile].bTerrainType;
  917. if (cur_set != shoreset && cur_set != iLatSet && cur_set != iSmoothSet)
  918. {
  919. ts[i][e] = 0;//ts[i][e]+1; // make sure you don´t smooth at it except it´s shore
  920. }
  921. }
  922. }
  923. }
  924. }
  925. //if(bOnlyLat) return;
  926. int needed = -1;
  927. // 1/1 is smoothed tile
  928. if (ts[1][1] == ils)
  929. {
  930. // single lat
  931. if (ts[0][1] != ils && ts[1][0] != ils
  932. && ts[1][2] != ils && ts[2][1] != ils)
  933. needed = 16;
  934. else if (ts[0][1] == ils && ts[1][0] == ils
  935. && ts[1][2] == ils && ts[2][1] == ils)
  936. needed = 0;
  937. else if (ts[0][1] == ils && ts[2][1] == ils &&
  938. ts[1][0] != ils && ts[1][2] != ils)
  939. needed = 11;
  940. else if (ts[1][0] == ils && ts[1][2] == ils &&
  941. ts[0][1] != ils && ts[2][1] != ils)
  942. needed = 6;
  943. else if (ts[1][0] != ils && ts[0][1] == ils &&
  944. ts[2][1] == ils)
  945. needed = 9;
  946. else if (ts[2][1] != ils && ts[1][0] == ils &&
  947. ts[1][2] == ils)
  948. needed = 5;
  949. else if (ts[1][2] != ils && ts[0][1] == ils &&
  950. ts[2][1] == ils)
  951. needed = 3;
  952. else if (ts[0][1] != ils && ts[1][0] == ils &&
  953. ts[1][2] == ils)
  954. needed = 2;
  955. else if (ts[0][1] == ils && ts[1][0] != ils &&
  956. ts[1][2] != ils && ts[2][1] != ils)
  957. needed = 15;
  958. else if (ts[1][2] == ils && ts[1][0] != ils &&
  959. ts[0][1] != ils && ts[2][1] != ils)
  960. needed = 14;
  961. else if (ts[2][1] == ils && ts[1][0] != ils &&
  962. ts[0][1] != ils && ts[1][2] != ils)
  963. needed = 12;
  964. else if (ts[1][0] == ils && ts[0][1] != ils &&
  965. ts[1][2] != ils && ts[2][1] != ils)
  966. needed = 8;
  967. else if (ts[1][0] != ils && ts[2][1] != ils)
  968. needed = 13;
  969. else if (ts[1][0] != ils && ts[0][1] != ils)
  970. needed = 10;
  971. else if (ts[2][1] != ils && ts[1][2] != ils)
  972. needed = 7;
  973. else if (ts[0][1] != ils && ts[1][2] != ils)
  974. needed = 4;
  975. }
  976. else if (ts[1][1] == its)
  977. {
  978. // replace target set instead of smooth set
  979. //if(st(ts[0][0], && ts[0][1]
  980. }
  981. needed -= 1;
  982. if (needed >= 0)
  983. {
  984. /*for(i=0;i<*tiledata_count;i++)
  985. {
  986. if((*tiledata)[i].wTileSet==iLatSet)
  987. {
  988. break;
  989. }
  990. }*/
  991. i = tilesets_start[iLatSet];
  992. // i is first lat tile
  993. int e;
  994. for (e = 0;e < needed;e++)
  995. {
  996. i += (*tiledata)[i].wTileCount;
  997. }
  998. SetTileAt(dwPos, i, 0);
  999. }
  1000. else if (needed == -1)
  1001. {
  1002. /*for(i=0;i<*tiledata_count;i++)
  1003. {
  1004. if((*tiledata)[i].wTileSet==iSmoothSet)
  1005. {
  1006. break;
  1007. }
  1008. }*/
  1009. i = tilesets_start[iSmoothSet];
  1010. // i is first lat tile
  1011. SetTileAt(dwPos, i, 0);
  1012. }
  1013. }
  1014. BOOL GetLocalSize(RECT* rect) const;
  1015. void Undo();
  1016. void TakeSnapshot(BOOL bEraseFollowing = TRUE, int left = 0, int top = 0, int right = 0, int bottom = 0);
  1017. BOOL CheckMapPackData();
  1018. int GetInfantryCountAt(DWORD dwPos);
  1019. void DeleteTube(std::uint16_t wID);
  1020. // void SetTube(WORD wID, CTube *lpTI);
  1021. void SetTube(CTube* lpTI);
  1022. CTube* GetTube(std::uint16_t wID);
  1023. };
  1024. inline bool CMapData::isInside(MapCoords xy) const
  1025. {
  1026. return xy.x >= 0 && xy.y >= 0 && xy.x < m_IsoSize && xy.y < m_IsoSize;
  1027. }
  1028. inline MapCoords CMapData::ToMapCoords(ProjectedCoords xy) const
  1029. {
  1030. return ToMapCoords3d(xy, 0);
  1031. }
  1032. inline MapCoords CMapData::ToMapCoords3d(ProjectedCoords xy, int mapZ) const
  1033. {
  1034. float cx = xy.x, cy = xy.y + mapZ * f_y / 2;
  1035. return MapCoords(
  1036. cy / (float)f_y - cx / (float)f_x + (float)(m_IsoSize - 2) / 2 + (float)0.5,
  1037. cy / (float)f_y + cx / (float)f_x - (float)(m_IsoSize - 2) / 2.0f - (float)0.5
  1038. );
  1039. }
  1040. inline MapCoords CMapData::ToMapCoords3d(const ProjectedCoords xy, bool bAllowAccessBehindCliffs, bool ignoreHideFlagsAndOutside) const
  1041. {
  1042. auto xy2d = ToMapCoords(xy);
  1043. static const auto fxy = ProjectedVec(f_x, f_y).convertT<float>();
  1044. auto ret = ignoreHideFlagsAndOutside ? xy2d : MapCoords(-1, -1);
  1045. for (int i = 15; i >= 0; i--)
  1046. {
  1047. for (int e = 0; e < 3; e++)
  1048. {
  1049. const MapVec off(i, i); // this is a vertical line starting from the bottom
  1050. const MapVec off2(e == 1 ? -1 : 0, e == 2 ? -1 : 0); // increase x or y or neither in map coordinates by one so that we have a broader area to check
  1051. const MapCoords cur = xy2d + off + off2;
  1052. if (isInside(cur))
  1053. {
  1054. const auto& mfd = *GetFielddataAt(GetMapPos(cur));
  1055. const int ground = mfd.wGround == 0xFFFF ? 0 : mfd.wGround;
  1056. if (ignoreHideFlagsAndOutside || (!mfd.bHide && !(tiledata && (*tiledata)[ground].bHide)))
  1057. {
  1058. const auto curProj = ProjectCoords3d(cur);
  1059. // now projCoords hold the logical pixel coordinates for the current field...
  1060. // we now need to check if cx and cy are in this field
  1061. //if(*x >= m && *x<= m+f_x && *y>=n && *y<=n+f_y)
  1062. {
  1063. auto df1 = (xy - curProj).convertT<float>();
  1064. auto dfScaled = df1 / fxy;
  1065. auto d = Vec2<CSProjected, float>(dfScaled.y - dfScaled.x + 0.5f, dfScaled.y + dfScaled.x - 0.5f);
  1066. if (d.x >= 0.0f && d.y >= 0.0f && d.x <= 1.0f && d.y <= 1.0f)// || (!bAllowAccessBehindCliffs && xy.y >= curProj.y)))
  1067. //if (d == MapCoords(0, 0))
  1068. {
  1069. if (bAllowAccessBehindCliffs)
  1070. ret = cur;
  1071. else
  1072. return cur;
  1073. }
  1074. }
  1075. }
  1076. }
  1077. }
  1078. }
  1079. return ret;
  1080. }
  1081. inline ProjectedCoords CMapData::ProjectCoords(MapCoords xy) const
  1082. {
  1083. return ProjectCoords3d(xy, 0);
  1084. }
  1085. inline ProjectedCoords CMapData::ProjectCoords3d(MapCoords xy, int z) const
  1086. {
  1087. return ProjectedCoords(
  1088. (m_IsoSize - 2 - xy.x + xy.y) * f_x / 2,
  1089. (xy.y + xy.x - z) * f_y / 2
  1090. );
  1091. }
  1092. inline ProjectedCoords CMapData::ProjectCoords3d(MapCoords xy) const
  1093. {
  1094. return ProjectCoords3d(xy, isInside(xy) ? GetHeightAt(xy) : 0);
  1095. }
  1096. #endif // !defined(AFX_MAP_H__9278CAC0_D4E7_11D3_B63B_444553540001__INCLUDED_)