56 std::unique_ptr<CSurface8>
Map;
84 std::unique_ptr<C4FoW>
pFoW;
90 uint32_t
ChunkyRandom(uint32_t &iOffset, uint32_t iRange)
const;
92 void DrawSmoothOChunk(
C4Landscape *, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg,
int flip, uint32_t cro);
93 void ChunkOZoom(
C4Landscape *,
const CSurface8 &sfcMap,
const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX = 0, int32_t iOffY = 0);
95 bool MapToSurface(
C4Landscape *,
const CSurface8 &sfcMap,
const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY);
96 bool MapToLandscape(
C4Landscape *d,
const CSurface8 &sfcMap,
const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iOffsX = 0, int32_t iOffsY = 0,
bool noClear =
false);
107 bool DrawLineLandscape(int32_t iX, int32_t iY, int32_t iGrade, uint8_t line_color, uint8_t line_color_bkg);
108 bool DrawLineMap(int32_t iX, int32_t iY, int32_t iRadius, uint8_t line_color, uint8_t line_color_bkg);
113 int32_t
ForPolygon(
C4Landscape *d,
int *vtcs,
int length,
const std::function<
bool(int32_t, int32_t)> &callback,
114 C4MaterialList *mats_count =
nullptr, uint8_t col = 0, uint8_t colBkg = 0, uint8_t *conversion_table =
nullptr);
132 bool ForLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
133 std::function<
bool(int32_t, int32_t)> fnCallback,
134 int32_t *lastx =
nullptr, int32_t *lasty =
nullptr)
136 int d, dx, dy, aincr, bincr, xincr, yincr, x, y;
137 if (
Abs(x2 - x1) <
Abs(y2 - y1))
139 if (y1 > y2) { std::swap(x1, x2); std::swap(y1, y2); }
140 xincr = (x2 > x1) ? 1 : -1;
141 dy = y2 - y1; dx =
Abs(x2 - x1);
142 d = 2 * dx - dy; aincr = 2 * (dx - dy); bincr = 2 * dx; x = x1; y = y1;
143 if (!fnCallback(x, y))
145 if (lastx) *lastx = x;
146 if (lasty) *lasty = y;
149 for (y = y1 + 1; y <= y2; ++y)
151 if (d >= 0) { x += xincr; d += aincr; }
153 if (!fnCallback(x, y))
155 if (lastx) *lastx = x;
156 if (lasty) *lasty = y;
163 if (x1 > x2) { std::swap(x1, x2); std::swap(y1, y2); }
164 yincr = (y2 > y1) ? 1 : -1;
165 dx = x2 - x1; dy =
Abs(y2 - y1);
166 d = 2 * dy - dx; aincr = 2 * (dy - dx); bincr = 2 * dy; x = x1; y = y1;
167 if (!fnCallback(x, y))
169 if (lastx) *lastx = x;
170 if (lasty) *lasty = y;
173 for (x = x1 + 1; x <= x2; ++x)
175 if (d >= 0) { y += yincr; d += aincr; }
177 if (!fnCallback(x, y))
179 if (lastx) *lastx = x;
180 if (lasty) *lasty = y;
208 p->ExecuteScan(
this);
242 for (int32_t cnt = 0; cnt <
ScanSpeed; cnt++)
246 int32_t last_mat = -1;
247 for (cy = 0; cy <
Height; cy++)
272 #define PRETTY_TEMP_CONV
276 int32_t conv_to_tex = 0;
289 if (!conv_to_tex)
return 0;
297 C4RCMatScan rc = { cx, cy, mat, conv_to, dir, mconvs };
300 int32_t ydir = (dir == 0 ? +1 : -1), cy2;
301 #ifdef PRETTY_TEMP_CONV
303 int32_t lmat = (cx > 0 ? d->
_GetMat(cx - 1, cy) : -1);
305 if (lmat == mat)
return 0;
309 int32_t iSearchRange = std::max<int32_t>(5, mconvs);
311 int32_t cys = cy, cxs = cx;
316 if (d->
_GetMat(cxs, cys) == mat)
323 if ((mconvs = std::min(mconv -
Abs(cys - cy), mconvs)) < 0)
338 if (
Abs(cys - cy) > iSearchRange)
343 if (
Abs(cys - cy) > iSearchRange)
break;
350 for (cy2 = cy; mconvs >= 0 && Inside<int32_t>(cy2, 0, ::
Landscape.
GetHeight() - 1); cy2 += ydir, mconvs--)
353 int32_t pix = d->
_GetPix(cx, cy2);
355 #ifdef PRETTY_TEMP_CONV
357 int32_t lmat = (cx > 0 ? d->
_GetMat(cx - 1, cy2) : -1);
359 if (lmat == mat)
break;
366 return Abs(cy2 - cy);
371 uint32_t clrMod = 0xffffffff;
375 clrMod = p->Modulation;
382 else if (p->pLandscapeRender)
385 p->pLandscapeRender->Draw(cgo, pLight, clrMod);
392 if (!p->pLandscapeRender)
return true;
395 if (!p->Relights[i].Wdt)
398 C4Rect SolidMaskRect = p->pLandscapeRender->GetAffectedRect(p->Relights[i]);
403 p->pLandscapeRender->Update(p->Relights[i],
this);
404 if (p->pFoW) p->pFoW->Ambient.UpdateFromLandscape(*
this, p->Relights[i]);
410 p->Relights[i].Default();
419 static std::vector<int32_t> GetRoundPolygon(int32_t x, int32_t y, int32_t size, int32_t smoothness)
428 if (smoothness > 100) smoothness = 100;
429 if (smoothness < 0) smoothness = 0;
430 if (size <= 0) size = 1;
433 int32_t count = 2 * size / 3 + 6;
435 std::vector<int32_t> vertices;
436 vertices.reserve(count * 2);
444 C4Real anticircle =
itofix(3) + smoothness / 16 * smoothness / 16;
446 int random = 80 * (200 - smoothness);
448 for (
int i = 0; i < count; ++i)
453 currsize +=
Sin(angle * 3 + begin +
itofix(
Random(random)) / 100) * size / anticircle;
454 currsize +=
Cos(angle * 5 + begin2 +
itofix(
Random(random)) / 100) * size / anticircle / 2;
456 vertices.push_back(x +
fixtoi(
Sin(angle)*currsize));
457 vertices.push_back(y -
fixtoi(
Cos(angle)*currsize));
463 static std::vector<int32_t> GetRectangle(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt)
465 std::vector<int32_t> vertices;
468 vertices[0] = tx; vertices[1] = ty;
469 vertices[2] = tx; vertices[3] = ty + hgt;
470 vertices[4] = tx + wdt; vertices[5] = ty + hgt;
471 vertices[6] = tx + wdt; vertices[7] = ty;
476 static C4Rect getBoundingBox(
int *vtcs,
int length)
478 C4Rect BoundingBox(vtcs[0], vtcs[1], 1, 1);
479 for (int32_t i = 2; i + 1 < length; i += 2)
481 BoundingBox.Add(
C4Rect(vtcs[i], vtcs[i + 1], 1, 1));
488 std::vector<int32_t> vertices(GetRectangle(tx, ty, wdt, hgt));
489 C4Rect r(tx, ty, wdt, hgt);
490 p->PrepareChange(
this, r,
false);
491 p->ForPolygon(
this, &vertices[0], vertices.size() / 2, [
this](int32_t x, int32_t y) { return ClearPix(x, y); });
492 p->FinishChange(
this, r,
false);
497 std::vector<int32_t> vertices(GetRectangle(tx, ty, wdt, hgt));
498 return DigFreeShape(&vertices[0], vertices.size(), by_object, no_dig2objects, no_instability_check);
503 std::vector<int32_t> vertices(GetRoundPolygon(tx, ty, rad, 80));
504 return DigFreeShape(&vertices[0], vertices.size(), by_object, no_dig2objects, no_instability_check);
509 std::vector<int32_t> vertices(GetRoundPolygon(tx, ty, rad, 30));
510 BlastFreeShape(&vertices[0], vertices.size(), by_object, caused_by, iMaxDensity);
515 std::vector<int32_t> vertices(GetRoundPolygon(tx, ty, rad, 50));
516 p->ForPolygon(
this, &vertices[0], vertices.size() / 2, [
this](int32_t x, int32_t y) { return p->ShakeFreePix(this, x, y); });
525 C4FindObject *fo_list[] = { &fo_inrect, &fo_insolid, &fo_layer };
535 for (int32_t i = 0; i < dig_objects->
GetSize(); ++i)
539 if (dig_object != by_object)
556 using namespace std::placeholders;
558 C4Rect BoundingBox = getBoundingBox(vtcs, length);
562 std::unique_ptr<C4ValueArray> dig_objects(p->PrepareFreeShape(BoundingBox, by_object));
564 std::function<bool(int32_t, int32_t)> callback;
565 if (no_instability_check)
566 callback = [
this](int32_t x, int32_t y) {
return p->DigFreePixNoInstability(
this, x, y); };
568 callback = [
this](int32_t x, int32_t y) {
return p->DigFreePix(
this, x, y); };
574 amount = p->ForPolygon(
this, vtcs, length / 2, callback, by_object->
MaterialContents);
577 amount = p->ForPolygon(
this, vtcs, length / 2, callback,
nullptr);
592 p->PostFreeShape(dig_objects.get(), by_object);
601 C4Rect BoundingBox = getBoundingBox(vtcs, length);
604 std::unique_ptr<C4ValueArray> dig_objects(p->PrepareFreeShape(BoundingBox, by_object));
610 pblast_tbl = blast_tbl;
617 p->ForPolygon(
this, vtcs, length / 2, [
this](int32_t x, int32_t y) {
return p->BlastFreePix(
this, x, y); }, by_object->
MaterialContents, 0, 0, pblast_tbl);
622 p->ForPolygon(
this, vtcs, length / 2, [
this](int32_t x, int32_t y) {
return p->BlastFreePix(
this, x, y); }, MaterialContents, iMaxDensity);
630 mat_list = MaterialContents;
633 p->BlastMaterial2Objects(tx, ty, mat_list, by_player, (BoundingBox.
Wdt + BoundingBox.
Hgt) / 4, dig_objects.get());
635 if (MaterialContents)
delete MaterialContents;
638 p->PostFreeShape(dig_objects.get(), by_object);
645 if (mat_list->
Amount[mat])
647 int32_t cast_strength = str;
648 int32_t pxsamount = 0, blastamount = 0;
653 ::PXS.
Cast(mat, pxsamount, tx, ty, cast_strength * 2);
676 if (mat_list->
Amount[mat])
684 if (!pObj || !pObj->
Status)
continue;
686 if (pCollect && pCollect->
Status)
696 if (pCollect && pCollect->
Status && pObj && pObj->
Status)
713 int32_t mat = d->
GetMat(tx, ty);
725 int32_t mat = d->
GetMat(tx, ty);
739 int32_t mat = d->
GetMat(tx, ty);
759 int32_t mat = d->
GetMat(tx, ty);
777 BYTE bkgPix = p->Surface8Bkg->GetPix(tx, ty);
778 return SetPix2(tx, ty, bkgPix, bkgPix);
783 if (p->pFoW) p->pFoW->Remove(pObj);
795 return _SetPix2(x, y, fgPix, bgPix);
803 rc.
x = x; rc.
y = y; rc.
clr = fgPix; rc.
bgClr = fgPix;
810 if (bgPix ==
Transparent) bgPix = p->Surface8Bkg->_GetPix(x, y);
812 if (fgPix == opix && bgPix == p->Surface8Bkg->_GetPix(x, y))
return true;
814 if (p->Pix2Dens[fgPix])
816 if (!p->Pix2Dens[opix]) p->PixCnt[(y / 15) + (x / 17) * p->PixCntPitch]++;
820 if (p->Pix2Dens[opix]) p->PixCnt[(y / 15) + (x / 17) * p->PixCntPitch]--;
823 assert(!fgPix ||
MatValid(p->Pix2Mat[fgPix]));
824 int32_t omat = p->Pix2Mat[opix], nmat = p->Pix2Mat[fgPix];
825 if (opix) p->MatCount[omat]--;
826 if (fgPix) p->MatCount[nmat]++;
837 if (iBelow + iAbove + 1 >= iMinHeight)
841 if (iBelow < iMinHeight) iChange += iBelow;
842 if (iAbove < iMinHeight) iChange += iAbove;
844 p->EffectiveMatCount[nmat] += iChange;
854 if (iBelow + iAbove + 1 >= iMinHeight)
858 if (iBelow < iMinHeight) iChange += iBelow;
859 if (iAbove < iMinHeight) iChange += iAbove;
861 p->EffectiveMatCount[omat] -= iChange;
866 p->Surface8->SetPix(x, y, fgPix);
867 p->Surface8Bkg->SetPix(x, y, bgPix);
869 if (p->pLandscapeRender)
871 C4Rect CheckRect = p->pLandscapeRender->GetAffectedRect(
C4Rect(x, y, 1, 1));
873 if (!p->Relights[i].Wdt || p->Relights[i].Overlap(CheckRect) || i + 1 >=
C4LS_MaxRelights)
875 p->Relights[i].Add(CheckRect);
880 p->pFoW->Invalidate(CheckRect);
890 if (fgPix !=
Transparent) p->Surface8->SetPix(x, y, fgPix);
891 if (bgPix !=
Transparent) p->Surface8Bkg->SetPix(x, y, bgPix);
896 int32_t mat =
GetMat(tx, ty);
905 if (!
ClearPix(tx, ty))
return false;
934 for (cy = ty; cy < ty + hgt; cy++)
935 for (cx = tx; cx < tx + wdt; cx++)
944 for (cx = tx; cx < tx + wdt; cx++)
949 cpix =
GetPix(cx, cy + 1);
959 int32_t mat =
GetMat(fx, fy);
977 assert(tx); assert(ty);
981 if (!mdens)
return true;
1000 (*ty)--;
if (*ty < 0)
return false;
1002 if (
GetDensity(*tx - 1, *ty) < mdens) (*tx)--;
1003 if (
GetDensity(*tx + 1, *ty) < mdens) (*tx)++;
1006 if (
GetDensity(*tx, *ty) > mdens)
return false;
1028 int32_t check_dir = 0;
1029 for (int32_t i = 0; i < 2; ++i)
1034 if ((*pReact->
pFunc)(pReact, *tx, *ty, *tx, *ty + check_dir, fvx, fvy, mat, tmat,
meePXSPos,
nullptr))
1059 int n = 0;
int pix = -1;
1060 if (tx > 0 &&
_GetMat(tx - 1, ty) == mat)
1062 if (ty > 0 &&
_GetMat(tx, ty - 1) == mat)
1077 int32_t tyo = ty - 1;
1086 int32_t mat =
GetMat(x, y);
1103 auto sfcBg = std::make_unique<CSurface8>();
1104 if (!sfcBg->Create(sfcFg.
Wdt, sfcFg.
Hgt))
1109 for (int32_t y = 0; y < sfcFg.
Hgt; ++y)
1111 for (int32_t x = 0; x < sfcFg.
Wdt; ++x)
1127 bgPix = DefaultBkgMat(fgPix);
1136 bgPix = DefaultBkgMat(fgPix);
1139 sfcBg->_SetPix(x, y, bgPix);
1161 #define POLYGON_FIX_SHIFT 16
1163 static void fill_edge_structure(
CPolyEdge *edge,
int *i1,
int *i2)
1167 int *t = i1; i1 = i2; i2 = t;
1170 edge->
bottom = i2[1] - 1;
1173 edge->
prev =
nullptr;
1174 edge->
next =
nullptr;
1186 while ((pos) && (pos->
x + pos->
w / 2 < edge->
x + edge->
w / 2))
1193 while ((pos) && (pos->
y < edge->
y))
1200 if (pos) pos->
prev = edge;
1209 else return edge->
next;
1217 C4MaterialList *mats_count, uint8_t col, uint8_t colBkg, uint8_t *conversion_table)
1227 bool use_qpb =
false;
1236 else if (!(edgebuf =
new CPolyEdge[length])) {
return 0; }
1241 i2 = vtcs + (length - 1) * 2;
1242 for (c = 0; c < length; c++)
1246 fill_edge_structure(edge, i1, i2);
1251 inactive_edges = add_edge(inactive_edges, edge,
false);
1262 edge = inactive_edges;
1263 while ((edge) && (edge->
y == c))
1265 next_edge = edge->
next;
1266 inactive_edges = remove_edge(inactive_edges, edge);
1267 active_edges = add_edge(active_edges, edge,
true);
1272 edge = active_edges;
1273 while ((edge) && (edge->
next))
1279 if (x1 > x2) std::swap(x1, x2);
1283 for (
int xcnt = x2 - x1 - 1; xcnt >= 0; xcnt--)
1285 uint8_t pix = d->
GetPix(x1 + xcnt,
y);
1286 if (!conversion_table || conversion_table[pix])
1289 if (callback(x1 + xcnt,
y))
1292 mats_count->
Add(mat, 1);
1298 else if (conversion_table)
1299 for (
int xcnt = x2 - x1 - 1; xcnt >= 0; xcnt--)
1301 const uint8_t pix = conversion_table[uint8_t(d->
GetPix(x1 + xcnt,
y))];
1302 Surface8->SetPix(x1 + xcnt,
y, pix);
1303 if (colBkg !=
Transparent) Surface8Bkg->SetPix(x1 + xcnt,
y, colBkg);
1306 for (
int xcnt = x2 - x1 - 1; xcnt >= 0; xcnt--)
1308 if (col !=
Transparent) Surface8->SetPix(x1 + xcnt,
y, col);
1309 if (colBkg !=
Transparent) Surface8Bkg->SetPix(x1 + xcnt,
y, colBkg);
1315 edge = active_edges;
1318 next_edge = edge->
next;
1321 active_edges = remove_edge(active_edges, edge);
1325 edge->
x += edge->
dx;
1326 while ((edge->
prev) && (edge->
x + edge->
w / 2 < edge->
prev->
x + edge->
prev->
w / 2))
1334 else active_edges = edge;
1342 if (!use_qpb)
delete[] edgebuf;
1359 if (fClearMapCreator) { p->pMapCreator.reset(); }
1361 if (fClearSky) p->Sky.Clear();
1363 if (fClearRenderer) { p->pLandscapeRender.reset(); }
1364 p->TopRowPix.clear();
1365 p->BottomRowPix.clear();
1366 p->LeftColPix.clear();
1367 p->RightColPix.clear();
1368 p->Surface8.reset();
1369 p->Surface8Bkg.reset();
1373 p->pInitial.reset();
1374 p->pInitialBkg.reset();
1377 for (
auto &relight : p->Relights)
1386 for (
auto &conv : p->BridgeMatConversion)
1399 int32_t ambient_brightness;
1401 if (p->pFoW) p->pFoW->Ambient.SetBrightness(ambient_brightness /
static_cast<double>(255));
1407 int32_t ambient_brightness =
static_cast<int32_t
>(p->pFoW->Ambient.GetBrightness() * 255 + 0.5);
1413 static std::unique_ptr<CSurface8> GroupReadSurface8(
C4Group &hGroup,
const char *szWildCard)
1418 auto pSfc = std::make_unique<CSurface8>();
1419 if (!pSfc->Read(hGroup))
1429 if (!p->MapSeed) p->MapSeed =
Random(3133700);
1446 p->fMapChanged = fOverloadCurrent;
1460 std::unique_ptr<CSurface8> sfcMap, sfcMapBkg;
1463 if ((sfcMap = GroupReadSurface8(hGroup,
C4CFN_Map)))
1466 sfcMapBkg = p->CreateDefaultBkgSurface(*sfcMap,
true);
1467 if (!sfcMapBkg)
return false;
1476 if ((sfcMap = GroupReadSurface8(hGroup,
C4CFN_MapFg)))
1479 sfcMapBkg = GroupReadSurface8(hGroup,
C4CFN_MapBg);
1480 if (!sfcMapBkg) sfcMapBkg = p->CreateDefaultBkgSurface(*sfcMap,
false);
1481 if (!sfcMapBkg)
return false;
1486 CSurface8 *rendered_map =
nullptr, *rendered_bkg =
nullptr;
1489 if (p->CreateMapS2(hGroup, rendered_map, rendered_bkg))
1491 sfcMap.reset(rendered_map);
1492 sfcMapBkg.reset(rendered_bkg);
1504 if (!sfcMap && !fOverloadCurrent)
1506 if (p->CreateMap(rendered_map, rendered_bkg))
1508 sfcMap.reset(rendered_map);
1509 sfcMapBkg.reset(rendered_bkg);
1520 if (!fOverloadCurrent)
return false;
1521 if (fLoadSky)
if (!p->Sky.Init(fSavegame))
return false;
1525 assert(sfcMapBkg !=
nullptr);
1535 sfcMap->GetSurfaceSize(iWdt, iHgt);
1536 p->MapWidth = iWdt; p->MapHeight = iHgt;
1540 p->Width = p->MapZoom * p->MapWidth;
1541 p->Height = p->MapZoom * p->MapHeight;
1542 p->Width = std::max<int32_t>(p->Width, 100);
1543 p->Height = std::max<int32_t>(p->Height, 100);
1550 assert(p->Map ==
nullptr);
1551 assert(p->MapBkg ==
nullptr);
1552 p->Map = std::move(sfcMap);
1553 p->MapBkg = std::move(sfcMapBkg);
1559 if (!p->Sky.Init(fSavegame))
return false;
1572 if (!
Load(hGroup, fLoadSky, fSavegame))
return false;
1587 int32_t PixCntWidth = (
GetWidth() + 16) / 17;
1588 p->PixCntPitch = (
GetHeight() + 14) / 15;
1589 p->PixCnt.resize(PixCntWidth * p->PixCntPitch);
1595 assert(p->Surface8 ==
nullptr);
1596 assert(p->Surface8Bkg ==
nullptr);
1600 auto sf8 = std::make_unique<CSurface8>();
1601 auto sfb8 = std::make_unique<CSurface8>();
1604 p->Surface8 = std::move(sf8);
1605 p->Surface8Bkg = std::move(sfb8);
1612 std::unique_ptr<C4LandscapeRender> lsrender_backup;
1613 lsrender_backup.swap(p->pLandscapeRender);
1615 lsrender_backup.swap(p->pLandscapeRender);
1616 if (!map2landscape_success)
return false;
1627 AddDbgRec(
RCT_Map, p->Surface8->Bits, p->Surface8->Pitch * p->Surface8->Hgt);
1630 AddDbgRec(
RCT_Map, p->Surface8Bkg->Bits, p->Surface8Bkg->Pitch * p->Surface8Bkg->Hgt);
1634 assert(p->pFoW ==
nullptr);
1636 p->pFoW = std::make_unique<C4FoW>();
1640 if (!p->pLandscapeRender)
1641 p->pLandscapeRender = std::make_unique<C4LandscapeRenderGL>();
1644 if (p->pLandscapeRender)
1647 if (fOverloadCurrent)
1680 if (p->pFoW) p->pFoW->Ambient.CreateFromLandscape(*
this, 10., 50., 0.25);
1690 return p->Map !=
nullptr && p->MapBkg !=
nullptr;
1696 bool r = p->SaveInternal(
this, hGroup);
1707 if (!Surface8->Save(szTempLandscape))
1717 if (!Surface8Bkg->Save(szTempLandscape))
1723 if (fMapChanged && Map)
1737 bool r = p->SaveDiffInternal(
this, hGroup, fSyncSave);
1744 assert(pInitial && pInitialBkg);
1745 if (!pInitial || !pInitialBkg)
return false;
1749 bool fChanged =
false, fChangedBkg =
false;;
1751 for (
int y = 0;
y < Height;
y++)
1752 for (
int x = 0;
x < Width;
x++)
1754 if (pInitial[
y * Width +
x] == Surface8->_GetPix(
x,
y))
1759 if (pInitialBkg[
y * Width +
x] == Surface8Bkg->_GetPix(
x,
y))
1765 if (fSyncSave || fChanged)
1777 if (fSyncSave || fChangedBkg)
1791 for (
int y = 0;
y < Height;
y++)
1792 for (
int x = 0;
x < Width;
x++)
1795 Surface8->SetPix(
x,
y, pInitial[
y * Width +
x]);
1797 Surface8Bkg->SetPix(
x,
y, pInitialBkg[
y * Width +
x]);
1801 if (fMapChanged && Map)
1802 if (!d->
SaveMap(hGroup))
return false;
1823 p->pInitial[pitch +
x] = p->Surface8->_GetPix(
x,
y);
1824 p->pInitialBkg[pitch +
x] = p->Surface8Bkg->_GetPix(
x,
y);
1833 assert(!p->Surface8 && !p->Surface8Bkg);
1836 if ((p->Surface8 = GroupReadSurface8(hGroup,
C4CFN_Landscape)) ==
nullptr)
1838 if ((p->Surface8 = GroupReadSurface8(hGroup,
C4CFN_LandscapeFg)) ==
nullptr)
return false;
1843 if (p->Surface8->Wdt != p->Surface8Bkg->Wdt || p->Surface8->Hgt != p->Surface8Bkg->Hgt)
1845 LogFatal(
FormatString(
"Landscape has different dimensions than background landscape (%dx%d vs. %dx%d)", p->Surface8->Wdt, p->Surface8->Hgt, p->Surface8Bkg->Wdt, p->Surface8Bkg->Hgt).
getData());
1853 p->Surface8Bkg = p->CreateDefaultBkgSurface(*p->Surface8,
false);
1860 p->Surface8Bkg = p->CreateDefaultBkgSurface(*p->Surface8,
true);
1863 int iWidth, iHeight;
1864 p->Surface8->GetSurfaceSize(iWidth, iHeight);
1865 p->Width = iWidth; p->Height = iHeight;
1868 if (!p->Mat2Pal())
return false;
1873 BYTE byPix = p->Surface8->_GetPix(
x,
y);
1878 LogFatal(
FormatString(
"Landscape loading error at (%d/%d): Pixel value %d not a valid material!", (
int)
x, (
int)
y, (
int)byPix).getData());
1882 BYTE byPixBkg = p->Surface8Bkg->_GetPix(
x,
y);
1885 if (byPixBkg && !
MatValid(iMatBkg))
1887 LogFatal(
FormatString(
"Background Landscape loading error at (%d/%d): Pixel value %d not a valid material!", (
int)
x, (
int)
y, (
int)byPixBkg).getData());
1896 if (p->Sky.Init(fSavegame))
return false;
1903 std::unique_ptr<CSurface8> pDiff, pDiffBkg;
1907 if (pDiff ==
nullptr && pDiffBkg ==
nullptr)
return false;
1914 if (p->Surface8->_GetPix(
x,
y) != (byPix = pDiff->_GetPix(
x,
y)))
1916 p->Surface8->SetPix(
x,
y, byPix);
1918 if (p->Surface8Bkg->_GetPix(
x,
y) != (byPix = pDiffBkg->_GetPix(
x,
y)))
1919 p->Surface8Bkg->_SetPix(
x,
y, byPix);
1928 p = std::make_unique<P>();
1933 std::fill(MatCount.begin(), MatCount.end(), 0);
1934 std::fill(EffectiveMatCount.begin(), EffectiveMatCount.end(), 0);
1947 if (!iTex)
return MNone;
1957 if (!p->Map)
return false;
1958 assert(p->MapBkg !=
nullptr);
1992 bool fSuccess =
false;
2003 if (pMatGroup->
Close())
2018 if (!fSuccess)
return false;
2029 if (!Width)
return true;
2031 BottomRowPix.clear();
2033 RightColPix.clear();
2038 if (top_open_flag == 2 && !Map) top_open_flag = 1;
2039 if (bottom_open_flag == 2 && !Map) bottom_open_flag = 1;
2042 switch (top_open_flag)
2045 case 0: TopRowPix.assign(Width,
MCVehic);
break;
2048 TopRowPix.resize(Width);
2049 for (int32_t
x = 0;
x < Width; ++
x)
2051 uint8_t map_pix = MapBkg->GetPix(
x / MapZoom, 0);
2052 TopRowPix[
x] = ((map_pix != 0) ?
MCVehic : 0);
2056 default: TopRowPix.assign(Width, 0);
break;
2060 switch (bottom_open_flag)
2063 case 0: BottomRowPix.assign(Width,
MCVehic);
break;
2066 BottomRowPix.resize(Width);
2067 for (int32_t
x = 0;
x < Width; ++
x)
2069 uint8_t map_pix = MapBkg->GetPix(
x / MapZoom, Map->Hgt - 1);
2070 BottomRowPix[
x] = ((map_pix != 0) ?
MCVehic : 0);
2074 default: BottomRowPix.assign(Width, 0);
break;
2082 LeftColPix.resize(Height);
2083 RightColPix.resize(Height);
2085 for (int32_t
y = 0;
y < Height; ++
y)
2087 map_pix = MapBkg->GetPix(0,
y / MapZoom);
2088 if (!only_bg) map_pix += Map->GetPix(0,
y / MapZoom);
2089 LeftColPix[
y] = ((map_pix != 0) ?
MCVehic : 0);
2090 map_pix = MapBkg->GetPix(Map->Wdt - 1,
y / MapZoom);
2091 if (!only_bg) map_pix += Map->GetPix(Map->Wdt - 1,
y / MapZoom);
2092 RightColPix[
y] = ((map_pix != 0) ?
MCVehic : 0);
2099 LeftColPix.assign(Height,
MCVehic);
2100 RightColPix.assign(Height,
MCVehic);
2101 for (int32_t cy = 0; cy < LeftOpen; cy++)
2103 for (int32_t cy = 0; cy < RightOpen; cy++)
2104 RightColPix[cy] = 0;
2113 return p->MapToLandscape(
this, *p->Map, *p->MapBkg, 0, 0, p->MapWidth, p->MapHeight);
2119 if (!iRange)
return 0;
2120 iOffset = (iOffset * 16807) % 2147483647;
2121 return (iOffset ^ MapSeed) % iRange;
2126 unsigned int top_rough = 0, side_rough = 0, bottom_rough = 0;
2131 if (mcol !=
Transparent) Surface8->Box(tx, ty, tx + wdt, ty + hgt, mcol);
2132 if (mcolBkg !=
Transparent) Surface8Bkg->Box(tx, ty, tx + wdt, ty + hgt, mcolBkg);
2135 top_rough = 0; side_rough = 2; bottom_rough = 4;
2138 top_rough = 2; side_rough = 2; bottom_rough = 2;
2141 top_rough = 4; side_rough = 4; bottom_rough = 4;
2144 top_rough = 1; side_rough = 1; bottom_rough = 1;
2148 unsigned int rx = std::max(wdt / 2, 1);
2150 vtcs[0] = tx - ChunkyRandom(cro, rx * side_rough / 4); vtcs[1] = ty - ChunkyRandom(cro, rx * top_rough / 4);
2151 vtcs[2] = tx - ChunkyRandom(cro, rx * side_rough / 2); vtcs[3] = ty + hgt / 2;
2152 vtcs[4] = tx - ChunkyRandom(cro, rx * side_rough / 4); vtcs[5] = ty + hgt + ChunkyRandom(cro, rx * bottom_rough / 4);
2153 vtcs[6] = tx + wdt / 2; vtcs[7] = ty + hgt + ChunkyRandom(cro, rx * bottom_rough / 2);
2154 vtcs[8] = tx + wdt + ChunkyRandom(cro, rx * side_rough / 4); vtcs[9] = ty + hgt + ChunkyRandom(cro, rx * bottom_rough / 4);
2155 vtcs[10] = tx + wdt + ChunkyRandom(cro, rx * side_rough / 2); vtcs[11] = ty + hgt / 2;
2156 vtcs[12] = tx + wdt + ChunkyRandom(cro, rx * side_rough / 4); vtcs[13] = ty - ChunkyRandom(cro, rx * top_rough / 4);
2157 vtcs[14] = tx + wdt / 2; vtcs[15] = ty - ChunkyRandom(cro, rx * top_rough / 2);
2159 ForPolygon(d, vtcs, 8,
nullptr,
nullptr, mcol, mcolBkg);
2165 unsigned int rx = std::max(wdt / 2, 1);
2167 vtcs[0] = tx; vtcs[1] = ty;
2168 vtcs[2] = tx; vtcs[3] = ty + hgt;
2169 vtcs[4] = tx + wdt; vtcs[5] = ty + hgt;
2170 vtcs[6] = tx + wdt; vtcs[7] = ty;
2174 case 0: vtcs[0] = tx + wdt / 2; vtcs[1] += hgt / 3; vtcs[7] -= ChunkyRandom(cro, rx / 2);
break;
2175 case 1: vtcs[2] = tx + wdt / 2; vtcs[3] -= hgt / 3; vtcs[5] += ChunkyRandom(cro, rx / 2);
break;
2176 case 2: vtcs[4] = tx + wdt / 2; vtcs[5] -= hgt / 3; vtcs[3] += ChunkyRandom(cro, rx / 2);
break;
2177 case 3: vtcs[6] = tx + wdt / 2; vtcs[7] += hgt / 3; vtcs[1] -= ChunkyRandom(cro, rx / 2);
break;
2178 case 4: vtcs[0] = tx + wdt / 2; vtcs[1] += hgt / 2;
break;
2179 case 5: vtcs[2] = tx + wdt / 2; vtcs[3] -= hgt / 2;
break;
2180 case 6: vtcs[4] = tx + wdt / 2; vtcs[5] -= hgt / 2;
break;
2181 case 7: vtcs[6] = tx + wdt / 2; vtcs[7] += hgt / 2;
break;
2184 ForPolygon(d, vtcs, 4,
nullptr,
nullptr, mcol, mcolBkg);
2191 if (!pMaterial)
return;
2198 int iMapWidth, iMapHeight;
2201 iMapX = Clamp<int32_t>(iMapX, 0, iMapWidth - 1);
2202 iMapY = Clamp<int32_t>(iMapY, 0, iMapHeight - 1);
2203 iMapWdt = Clamp<int32_t>(iMapWdt, 0, iMapWidth - iMapX);
2204 iMapHgt = Clamp<int32_t>(iMapHgt, 0, iMapHeight - iMapY);
2206 int iChunkWidth = MapZoom, iChunkHeight = MapZoom;
2208 for (
int iY = iMapY; iY < iMapY + iMapHgt; iY++)
2211 int iToY = iY * iChunkHeight + iOffY;
2213 for (
int iX = iMapX; iX < iMapX + iMapWdt; iX++)
2216 uint8_t MapPixel = sfcMap.
_GetPix(iX, iY);
2217 uint8_t MapPixelBkg = sfcMapBkg.
_GetPix(iX, iY);
2219 int iToX = iX * iChunkWidth + iOffX;
2221 if (MapPixel == iTexture)
2224 DrawChunk(d, iToX, iToY, iChunkWidth, iChunkHeight, MapPixel, MapPixelBkg, iChunkType, (iX << 16) + iY);
2230 uint8_t below = sfcMap.
GetPix(iX, iY + 1);
2231 uint8_t above = sfcMap.
GetPix(iX, iY - 1);
2234 uint8_t leftBkg = sfcMapBkg.
GetPix(iX - 1, iY);
2235 uint8_t rightBkg = sfcMapBkg.
GetPix(iX + 1, iY);
2237 if (below == iTexture && above == iTexture &&
left == iTexture &&
right == iTexture)
2241 if (iY < iMapHeight - 1 && below == iTexture)
2244 if (iX > 0 &&
left == iTexture)
2247 DrawSmoothOChunk(d, iToX, iToY, iChunkWidth, iChunkHeight,
left, leftBkg, 3 + flat, (iX << 16) + iY);
2250 if (iX < iMapWidth - 1 &&
right == iTexture)
2253 DrawSmoothOChunk(d, iToX, iToY, iChunkWidth, iChunkHeight,
right, rightBkg, 0 + flat, (iX << 16) + iY);
2257 if (iY > 0 && above == iTexture)
2260 if (iX > 0 &&
left == iTexture)
2263 DrawSmoothOChunk(d, iToX, iToY, iChunkWidth, iChunkHeight,
left, leftBkg, 2 + flat, (iX << 16) + iY);
2266 if (iX < iMapWidth - 1 &&
right == iTexture)
2269 DrawSmoothOChunk(d, iToX, iToY, iChunkWidth, iChunkHeight,
right, rightBkg, 1 + flat, (iX << 16) + iY);
2276 if (shape && !::
Game.
C4S.
Landscape.
FlatChunkShapes) shape->
Draw(sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, iTexture, iOffX, iOffY, MapZoom, pMaterial->
MinShapeOverlap);
2279 static bool GetTexUsage(
const CSurface8 &sfcMap,
const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt,
DWORD *dwpTextureUsage)
2283 if (!dwpTextureUsage)
return false;
2285 iMapX = Clamp<int32_t>(iMapX, 0, sfcMap.
Wdt - 1); iMapY = Clamp<int32_t>(iMapY, 0, sfcMap.
Hgt - 1);
2286 iMapWdt = Clamp<int32_t>(iMapWdt, 0, sfcMap.
Wdt - iMapX); iMapHgt = Clamp<int32_t>(iMapHgt, 0, sfcMap.
Hgt - iMapY);
2288 for (int32_t cnt = 0; cnt <
C4M_MaxTexIndex; cnt++) dwpTextureUsage[cnt] = 0;
2290 for (iY = iMapY; iY < iMapY + iMapHgt; iY++)
2291 for (iX = iMapX; iX < iMapX + iMapWdt; iX++)
2294 const int32_t tex = sfcMap.
GetPix(iX, iY);
2297 if (!dwpTextureUsage[tex]++)
if (tex)
2301 LogF(
"Map2Landscape error: Texture index %d at (%d/%d) in map not defined in texture map!", (
int)tex, (
int)iX, (
int)iY);
2330 if (dwpTextureUsage[iIndex] > 0)
2333 ChunkOZoom(d, sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, iIndex, iToX, iToY);
2341 bool C4Landscape::P::MapToSurface(
C4Landscape *d,
const CSurface8 &sfcMap,
const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY)
2345 Surface8->Clip(iToX, iToY, iToX + iToWdt - 1, iToY + iToHgt - 1);
2346 Surface8Bkg->Clip(iToX, iToY, iToX + iToWdt - 1, iToY + iToHgt - 1);
2357 if (!GetTexUsage(sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, dwTexUsage))
return false;
2359 if (!TexOZoom(d, sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, dwTexUsage, iOffX, iOffY))
return false;
2363 Surface8Bkg->NoClip();
2371 assert(Surface8 && Surface8Bkg);
2373 int iMapWidth, iMapHeight, iLandscapeWidth, iLandscapeHeight;
2376 Surface8->GetSurfaceSize(iLandscapeWidth, iLandscapeHeight);
2378 iMapX = Clamp<int32_t>(iMapX, 0, iMapWidth - 1); iMapY = Clamp<int32_t>(iMapY, 0, iMapHeight - 1);
2379 iMapWdt = Clamp<int32_t>(iMapWdt, 0, iMapWidth - iMapX); iMapHgt = Clamp<int32_t>(iMapHgt, 0, iMapHeight - iMapY);
2381 if (!iMapWdt || !iMapHgt)
return true;
2385 To.
x = iMapX*MapZoom + iOffsX;
2386 To.
y = iMapY*MapZoom + iOffsY;
2387 To.
Wdt = iMapWdt*MapZoom;
2388 To.
Hgt = iMapHgt*MapZoom;
2390 PrepareChange(d, To);
2395 Surface8->ClearBox8Only(To.
x, To.
y, To.
Wdt, To.
Hgt);
2396 Surface8Bkg->ClearBox8Only(To.
x, To.
y, To.
Wdt, To.
Hgt);
2399 MapToSurface(d, sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, To.
x, To.
y, To.
Wdt, To.
Hgt, iOffsX, iOffsY);
2400 FinishChange(d, To);
2406 int32_t iWidth = 0, iHeight = 0;
2410 auto fg_map = std::make_unique<CSurface8>(iWidth, iHeight);
2414 MapCreator.
Create(fg_map.get(),
2418 auto bg_map = CreateDefaultBkgSurface(*fg_map,
false);
2422 sfcMap = fg_map.release();
2423 sfcMapBkg = bg_map.release();
2439 if (!pMapCreator->Render(
nullptr, sfcMap, sfcMapBkg))
2449 if (!p->pMapCreator)
return true;
2451 p->pMapCreator->ExecuteCallbacks(p->MapZoom);
2465 iMax = std::min<int32_t>(iMax,
GetHeight() -
y);
2466 for (int32_t i = 0; i < iMax; i++)
2472 iMax = std::min<int32_t>(iMax,
y + 1);
2473 for (int32_t i = 0; i < iMax; i++)
2482 int32_t cy1 = ry, cy2 = ry;
2483 bool UseUpwardsNextFree =
false, UseDownwardsNextSolid =
false;
2491 else if (UseUpwardsNextFree) { ry = cy1;
return true; }
2497 else if (UseDownwardsNextSolid) { ry = cy2;
return true; }
2509 int32_t cy1 = ry, cy2 = ry;
2518 ry = cy1;
return true;
2525 ry = cy2;
return true;
2537 int32_t cy1 = ry, cy2 = ry;
2546 ry = cy1;
return true;
2553 ry = cy2;
return true;
2564 int32_t cy1 = ry, cy2 = ry, rl1 = 0, rl2 = 0;
2573 rl1++;
if (rl1 >= hgt) { ry = cy1 + hgt / 2;
return true; }
2582 rl2++;
if (rl2 >= hgt) { ry = cy2 - hgt / 2;
return true; }
2595 int32_t cy1 = ry, cy2 = ry, rl1 = 0, rl2 = 0;
2604 rl1++;
if (rl1 >= hgt) { ry = cy1 + hgt / 2;
return true; }
2613 rl2++;
if (rl2 >= hgt) { ry = cy2 - hgt / 2;
return true; }
2628 bool fFound =
false;
2630 int32_t cx1, cx2, cy1, cy2, rl1 = 0, rl2 = 0;
2632 for (cx1 = cx2 = rx, cy1 = cy2 = ry; (cx1 > 0) || (cx2 < ::
Landscape.
GetWidth()); cx1--, cx2++)
2647 if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1; fFound =
true;
break; }
2648 if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2; fFound =
true;
break; }
2658 bool fFound =
false;
2660 int32_t cx1, cx2, cy1, cy2, rl1 = 0, rl2 = 0, cnt;
2662 for (cx1 = cx2 = rx, cy1 = cy2 = ry; (cx1 > 0) || (cx2 < ::
Landscape.
GetWidth()); cx1--, cx2++)
2670 for (lokay =
true, cnt = 0; cnt < height; cnt++)
if (!
GBackLiquid(cx1, cy1 + 1 + cnt)) lokay =
false;
2681 for (lokay =
true, cnt = 0; cnt < height; cnt++)
if (!
GBackLiquid(cx2, cy2 + 1 + cnt)) lokay =
false;
2687 if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1; fFound =
true;
break; }
2688 if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2; fFound =
true;
break; }
2696 bool FindLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height)
2698 int32_t cx1, cx2, cy1, cy2, rl1 = 0, rl2 = 0;
2700 for (cx1 = cx2 = rx, cy1 = cy2 = ry; (cx1 > 0) || (cx2 < ::
Landscape.
GetWidth()); cx1--, cx2++)
2715 if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1;
return true; }
2716 if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2;
return true; }
2724 bool FindTunnel(int32_t &rx, int32_t &ry, int32_t width, int32_t height)
2726 int32_t cx1, cx2, cy1, cy2, rl1 = 0, rl2 = 0;
2728 for (cx1 = cx2 = rx, cy1 = cy2 = ry; (cx1 > 0) || (cx2 < ::
Landscape.
GetWidth()); cx1--, cx2++)
2743 if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1;
return true; }
2744 if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2;
return true; }
2754 bool fFound =
false;
2756 int32_t cx1, cx2, cy1, cy2, rh1, rh2, rl1, rl2;
2758 cx1 = cx2 = rx; cy1 = cy2 = ry;
2759 rh1 = cy1; rh2 = cy2;
2795 if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1; fFound =
true;
break; }
2796 if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2; fFound =
true;
break; }
2808 bool fFound =
false;
2811 if (hrange == -1) hrange = std::max(wdt / 4, 5);
2813 int32_t cx1, cx2, cy1, cy2, rh1, rh2, rl1, rl2;
2820 cx2 = std::max(rx - wdt / 2, 0); cy2 = ry;
2824 rh1 = cy1; rh2 = cy2; rl1 = rl2 = 0;
2861 if (rl1 >= wdt)
if (cx1 > 0)
2864 rx = cx1 + wdt / 2; ry = cy1; fFound =
true;
break;
2869 rx = cx2 - wdt / 2; ry = cy2; fFound =
true;
break;
2884 bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
2889 bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix, int32_t *iy)
2892 bool reverse =
false;
2893 bool steep =
Abs(y2 - y1) >
Abs(x2 - x1);
2910 int32_t deltax = x2 - x1;
2911 int32_t deltay =
Abs(y2 - y1);
2913 int32_t ystep = (y1 < y2) ? 1 : -1;
2916 for (int32_t
x = x1;
x <= x2;
x++)
2922 if (ix) { *ix =
y; *iy =
x; }
2930 if (ix) { *ix =
x; *iy =
y; }
2936 if (2 * error >= deltax)
2945 int32_t deltax = x2 - x1;
2946 int32_t deltay =
Abs(y2 - y1);
2948 int32_t ystep = (y1 < y2) ? 1 : -1;
2952 for (int32_t
x = x2;
x >= x1;
x--)
2958 if (ix) { *ix =
y; *iy =
x; }
2966 if (ix) { *ix =
x; *iy =
y; }
2972 if (2 * error <= -deltax)
2997 int32_t iClosest =
Distance(iFx, iFy, iTx, iTy);
3004 if (cdis < iClosest) iClosest = cdis;
3005 cx += iXDir; cy += iYDir; iYDir +=
GravAccel;
3010 static constexpr int32_t
3011 Throwing_MaxVertical = 50,
3012 Throwing_MaxHorizontal = 60;
3022 if (!
Inside(rY - iTy, -Throwing_MaxVertical, +Throwing_MaxVertical))
return false;
3025 int32_t iDir = +1;
if (fXDir > 0) iDir = -1;
3028 for (int32_t cnt = 0; Inside<int32_t>(rX, 0, ::
Landscape.
GetWidth() - 1) && (cnt <= Throwing_MaxHorizontal); rX += iDir, cnt++)
3037 if (itjd <= 2)
return true;
3045 static constexpr int32_t
3046 Closest_MaxRange = 200,
3050 int32_t iExcludeAngle1, int32_t iExcludeAngle2)
3053 for (int32_t iR = Closest_Step; iR < Closest_MaxRange; iR += Closest_Step)
3054 for (int32_t iAngle = iAngle1; iAngle < iAngle2; iAngle += Closest_Step)
3055 if (!
Inside(iAngle, iExcludeAngle1, iExcludeAngle2))
3063 rX = iX; rY = iY;
return true;
3073 if (!(ndef = PropList->
GetDef()))
3085 int32_t rtx, rty, wdt, hgt;
3087 rtx = iX - wdt / 2; rty = iY - hgt;
3114 bool fLeft =
true, fRight =
true;
3117 if (
GetDensity(fx, fy + ydir) < mdens) { fy += ydir;
return true; }
3120 for (cslide = 1; (cslide <= mslide) && (fLeft || fRight); cslide++)
3127 else if (
GetDensity(fx - cslide, fy + ydir) < mdens)
3137 else if (
GetDensity(fx + cslide, fy + ydir) < mdens)
3152 bool fLeft =
true, fRight =
true;
3155 if (
GetDensity(fx, fy + ydir) < mdens) { fy += ydir;
return true; }
3158 for (cslide = 1; (cslide <= mslide) && (fLeft || fRight); cslide++)
3165 else if (
GetDensity(fx - cslide, fy + ydir) < mdens)
3167 fx -= cslide; fy += ydir;
return true;
3175 else if (
GetDensity(fx + cslide, fy + ydir) < mdens)
3177 fx += cslide; fy += ydir;
return true;
3191 fx = Clamp<int32_t>(fx, 0,
GetWidth() - 1);
3192 fy = Clamp<int32_t>(fy, 0,
GetHeight() - 1);
3194 const int32_t iPushRange = 500;
3195 int32_t
left = std::max<int32_t>(0, fx - iPushRange),
right = std::min<int32_t>(
GetWidth() - 1, fx + iPushRange),
3196 top = std::max<int32_t>(0, fy - iPushRange),
bottom = std::min<int32_t>(
GetHeight() - 1, fy + iPushRange);
3198 const int8_t R = 0, D = 1, L = 2, U = 3;
3200 int32_t
x = fx,
y = fy;
3207 else if (dens == mdens)
3210 for (int32_t i = 0; ; i++)
3213 x -= i; dir = L;
break;
3217 y -= i; dir = U;
break;
3221 x += i; dir = R;
break;
3225 y += i; dir = D;
break;
3233 for (; i < iPushRange; i++)
3237 x -= i; dir = R;
break;
3241 y -= i; dir = D;
break;
3245 x += i; dir = L;
break;
3249 y += i; dir = U;
break;
3253 if (i >= iPushRange)
return false;
3262 int32_t sx =
x, sy =
y, sdir = dir;
3264 bool fGotBest =
false; int32_t bx = 0, by = 0, bdist = 0;
3274 case R: nx++;
break;
3275 case D: ny++;
break;
3276 case L: nx--;
break;
3277 case U: ny--;
break;
3278 default: assert(
false);
3288 int32_t dist =
Abs(nx - fx) + mslide * (liquid ? fy - ny :
Abs(fy - ny));
3290 if (!fGotBest || dist < bdist)
3293 bx = nx; by = ny; bdist = dist; fGotBest =
true;
3295 top = std::max<int32_t>(
top, fy - dist / mslide - 1);
3298 bottom = std::min<int32_t>(
bottom, fy + dist / mslide + 1);
3299 left = std::max<int32_t>(
left, fx - dist - 1);
3300 right = std::min<int32_t>(
right, fx + dist + 1);
3303 sx =
x; sy =
y; sdir = dir;
3307 if (fInBounds && dens == mdens)
3320 }
while (
x != sx ||
y != sy || dir != sdir);
3322 if (!fGotBest)
return false;
3330 int32_t cx, cy, ascnt = 0;
3331 for (cy =
y; cy <
y + hgt; cy++)
3332 for (cx =
x; cx <
x + wdt; cx++)
3340 int32_t mslide, cslide, tslide, distant_x = 0;
3352 fLeft =
true; fRight =
true; tslide = 0; distant_x =
x;
3353 for (cslide = 1; (cslide <= mslide) && (fLeft || fRight); cslide++)
3358 if (
GetMat(
x - cslide,
y) != mat) fLeft =
false;
3361 distant_x =
x - cslide;
3362 if (
GetMat(distant_x,
y - 1) == mat) { tslide = -cslide;
break; }
3368 if (
GetMat(
x + cslide,
y) != mat) fRight =
false;
3371 distant_x =
x + cslide;
3372 if (
GetMat(distant_x,
y - 1) == mat) { tslide = +cslide;
break; }
3378 if (tslide) {
x += tslide;
y--; }
3383 if (distant_first)
x = distant_x;
3409 if (!rbyCol)
return false;
3415 bool C4Landscape::DrawBrush(int32_t iX, int32_t iY, int32_t iGrade,
const char *szMaterial,
const char *szTexture,
const char *szBackMaterial,
const char *szBackTexture)
3417 BYTE byCol, byColBkg;
3419 if (!p->GetMapColorIndex(szMaterial, szTexture, byCol))
return false;
3420 if (!p->GetMapColorIndex(szBackMaterial, szBackTexture, byColBkg))
return false;
3423 int32_t shape_wdt = 0, shape_hgt = 0;
3439 int32_t iRadius = std::max<int32_t>(2 * iGrade / p->MapZoom, 1);
3442 p->Map->SetPix(iX / p->MapZoom, iY / p->MapZoom, byCol);
3443 p->MapBkg->SetPix(iX / p->MapZoom, iY / p->MapZoom, byColBkg);
3447 p->Map->Circle(iX / p->MapZoom, iY / p->MapZoom, iRadius, byCol);
3448 p->MapBkg->Circle(iX / p->MapZoom, iY / p->MapZoom, iRadius, byColBkg);
3451 p->MapToLandscape(
this, *p->Map, *p->MapBkg, iX / p->MapZoom - iRadius - 1 - shape_wdt, iY / p->MapZoom - iRadius - 1 - shape_hgt, 2 * iRadius + 2 + shape_wdt * 2, 2 * iRadius + 2 + shape_hgt * 2);
3458 C4Rect BoundingBox(iX - iGrade - 1, iY - iGrade - 1, iGrade * 2 + 2, iGrade * 2 + 2);
3460 p->PrepareChange(
this, BoundingBox);
3461 p->Surface8->Circle(iX, iY, iGrade, byCol);
3462 p->Surface8Bkg->Circle(iX, iY, iGrade, byColBkg);
3463 p->FinishChange(
this, BoundingBox);
3473 Surface8->Circle(iX, iY, iGrade, line_color);
3474 Surface8Bkg->Circle(iX, iY, iGrade, line_color_bkg);
3480 if (!Map)
return false;
3483 Map->SetPix(iX, iY, line_color); MapBkg->SetPix(iX, iY, line_color_bkg);
3487 Map->Circle(iX, iY, iRadius, line_color); MapBkg->Circle(iX, iY, iRadius, line_color_bkg);
3492 bool C4Landscape::DrawLine(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iGrade,
const char *szMaterial,
const char *szTexture,
const char *szBackMaterial,
const char *szBackTexture)
3495 uint8_t line_color, line_color_bkg;
3496 if (!p->GetMapColorIndex(szMaterial, szTexture, line_color))
return false;
3497 if (!p->GetMapColorIndex(szBackMaterial, szBackTexture, line_color_bkg))
return false;
3500 int32_t shape_wdt = 0, shape_hgt = 0;
3516 int32_t iRadius = std::max<int32_t>(2 * iGrade / p->MapZoom, 1);
3517 iX1 /= p->MapZoom; iY1 /= p->MapZoom; iX2 /= p->MapZoom; iY2 /= p->MapZoom;
3518 ForLine(iX1, iY1, iX2, iY2, [
this, line_color, line_color_bkg, iRadius](int32_t
x, int32_t
y) {
return p->DrawLineMap(
x,
y, iRadius, line_color, line_color_bkg); });
3520 int iUpX = std::min(iX1, iX2) - iRadius - 1;
3521 int iUpY = std::min(iY1, iY2) - iRadius - 1;
3522 int iUpWdt =
Abs(iX2 - iX1) + 2 * iRadius + 2;
3523 int iUpHgt =
Abs(iY2 - iY1) + 2 * iRadius + 2;
3524 p->MapToLandscape(
this, *p->Map, *p->MapBkg, iUpX - shape_wdt, iUpY - shape_hgt, iUpWdt + shape_wdt * 2, iUpHgt + shape_hgt * 2);
3532 C4Rect BoundingBox(iX1 - iGrade, iY1 - iGrade, iGrade * 2 + 1, iGrade * 2 + 1);
3533 BoundingBox.
Add(
C4Rect(iX2 - iGrade, iY2 - iGrade, iGrade * 2 + 1, iGrade * 2 + 1));
3535 p->PrepareChange(
this, BoundingBox);
3536 ForLine(iX1, iY1, iX2, iY2, [
this, line_color, line_color_bkg, iGrade](int32_t
x, int32_t
y) {
return p->DrawLineLandscape(
x,
y, iGrade, line_color, line_color_bkg); });
3537 p->FinishChange(
this, BoundingBox);
3545 bool C4Landscape::DrawBox(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iGrade,
const char *szMaterial,
const char *szTexture,
const char *szBackMaterial,
const char *szBackTexture)
3548 int32_t iX0 = std::min(iX1, iX2); int32_t iY0 = std::min(iY1, iY2);
3549 iX2 = std::max(iX1, iX2); iY2 = std::max(iY1, iY2); iX1 = iX0; iY1 = iY0;
3550 BYTE byCol, byColBkg;
3552 if (!p->GetMapColorIndex(szMaterial, szTexture, byCol))
return false;
3553 if (!p->GetMapColorIndex(szBackMaterial, szBackTexture, byColBkg))
return false;
3556 int32_t shape_wdt = 0, shape_hgt = 0;
3571 iX1 /= p->MapZoom; iY1 /= p->MapZoom; iX2 /= p->MapZoom; iY2 /= p->MapZoom;
3572 p->Map->Box(iX1, iY1, iX2, iY2, byCol);
3573 p->MapBkg->Box(iX1, iY1, iX2, iY2, byColBkg);
3575 p->MapToLandscape(
this, *p->Map, *p->MapBkg, iX1 - 1 - shape_wdt, iY1 - 1 - shape_hgt, iX2 - iX1 + 3 + shape_wdt * 2, iY2 - iY1 + 3 + shape_hgt * 2);
3581 C4Rect BoundingBox(iX1, iY1, iX2 - iX1 + 1, iY2 - iY1 + 1);
3583 p->PrepareChange(
this, BoundingBox);
3584 p->Surface8->Box(iX1, iY1, iX2, iY2, byCol);
3585 p->Surface8Bkg->Box(iX1, iY1, iX2, iY2, byColBkg);
3586 p->FinishChange(
this, BoundingBox);
3594 bool C4Landscape::DrawChunks(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t icntx, int32_t icnty,
const char *szMaterial,
const char *szTexture,
bool bIFT)
3597 if (!p->GetMapColorIndex(szMaterial, szTexture, byColor))
return false;
3605 C4Rect BoundingBox(tx - 5, ty - 5, wdt + 10, hgt + 10);
3606 p->PrepareChange(
this, BoundingBox);
3609 p->Surface8->Clip(BoundingBox.
x, BoundingBox.
y, BoundingBox.
x + BoundingBox.
Wdt, BoundingBox.
y + BoundingBox.
Hgt);
3610 p->Surface8Bkg->Clip(BoundingBox.
x, BoundingBox.
y, BoundingBox.
x + BoundingBox.
Wdt, BoundingBox.
y + BoundingBox.
Hgt);
3615 for (
x = 0;
x < icntx;
x++)
3616 for (
y = 0;
y < icnty;
y++)
3617 p->DrawChunk(
this, tx + wdt*
x / icntx, ty + hgt*
y / icnty, wdt / icntx, hgt / icnty, byColor, bIFT ? p->DefaultBkgMat(byColor) : 0, shape,
Random(1000));
3620 p->Surface8->NoClip();
3621 p->Surface8Bkg->NoClip();
3623 p->FinishChange(
this, BoundingBox);
3631 if (length < 6)
return false;
3632 if (length % 2 == 1)
return false;
3635 if (!iMatTex)
return false;
3638 uint8_t mcolBkg = 0;
3639 if (szBackMaterial !=
nullptr)
3642 if (!iBackMatTex)
return false;
3646 uint8_t *conversion_map =
nullptr;
3649 conversion_map = p->GetBridgeMatConversion(
this,
MatTex2PixCol(iMatTex));
3653 C4Rect BoundingBox = getBoundingBox(vtcs, length);
3655 p->PrepareChange(
this, BoundingBox);
3656 p->ForPolygon(
this, vtcs, length / 2,
nullptr,
nullptr, mcol, mcolBkg, conversion_map);
3657 p->FinishChange(
this, BoundingBox);
3663 return p->Surface8 ? p->Surface8->pPal :
nullptr;
3696 return p->Surface8->_GetPix(
x,
y);
3707 if (
static_cast<uint32_t
>(
x) >=
static_cast<uint32_t
>(p->Width))
3713 return p->TopRowPix[
x];
3715 if (
static_cast<uint32_t
>(
y) >=
static_cast<uint32_t
>(p->Height))
3717 return p->BottomRowPix[
x];
3719 return p->Surface8->_GetPix(
x,
y);
3757 return p->Surface8Bkg->_GetPix(
x,
y);
3767 if (
static_cast<uint32_t
>(
x) >=
static_cast<uint32_t
>(
GetWidth()))
3773 return p->DefaultBkgMat(p->TopRowPix[
x]);
3775 if (
static_cast<uint32_t
>(
y) >=
static_cast<uint32_t
>(
GetHeight()))
3777 return p->DefaultBkgMat(p->BottomRowPix[
x]);
3780 return p->Surface8Bkg->_GetPix(
x,
y);
3825 return p->PixCnt[(
x / 17) * p->PixCntPitch + (
y / 15)] > 0;
3830 return (
x / 17) * 17 + 17;
3839 x /= 17;
y /= 15; x2 /= 17; y2 /= 15;
3840 while (
x != x2 &&
y != y2)
3842 if (p->PixCnt[
x * p->PixCntPitch +
y])
3844 if (
x > x2)
x--;
else x++;
3845 if (
y > y2)
y--;
else y++;
3850 if (p->PixCnt[
x * p->PixCntPitch +
y])
3852 if (
x > x2)
x--;
else x++;
3857 if (p->PixCnt[
x * p->PixCntPitch +
y])
3859 if (
y > y2)
y--;
else y++;
3861 return !p->PixCnt[
x * p->PixCntPitch +
y];
3867 int32_t for_material = d->
GetPixMat(for_material_col);
3868 if (for_material < 0 || for_material >=
MaterialMap.
Num)
return nullptr;
3870 if (!BridgeMatConversion[for_material_col])
3878 conv_map[i] = for_material_col;
3886 BridgeMatConversion[for_material_col] = std::move(conv_map);
3888 return BridgeMatConversion[for_material_col].get();
3891 bool C4Landscape::DrawQuad(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iX3, int32_t iY3, int32_t iX4, int32_t iY4,
const char *szMaterial,
const char *szBackMaterial,
bool fDrawBridge)
3895 vtcs[0] = iX1; vtcs[1] = iY1;
3896 vtcs[2] = iX2; vtcs[3] = iY2;
3897 vtcs[4] = iX3; vtcs[5] = iY3;
3898 vtcs[6] = iX4; vtcs[7] = iY4;
3899 return DrawPolygon(vtcs, 8, szMaterial, szBackMaterial, fDrawBridge);
3904 if (!p->Map)
return 0;
3905 return p->Map->GetPix(iX, iY);
3910 if (!p->MapBkg)
return 0;
3911 return p->MapBkg->GetPix(iX, iY);
3917 C4Rect SolidMaskRect = BoundingBox;
3918 if (pLandscapeRender)
3919 SolidMaskRect = pLandscapeRender->GetAffectedRect(pLandscapeRender->GetAffectedRect(SolidMaskRect));
3922 pSolid->RemoveTemporary(SolidMaskRect);
3924 if (updateMatCnt) UpdateMatCnt(d, BoundingBox,
false);
3931 if (!BoundingBox.
Wdt || !BoundingBox.
Hgt)
return;
3933 if (pLandscapeRender)
3934 pLandscapeRender->Update(BoundingBox, d);
3935 if (updateMatAndPixCnt) UpdateMatCnt(d, BoundingBox,
true);
3937 C4Rect SolidMaskRect = BoundingBox;
3938 if (pLandscapeRender)
3939 SolidMaskRect = pLandscapeRender->GetAffectedRect(pLandscapeRender->GetAffectedRect(SolidMaskRect));
3942 pSolid->Repair(SolidMaskRect);
3945 if (updateMatAndPixCnt) UpdatePixCnt(d, BoundingBox);
3949 pFoW->Invalidate(BoundingBox);
3950 pFoW->Ambient.UpdateFromLandscape(*d, BoundingBox);
3959 bool C4Landscape::DrawMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt,
const char *szMapDef,
bool ignoreSky)
3962 if (!szMapDef)
return false;
3964 if (!
ClipRect(iX, iY, iWdt, iHgt))
return false;
3966 int32_t iMapWdt = (iWdt - 1) / p->MapZoom + 1;
3967 int32_t iMapHgt = (iHgt - 1) / p->MapZoom + 1;
3969 FakeLS.
MapWdt.
Set(iMapWdt, 0, iMapWdt, iMapWdt);
3970 FakeLS.
MapHgt.
Set(iMapHgt, 0, iMapHgt, iMapHgt);
3978 if (!MapCreator.
Render(
nullptr, sfcMap, sfcMapBkg))
3981 bool fSuccess = p->MapToLandscape(
this, *sfcMap, *sfcMapBkg, 0, 0, iMapWdt, iMapHgt, iX, iY, ignoreSky);
3992 if (!szMapDef || !p->pMapCreator)
return false;
3994 if (!
ClipRect(iX, iY, iWdt, iHgt))
return false;
3996 int32_t iMapWdt = (iWdt - 1) / p->MapZoom + 1;
3997 int32_t iMapHgt = (iHgt - 1) / p->MapZoom + 1;
3998 bool fSuccess =
false;
4000 C4MCMap *pMap = p->pMapCreator->GetMap(szMapDef);
4001 if (!pMap)
return false;
4002 pMap->
SetSize(iMapWdt, iMapHgt);
4005 if (p->pMapCreator->Render(szMapDef, sfcMap, sfcMapBkg))
4008 fSuccess = p->MapToLandscape(
this, *sfcMap, *sfcMapBkg, 0, 0, iMapWdt, iMapHgt, iX, iY, ignoreSky);
4021 p->Modulation = dwWithClr;
4030 if (rX < 0) { rWdt += rX; rX = 0; }
4031 if (rY < 0) { rHgt += rY; rY = 0; }
4043 return rWdt > 0 && rHgt > 0;
4049 if (!p->Map)
return false;
4050 int iPitch, iMapWdt, iMapHgt;
4051 BYTE *pMap = p->Map->Bits;
4052 iMapWdt = p->Map->Wdt;
4053 iMapHgt = p->Map->Hgt;
4054 iPitch = p->Map->Pitch;
4055 if (!pMap)
return false;
4056 for (int32_t
y = 0;
y < iMapHgt; ++
y)
4058 for (int32_t
x = 0;
x < iMapWdt; ++
x)
4060 if (*pMap == iOldIndex)
4064 pMap += iPitch - iMapWdt;
4071 if (((!szMatTex || !*szMatTex) && !fInsert) || !Inside<int>(iNewIndex, 1,
C4M_MaxTexIndex - 1))
4073 DebugLogF(
"Cannot insert new texture %s to index %d: Invalid parameters.", (
const char *)szMatTex, (
int)iNewIndex);
4086 if (--byLastMoveIndex == iNewIndex)
4088 DebugLogF(
"Cannot insert new texture %s to index %d: No room for insertion.", (
const char *)szMatTex, (
int)iNewIndex);
4093 while (--byLastMoveIndex >= iNewIndex)
4100 if (szMatTex && *szMatTex)
4115 LogF(
"Cannot insert new texture %s to index %d: Texture map entry error", (
const char *)szMatTex, (
int)iNewIndex);
4135 DebugLogF(
"Cannot move texture %s to index %d: Texture not found.", (
const char *)szMatTex, (
int)iNewIndex);
4157 fTexUsage[iMatTex] =
false;
4161 const BYTE pix = p->Surface8->GetPix(
x,
y);
4162 const BYTE backPix = p->Surface8Bkg->GetPix(
x,
y);
4166 fTexUsage[pix] =
true;
4167 fTexUsage[backPix] =
true;
4181 if (!fTexUsage[iMatTex])
4194 return p->pFoW !=
nullptr;
4199 return p->pFoW.get();
4204 assert(material >= 0 && (
unsigned) material < p->MatCount.size());
4205 return p->MatCount[material];
4210 assert(material >= 0 && (
unsigned) material < p->EffectiveMatCount.size());
4211 return p->EffectiveMatCount[material];
4233 p->Pix2Place[0] = 0;
4235 std::fill(p->BridgeMatConversion.begin(), p->BridgeMatConversion.end(),
nullptr);
4240 if (!Surface8 || !Surface8Bkg)
return false;
4246 if (!pTex || pTex->
isNull())
4260 int32_t PixCntWidth = (Width + 16) / 17;
4261 for (int32_t
y = std::max<int32_t>(0, Rect.
y / 15); y < std::min<int32_t>(PixCntPitch, (Rect.
y + Rect.
Hgt + 14) / 15);
y++)
4262 for (int32_t
x = std::max<int32_t>(0, Rect.
x / 17); x < std::min<int32_t>(PixCntWidth, (Rect.
x + Rect.
Wdt + 16) / 17);
x++)
4265 for (int32_t x2 =
x * 17; x2 < std::min<int32_t>(
x * 17 + 17, Width); x2++)
4266 for (int32_t y2 =
y * 15; y2 < std::min<int32_t>(
y * 15 + 15, Height); y2++)
4270 assert(
iCnt == PixCnt[
x * PixCntPitch +
y]);
4271 PixCnt[
x * PixCntPitch +
y] =
iCnt;
4278 if (!Rect.
Hgt || !Rect.
Wdt)
return;
4280 const int32_t iMul = fPlus ? +1 : -1;
4282 for (int32_t
x = 0;
x < Rect.
Wdt;
x++)
4286 for (
y = 1;
y < Rect.
Hgt;
y++)
4288 int32_t iMat = d->
_GetMat(Rect.
x +
x, Rect.
y +
y - 1);
4297 MatCount[iMat] += iMul * (iHgt + 1);
4302 int iAddedHeight = 0;
4303 if (Rect.
y && iHgt + 1 ==
y)
4304 iAddedHeight = d->
GetMatHeight(Rect.
x +
x, Rect.
y - 1, -1, iMat, iMinHgt);
4306 if (iHgt + 1 + iAddedHeight >= iMinHgt)
4308 EffectiveMatCount[iMat] += iMul * (iHgt + 1);
4309 if (iAddedHeight < iMinHgt)
4310 EffectiveMatCount[iMat] += iMul * iAddedHeight;
4319 int32_t iMat = d->
_GetMat(Rect.
x +
x, Rect.
y + Rect.
Hgt - 1);
4323 MatCount[iMat] += iMul * (iHgt + 1);
4327 int iAddedHeight1 = 0, iAddedHeight2 = 0;
4329 if (Rect.
y && iHgt + 1 == Rect.
Hgt)
4330 iAddedHeight1 = d->
GetMatHeight(Rect.
x +
x, Rect.
y - 1, -1, iMat, iMinHgt);
4332 if (Rect.
y +
y < Height)
4337 EffectiveMatCount[iMat] += iMul * (iHgt + 1);
4338 if (iAddedHeight1 < iMinHgt)
4339 EffectiveMatCount[iMat] += iMul * iAddedHeight1;
4340 if (iAddedHeight2 < iMinHgt)
4341 EffectiveMatCount[iMat] += iMul * iAddedHeight2;
#define C4CFN_LandscapeFg
#define C4CFN_DiffLandscape
#define C4CFN_TempLandscapeBkg
#define C4CFN_DiffLandscapeBkg
#define C4CFN_TempLandscape
#define C4CFN_LandscapeBg
#define C4CFN_DynLandscape
const int32_t C4M_Vehicle
const int C4M_MaxTexIndex
const uint32_t OCF_InSolid
void GameMsgObjectError(const char *szText, C4Object *pTarget, bool Red)
C4AulScriptEngine ScriptEngine
C4GraphicsSystem GraphicsSystem
C4GraphicsResource GraphicsResource
constexpr bool DEBUGREC_MATSCAN
bool FindLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height)
CPolyEdge QuickPolyBuf[QuickPolyBufSize]
bool FindTunnelHeight(int32_t cx, int32_t &ry, int32_t hgt)
bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt, int32_t hrange)
bool FindSurfaceLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height)
bool AboveSolid(int32_t &rx, int32_t &ry)
bool PathFreeIgnoreVehiclePix(int32_t x, int32_t y)
const int QuickPolyBufSize
bool FindLiquidHeight(int32_t cx, int32_t &ry, int32_t hgt)
bool PathFreePix(int32_t x, int32_t y)
bool PathFreeIgnoreVehicle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix, int32_t *iy)
bool FindTunnel(int32_t &rx, int32_t &ry, int32_t width, int32_t height)
#define POLYGON_FIX_SHIFT
int32_t TrajectoryDistance(int32_t iFx, int32_t iFy, C4Real iXDir, C4Real iYDir, int32_t iTx, int32_t iTy)
bool FindThrowingPosition(int32_t iTx, int32_t iTy, C4Real fXDir, C4Real fYDir, int32_t iHeight, int32_t &rX, int32_t &rY)
bool FindSolidGround(int32_t &rx, int32_t &ry, int32_t width)
bool ConstructionCheck(C4PropList *PropList, int32_t iX, int32_t iY, C4Object *pByObj)
bool AboveSemiSolid(int32_t &rx, int32_t &ry)
bool SemiAboveSolid(int32_t &rx, int32_t &ry)
bool FindLevelGround(int32_t &rx, int32_t &ry, int32_t width, int32_t hrange)
bool FindClosestFree(int32_t &rX, int32_t &rY, int32_t iAngle1, int32_t iAngle2, int32_t iExcludeAngle1, int32_t iExcludeAngle2)
int32_t PixCol2Mat(BYTE pixc)
bool GBackLiquid(int32_t x, int32_t y)
int32_t PixCol2Tex(BYTE pixc)
bool DensitySolid(int32_t dens)
bool GBackSemiSolid(int32_t x, int32_t y)
int32_t GBackMat(int32_t x, int32_t y)
const int32_t C4LS_MaxRelights
bool GBackSolid(int32_t x, int32_t y)
const char * LoadResStr(const char *id)
bool LogF(const char *strMessage,...)
bool LogFatal(const char *szMessage)
bool DebugLogF(const char *strMessage ...)
C4MapScriptHost MapScript
C4MaterialMap MaterialMap
BYTE MatTex2PixCol(int32_t tex)
bool MatValid(int32_t mat)
bool MatVehicle(int32_t iMat)
BYTE Mat2PixColDefault(int32_t mat)
int32_t MatDensity(int32_t mat)
const C4Real DefaultGravAccel
C4Fixed itofix(int32_t x)
C4Real Cos(const C4Real &fAngle)
int fixtoi(const C4Fixed &x)
C4Real Sin(const C4Real &fAngle)
void AddDbgRec(C4RecordChunkType eType, const void *pData, int iSize)
C4Value C4VObj(C4Object *pObj)
C4Value C4VInt(int32_t i)
const char * SSearch(const char *szString, const char *szIndex)
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
int32_t Distance(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2)
T Clamp(T bval, T lbound, T rbound)
bool SEqual(const char *szStr1, const char *szStr2)
bool Inside(T ival, U lbound, V rbound)
StdCastAdapt< T, int32_t > mkCastIntAdapt(T &rValue)
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
StdStrBuf FormatString(const char *szFmt,...)
bool EraseItem(const char *szItemName)
void MakeTempFilename(char *szFilename)
C4PropListStatic * GetPropList()
const char * AtTempPath(const char *filename)
void DeactivateBlitModulation()
void Blit8Fast(CSurface8 *sfcSource, int fx, int fy, C4Surface *sfcTarget, int tx, int ty, int wdt, int hgt)
void ActivateBlitModulation(DWORD dwWithClr)
C4ValueArray * FindMany(const C4ObjectList &Objs)
void FixRandom(uint64_t seed)
void SetInitProgress(float to_progress)
C4Object * FindConstuctionSiteBlock(int32_t x, int32_t y, int32_t wdt, int32_t hgt)
int32_t StartupPlayerCount
C4Object * CreateObject(C4PropList *type, C4Object *creator, int32_t owner=NO_OWNER, int32_t x=50, int32_t y=50, int32_t r=0, bool grow_from_center=false, C4Real xdir=Fix0, C4Real ydir=Fix0, C4Real rdir=Fix0, int32_t controller=NO_OWNER)
void CastObjects(C4ID id, C4Object *creator, int32_t num, int32_t level, int32_t x, int32_t y, int32_t owner=NO_OWNER, int32_t controller=NO_OWNER, C4ValueArray *out_objects=nullptr)
bool AccessEntry(const char *wildcard, size_t *size=nullptr, char *filename=nullptr, bool needs_to_be_a_group=false)
bool OpenAsChild(C4Group *mother, const char *entry_name, bool is_exclusive=false, bool do_create=false)
bool Move(const char *filename, const char *entry_name)
bool FindEntry(const char *wildcard, StdStrBuf *filename=nullptr, size_t *size=nullptr)
bool Open(const char *group_name, bool do_create=false)
int32_t GetPlacement(int32_t x, int32_t y) const
BYTE GetMapIndex(int32_t iX, int32_t iY) const
bool DrawBox(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iGrade, const char *szMaterial, const char *szTexture, const char *szBackMaterial, const char *szBackTexture)
C4Real GetGravity() const
LandscapeMode GetMode() const
void RaiseTerrain(int32_t tx, int32_t ty, int32_t wdt)
bool DrawMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, const char *szMapDef, bool ignoreSky=false)
bool DrawLine(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iGrade, const char *szMaterial, const char *szTexture, const char *szBackMaterial, const char *szBackTexture)
bool InsertMaterialOutsideLandscape(int32_t tx, int32_t ty, int32_t mdens)
int32_t GetEffectiveMatCount(int material) const
int32_t DigFreeRect(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, C4Object *by_object=nullptr, bool no_dig2objects=false, bool no_instability_check=false)
BYTE GetPix(int32_t x, int32_t y) const
int32_t ExtractMaterial(int32_t fx, int32_t fy, bool distant_first)
bool GetLight(int32_t x, int32_t y)
int32_t GetDensity(int32_t x, int32_t y) const
int32_t GetPixMat(BYTE byPix) const
BYTE GetBackPix(int32_t x, int32_t y) const
BYTE _GetPix(int32_t x, int32_t y) const
bool FindMatPathPush(int32_t &fx, int32_t &fy, int32_t mdens, int32_t mslide, bool liquid) const
bool FindMatPath(int32_t &fx, int32_t &fy, int32_t ydir, int32_t mdens, int32_t mslide) const
static const uint8_t Transparent
bool DrawQuad(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iX3, int32_t iY3, int32_t iX4, int32_t iY4, const char *szMaterial, const char *szBackMaterial, bool fDrawBridge)
bool InsertDeadMaterial(int32_t mat, int32_t tx, int32_t ty)
BYTE _GetBackPix(int32_t x, int32_t y) const
bool _SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix)
void Clear(bool fClearMapCreator=true, bool fClearSky=true, bool fClearRenderer=true)
void ClearFreeRect(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt)
void SetGravity(C4Real g)
bool FindMatSlide(int32_t &fx, int32_t &fy, int32_t ydir, int32_t mdens, int32_t mslide) const
bool ReplaceMapColor(BYTE iOldIndex, BYTE iNewIndex)
bool DrawChunks(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t icntx, int32_t icnty, const char *szMaterial, const char *szTexture, bool bIFT)
void BlastFreeShape(int *vtcs, int length, C4Object *by_object=nullptr, int32_t by_player=NO_OWNER, int32_t iMaxDensity=C4M_Vehicle)
int32_t GetBackMat(int32_t x, int32_t y) const
CStdPalette * GetPal() const
int32_t GetHeight() const
void FindMatTop(int32_t mat, int32_t &x, int32_t &y, bool distant_first) const
bool Save(C4Group &hGroup) const
int32_t AreaSolidCount(int32_t x, int32_t y, int32_t wdt, int32_t hgt) const
bool _FastSolidCheck(int32_t x, int32_t y) const
int32_t _GetMat(int32_t x, int32_t y) const
int32_t GetMat(int32_t x, int32_t y) const
int32_t GetPixDensity(BYTE byPix) const
void CheckInstabilityRange(int32_t tx, int32_t ty)
bool InsertMaterial(int32_t mat, int32_t *tx, int32_t *ty, int32_t vx=0, int32_t vy=0, bool query_only=false)
int32_t _GetBackPlacement(int32_t x, int32_t y) const
bool ClearPix(int32_t tx, int32_t ty)
void SetMode(LandscapeMode iMode)
bool Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bool &rfLoaded, bool fSavegame)
int32_t GetBackPlacement(int32_t x, int32_t y) const
bool CheckInstability(int32_t tx, int32_t ty, int32_t recursion_count=0)
int32_t _GetPlacement(int32_t x, int32_t y) const
bool DrawBrush(int32_t iX, int32_t iY, int32_t iGrade, const char *szMaterial, const char *szTexture, const char *szBackMaterial, const char *szBackTexture)
bool DrawPolygon(int *vtcs, int length, const char *szMaterial, const char *szBackMaterial, bool fDrawBridge)
int32_t _GetBackDensity(int32_t x, int32_t y) const
bool SetTextureIndex(const char *szMatTex, BYTE iNewIndex, bool fInsert)
int32_t GetBackDensity(int32_t x, int32_t y) const
int32_t DigFree(int32_t tx, int32_t ty, int32_t rad, C4Object *by_object=nullptr, bool no_dig2objects=false, bool no_instability_check=false)
void ClearPointers(C4Object *pObj)
void ShakeFree(int32_t tx, int32_t ty, int32_t rad)
int32_t DigFreeShape(int *vtcs, int length, C4Object *by_object=nullptr, bool no_dig2objects=false, bool no_instability_check=false)
bool ApplyDiff(C4Group &hGroup)
DWORD GetModulation() const
bool ClipRect(int32_t &rX, int32_t &rY, int32_t &rWdt, int32_t &rHgt) const
void _SetPix2Tmp(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix)
static int32_t FastSolidCheckNextX(int32_t x)
int32_t GetMatCount(int material) const
int32_t GetMapZoom() const
bool DrawDefMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, const char *szMapDef, bool ignoreSky=false)
void CompileFunc(StdCompiler *pComp)
int32_t GetMatHeight(int32_t x, int32_t y, int32_t iYDir, int32_t iMat, int32_t iMax) const
void RemoveUnusedTexMapEntries()
bool SaveTextures(C4Group &hGroup) const
int32_t _GetBackMat(int32_t x, int32_t y) const
bool Incinerate(int32_t x, int32_t y, int32_t cause_player)
bool SaveDiff(C4Group &hGroup, bool fSyncSave) const
void DrawMaterialRect(int32_t mat, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt)
bool Load(C4Group &hGroup, bool fLoadSky, bool fSavegame)
bool SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix)
bool SaveMap(C4Group &hGroup) const
void BlastFree(int32_t tx, int32_t ty, int32_t rad, int32_t caused_by=NO_OWNER, C4Object *by_object=nullptr, int32_t iMaxDensity=C4M_Vehicle)
bool SetModulation(DWORD dwWithClr)
bool _PathFree(int32_t x, int32_t y, int32_t x2, int32_t y2) const
int32_t _GetDensity(int32_t x, int32_t y) const
void Draw(C4TargetFacet &cgo, class C4FoWRegion *pLight=nullptr)
BYTE GetBackMapIndex(int32_t iX, int32_t iY) const
void HandleTexMapUpdate()
bool _GetLight(int32_t x, int32_t y)
void SetSize(int32_t iWdt, int32_t iHgt)
void Create(CSurface8 *sfcMap, C4SLandscape &rLScape, C4TextureMap &rTexMap, int32_t iPlayerNum=1)
bool ReadScript(const char *szScript)
bool Render(const char *szMapName, CSurface8 *&sfcMap, CSurface8 *&sfcMapBkg)
bool InitializeMap(C4SLandscape *pLandscape, C4TextureMap *pTexMap, C4MaterialMap *pMatMap, uint32_t iPlayerCount, std::unique_ptr< CSurface8 > *pmap_fg_surface, std::unique_ptr< CSurface8 > *pmap_bg_surface)
bool Create(int32_t x, int32_t y, bool fExecute=false)
C4MaterialCoreShape MapChunkType
int32_t Blast2ObjectRatio
int32_t AboveTempConvertDir
int32_t Dig2ObjectCollect
int32_t BelowTempConvertDir
int32_t AboveTempConvertTo
int32_t BelowTempConvertTo
int32_t Amount[C4MaxMaterial]
void Add(int32_t iMaterial, int32_t iAmount)
C4MaterialReaction * GetReactionUnsafe(int32_t iPXSMat, int32_t iLandscapeMat)
int32_t Get(const char *szMaterial)
C4MaterialList * MaterialContents
void AssignRemoval(bool exit_contents=false)
bool Collect(C4Object *pObj)
void Cast(int32_t mat, int32_t num, int32_t tx, int32_t ty, int32_t level)
bool Create(int32_t mat, C4Real ix, C4Real iy, C4Real ixdir=Fix0, C4Real iydir=Fix0)
DWORD PatternClr(unsigned int iX, unsigned int iY) const
virtual const char * GetName() const
virtual C4Def const * GetDef() const
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
const char * GetName() const override
int32_t GetMiddleX() const
int32_t GetBottom() const
int32_t GetMiddleY() const
void Intersect(const C4Rect &r2)
void Add(const C4Rect &r2)
void GetMapSize(int32_t &rWdt, int32_t &rHgt, int32_t iPlayerNum)
bool LandscapeInsertThrust
void Set(int32_t std=0, int32_t rnd=0, int32_t min=0, int32_t max=100)
static C4SolidMask * Last
static void RemoveSolidMasks()
void PutTemporary(C4Rect where)
static void PutSolidMasks()
static bool CheckConsistency()
void RemoveTemporary(C4Rect where)
static C4SolidMask * First
const C4Pattern & GetPattern() const
const char * GetTextureName() const
C4Material * GetMaterial() const
int32_t GetMaterialIndex() const
const char * GetMaterialName() const
class C4TextureShape * GetMaterialShape() const
int32_t GetIndex(const char *szMaterial, const char *szTexture, bool fAddIfNotExist=true, const char *szErrorIfFailed=nullptr)
int32_t GetIndexMatTex(const char *szMaterialTexture, const char *szDefaultTexture=nullptr, bool fAddIfNotExist=true, const char *szErrorIfFailed=nullptr)
bool SaveMap(C4Group &hGroup, const char *szEntryName)
BYTE DefaultBkgMatTex(BYTE fg) const
const char * GetTexture(int32_t iIndex)
void StoreMapPalette(CStdPalette *, C4MaterialMap &rMaterials)
void MoveIndex(BYTE byOldIndex, BYTE byNewIndex)
const C4TexMapEntry * GetEntry(int32_t iIndex) const
std::vector< int32_t > Order
bool AddEntry(BYTE byIndex, const char *szMaterial, const char *szTexture)
void RemoveEntry(int32_t iIndex)
void Draw(const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX, int32_t iOffY, int32_t MapZoom, int32_t min_overlap_ratio)
int32_t GetMaxPolyHeight() const
int32_t GetMaxPolyWidth() const
const C4Value & GetItem(int32_t iElem) const
C4Object * getObj() const
BYTE _GetPix(int x, int y) const
BYTE GetPix(int iX, int iY) const
void GetSurfaceSize(int &irX, int &irY) const
void _SetPix(int iX, int iY, BYTE byCol)
void Value(const T &rStruct)
virtual bool isDeserializer()
void CopyUntil(const char *szString, char cUntil)
const char * getData() const
std::unique_ptr< BYTE[]> pInitial
void PostFreeShape(C4ValueArray *dig_objects, C4Object *by_object)
int32_t DoScan(C4Landscape *, int32_t x, int32_t y, int32_t mat, int32_t dir)
uint32_t ChunkyRandom(uint32_t &iOffset, uint32_t iRange) const
bool DigFreePixNoInstability(C4Landscape *d, int32_t tx, int32_t ty)
bool SaveInternal(const C4Landscape *d, C4Group &hGroup) const
std::array< DWORD, C4MaxMaterial > MatCount
void FinishChange(C4Landscape *d, C4Rect BoundingBox, bool updateMatAndPixCnt=true)
std::vector< uint8_t > BottomRowPix
bool DrawLineMap(int32_t iX, int32_t iY, int32_t iRadius, uint8_t line_color, uint8_t line_color_bkg)
std::array< std::unique_ptr< uint8_t[]>, C4M_MaxTexIndex > BridgeMatConversion
BYTE DefaultBkgMat(BYTE fg) const
int32_t Pix2Dens[C4M_MaxTexIndex]
bool CreateMapS2(C4Group &ScenFile, CSurface8 *&sfcMap, CSurface8 *&sfcMapBkg)
bool BlastFreePix(C4Landscape *d, int32_t tx, int32_t ty)
bool ShakeFreePix(C4Landscape *d, int32_t tx, int32_t ty)
std::unique_ptr< CSurface8 > Map
C4ValueArray * PrepareFreeShape(C4Rect &BoundingBox, C4Object *by_object)
std::array< DWORD, C4MaxMaterial > EffectiveMatCount
bool DrawLineLandscape(int32_t iX, int32_t iY, int32_t iGrade, uint8_t line_color, uint8_t line_color_bkg)
void PrepareChange(const C4Landscape *d, const C4Rect &BoundingBox, bool updateMatCnt=true)
std::unique_ptr< C4MapCreatorS2 > pMapCreator
bool SaveDiffInternal(const C4Landscape *d, C4Group &hGroup, bool fSyncSave) const
bool DigFreePix(C4Landscape *d, int32_t tx, int32_t ty)
bool CreateMap(CSurface8 *&sfcMap, CSurface8 *&sfcMapBkg)
void ChunkOZoom(C4Landscape *, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX=0, int32_t iOffY=0)
void DrawChunk(C4Landscape *, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, C4MaterialCoreShape Shape, uint32_t cro)
int32_t ForPolygon(C4Landscape *d, int *vtcs, int length, const std::function< bool(int32_t, int32_t)> &callback, C4MaterialList *mats_count=nullptr, uint8_t col=0, uint8_t colBkg=0, uint8_t *conversion_table=nullptr)
bool GetMapColorIndex(const char *szMaterial, const char *szTexture, BYTE &rbyCol) const
void ExecuteScan(C4Landscape *)
std::unique_ptr< C4FoW > pFoW
std::unique_ptr< CSurface8 > Surface8
std::vector< uint8_t > LeftColPix
uint8_t * GetBridgeMatConversion(const C4Landscape *d, int32_t for_material_col) const
void DigMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, C4Object *pCollect=nullptr)
void UpdateMatCnt(const C4Landscape *, C4Rect Rect, bool fPlus)
bool MapToSurface(C4Landscape *, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY)
std::vector< uint8_t > RightColPix
int32_t Pix2Mat[C4M_MaxTexIndex]
int32_t Pix2Place[C4M_MaxTexIndex]
std::vector< uint8_t > PixCnt
void UpdatePixCnt(const C4Landscape *, const C4Rect &Rect, bool fCheck=false)
std::unique_ptr< CSurface8 > CreateDefaultBkgSurface(CSurface8 &sfcFg, bool msbAsIft) const
void DrawSmoothOChunk(C4Landscape *, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, int flip, uint32_t cro)
std::unique_ptr< BYTE[]> pInitialBkg
std::vector< uint8_t > TopRowPix
std::unique_ptr< C4LandscapeRender > pLandscapeRender
void BlastMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, int32_t caused_by, int32_t str, C4ValueArray *out_objects)
bool TexOZoom(C4Landscape *, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, DWORD *dwpTextureUsage, int32_t iToX=0, int32_t iToY=0)
std::unique_ptr< CSurface8 > Surface8Bkg
bool Pix2Light[C4M_MaxTexIndex]
std::array< C4Rect, C4LS_MaxRelights > Relights
std::unique_ptr< CSurface8 > MapBkg
bool MapToLandscape(C4Landscape *d, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iOffsX=0, int32_t iOffsY=0, bool noClear=false)
C4MaterialReactionFunc pFunc