1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design)
5 * Copyright (c) 2017-2021, The LegacyClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16
17/* Handles landscape and sky */
18
19#pragma once
20
21#include "C4Id.h"
22#include "C4Sky.h"
23#include "C4Shape.h"
24
25#include <StdSurface8.h>
26
27#include <cstdint>
28
29const uint8_t GBM = 128,
30 GBM_ColNum = 64,
31 IFT = 0x80,
32 IFTOld = GBM_ColNum;
33
34const uint8_t CSkyDef1 = 104;
35
36const int32_t C4MaxMaterial = 125;
37
38const int32_t C4LSC_Undefined = 0,
39 C4LSC_Dynamic = 1,
40 C4LSC_Static = 2,
41 C4LSC_Exact = 3;
42
43const int32_t C4LS_MaxRelights = 50;
44
45class C4MapCreatorS2;
46class C4Object;
47
48class C4Landscape
49{
50public:
51 C4Landscape();
52 ~C4Landscape();
53
54public:
55 int32_t Mode;
56 int32_t Width, Height;
57 int32_t MapWidth, MapHeight, MapZoom;
58 CSurface8 *Map;
59 uint32_t MatCount[C4MaxMaterial]; // NoSave //
60 uint32_t EffectiveMatCount[C4MaxMaterial]; // NoSave //
61 int32_t BlastMatCount[C4MaxMaterial]; // SyncClearance-NoSave //
62 bool NoScan; // ExecuteScan() disabled
63 int32_t ScanX, ScanSpeed; // SyncClearance-NoSave //
64 int32_t LeftOpen, RightOpen;
65 bool TopOpen, BottomOpen;
66 C4Fixed Gravity;
67 uint32_t Modulation; // landscape blit modulation; 0 means normal
68 int32_t MapSeed; // random seed for MapToLandscape
69 bool ShadeMaterials; // shade materials
70 C4Sky Sky;
71 C4MapCreatorS2 *pMapCreator; // map creator for script-generated maps
72 bool fMapChanged;
73 uint8_t *pInitial; // Initial landscape after creation - used for diff
74
75protected:
76 C4Surface *Surface32;
77 C4Surface *AnimationSurface;
78 CSurface8 *Surface8;
79 int32_t Pix2Mat[256], Pix2Dens[256], Pix2Place[256];
80 int32_t PixCntPitch;
81 uint8_t *PixCnt;
82 C4Rect Relights[C4LS_MaxRelights];
83
84public:
85 void Default();
86 void Clear(bool fClearMapCreator = true, bool fClearSky = true);
87 void Execute();
88 void Synchronize();
89 void Draw(C4FacetEx &cgo, int32_t iPlayer = -1);
90 void ScenarioInit();
91 void ClearRect(int32_t iTx, int32_t iTy, int32_t iWdt, int32_t iHgt);
92 void ClearRectDensity(int32_t iTx, int32_t iTy, int32_t iWdt, int32_t iHgt, int32_t iOfDensity);
93 void ClearMatCount();
94 void ClearBlastMatCount();
95 void ScanSideOpen();
96 void CheckInstabilityRange(int32_t tx, int32_t ty);
97 void ShakeFree(int32_t tx, int32_t ty, int32_t rad);
98 void DigFree(int32_t tx, int32_t ty, int32_t rad, bool fRequest = false, C4Object *pByObj = nullptr);
99 void DigFreeRect(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, bool fRequest = false, C4Object *pByObj = nullptr);
100 void DigFreeMat(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t mat);
101 void BlastFree(int32_t tx, int32_t ty, int32_t rad, int32_t grade, int32_t iByPlayer);
102 void DrawMaterialRect(int32_t mat, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt);
103 void RaiseTerrain(int32_t tx, int32_t ty, int32_t wdt);
104 void FindMatTop(int32_t mat, int32_t &x, int32_t &y);
105 uint8_t GetMapIndex(int32_t iX, int32_t iY);
106 bool Load(C4Group &hGroup, bool fLoadSky, bool fSavegame);
107 bool Save(C4Group &hGroup);
108 bool SaveDiff(C4Group &hGroup, bool fSyncSave);
109 bool SaveMap(C4Group &hGroup);
110 bool SaveInitial();
111 bool SaveTextures(C4Group &hGroup);
112 bool Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bool &rfLoaded, bool fSavegame);
113 bool MapToLandscape();
114 bool ApplyDiff(C4Group &hGroup);
115 bool SetMode(int32_t iMode);
116 bool SetPix(int32_t x, int32_t y, uint8_t npix); // set landscape pixel (bounds checked)
117 bool SetPixDw(int32_t x, int32_t y, uint32_t dwPix); // set pixel how it is visible only
118 bool _SetPix(int32_t x, int32_t y, uint8_t npix); // set landsape pixel (bounds not checked)
119 bool _SetPixIfMask(int32_t x, int32_t y, uint8_t npix, uint8_t nMask); // set landscape pixel, if it matches nMask color (no bound-checks)
120 bool CheckInstability(int32_t tx, int32_t ty);
121 bool ClearPix(int32_t tx, int32_t ty);
122 bool InsertMaterial(int32_t mat, int32_t tx, int32_t ty, int32_t vx = 0, int32_t vy = 0);
123 bool FindMatPath(int32_t &fx, int32_t &fy, int32_t ydir, int32_t mdens, int32_t mslide);
124 bool FindMatSlide(int32_t &fx, int32_t &fy, int32_t ydir, int32_t mdens, int32_t mslide);
125 bool FindMatPathPush(int32_t &fx, int32_t &fy, int32_t mdens, int32_t mslide, bool liquid);
126 bool Incinerate(int32_t x, int32_t y);
127 bool DrawBrush(int32_t iX, int32_t iY, int32_t iGrade, const char *szMaterial, const char *szTexture, bool fIFT);
128 bool DrawLine(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iGrade, const char *szMaterial, const char *szTexture, bool fIFT);
129 bool DrawBox(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iGrade, const char *szMaterial, const char *szTexture, bool fIFT);
130 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);
131 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, bool bIFT);
132 CStdPalette *GetPal() const { return Surface8 ? Surface8->pPal : nullptr; }
133
134 inline uint8_t _GetPix(int32_t x, int32_t y) // get landscape pixel (bounds not checked)
135 {
136 return Surface8->_GetPix(x, y);
137 }
138
139 inline uint32_t _GetPixDw(int32_t x, int32_t y, bool fApplyModulation) // get landscape pixel (bounds not checked)
140 {
141 return Surface32->GetPixDw(iX: x, iY: y, fApplyModulation);
142 }
143
144 inline uint8_t GetPix(int32_t x, int32_t y) // get landscape pixel (bounds checked)
145 {
146 extern uint8_t MCVehic;
147 // Border checks
148 if (x < 0)
149 if (y < LeftOpen) return 0;
150 else return MCVehic;
151 if (x >= Width)
152 if (y < RightOpen) return 0;
153 else return MCVehic;
154 if (y < 0)
155 if (TopOpen) return 0;
156 else return MCVehic;
157 if (y >= Height)
158 if (BottomOpen) return 0;
159 else return MCVehic;
160 return Surface8->_GetPix(x, y);
161 }
162
163 inline int32_t _GetMat(int32_t x, int32_t y) // get landscape material (bounds not checked)
164 {
165 return Pix2Mat[_GetPix(x, y)];
166 }
167
168 inline int32_t _GetDensity(int32_t x, int32_t y) // get landscape density (bounds not checked)
169 {
170 return Pix2Dens[_GetPix(x, y)];
171 }
172
173 inline int32_t GetMat(int32_t x, int32_t y) // get landscape material (bounds checked)
174 {
175 return Pix2Mat[GetPix(x, y)];
176 }
177
178 inline int32_t GetDensity(int32_t x, int32_t y) // get landscape density (bounds checked)
179 {
180 return Pix2Dens[GetPix(x, y)];
181 }
182
183 inline int32_t GetPlacement(int32_t x, int32_t y) // get landscape material placement (bounds checked)
184 {
185 return Pix2Place[GetPix(x, y)];
186 }
187
188 inline int32_t GetPixMat(uint8_t byPix) { return Pix2Mat[byPix]; }
189 bool _PathFree(int32_t x, int32_t y, int32_t x2, int32_t y2); // quickly checks wether there *might* be pixel in the path.
190 int32_t GetMatHeight(int32_t x, int32_t y, int32_t iYDir, int32_t iMat, int32_t iMax);
191 int32_t DigFreePix(int32_t tx, int32_t ty);
192 int32_t ShakeFreePix(int32_t tx, int32_t ty);
193 int32_t BlastFreePix(int32_t tx, int32_t ty, int32_t grade, int32_t iBlastSize);
194 int32_t AreaSolidCount(int32_t x, int32_t y, int32_t wdt, int32_t hgt);
195 int32_t ExtractMaterial(int32_t fx, int32_t fy);
196 bool DrawMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, const char *szMapDef); // creates and draws a map section using MapCreatorS2
197 bool ClipRect(int32_t &rX, int32_t &rY, int32_t &rWdt, int32_t &rHgt); // clip given rect by landscape size; return whether anything is left unclipped
198 bool DrawDefMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, const char *szMapDef); // creates and draws a map section using MapCreatorS2 and a map from the loaded Landscape.txt
199
200 bool SetModulation(uint32_t dwWithClr) // adjust the way the landscape is blitted
201 {
202 Modulation = dwWithClr; return true;
203 }
204
205 uint32_t GetModulation() { return Modulation; }
206 bool PostInitMap(); // do script callbacks of MapCreatorS2 in finished landscape
207 bool ReplaceMapColor(uint8_t iOldIndex, uint8_t iNewIndex); // find every occurance of iOldIndex in map; replace it by new index
208 bool SetTextureIndex(const char *szMatTex, uint8_t iNewIndex, bool fInsert); // change color index of map texture, or insert a new one
209 void SetMapChanged() { fMapChanged = true; }
210 void HandleTexMapUpdate();
211 void UpdatePixMaps();
212 bool DoRelights();
213 void RemoveUnusedTexMapEntries();
214
215protected:
216 void ExecuteScan();
217 int32_t DoScan(int32_t x, int32_t y, int32_t mat, int32_t dir);
218 int32_t ChunkyRandom(int32_t &iOffset, int32_t iRange); // return static random value, according to offset and MapSeed
219 void DrawChunk(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t mcol, int32_t iChunkType, int32_t cro);
220 void DrawSmoothOChunk(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t mcol, uint8_t flip, int32_t cro);
221 void ChunkOZoom(CSurface8 *sfcMap, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iTexture, int32_t iOffX = 0, int32_t iOffY = 0);
222 bool GetTexUsage(CSurface8 *sfcMap, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint32_t *dwpTextureUsage);
223 bool TexOZoom(CSurface8 *sfcMap, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint32_t *dwpTextureUsage, int32_t iToX = 0, int32_t iToY = 0);
224 bool MapToSurface(CSurface8 *sfcMap, 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);
225 bool MapToLandscape(CSurface8 *sfcMap, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iOffsX = 0, int32_t iOffsY = 0); // zoom map segment to surface (or sector surfaces)
226 bool GetMapColorIndex(const char *szMaterial, const char *szTexture, bool fIFT, uint8_t &rbyCol);
227 bool SkyToLandscape(int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY);
228 CSurface8 *CreateMap(); // create map by landscape attributes
229 CSurface8 *CreateMapS2(C4Group &ScenFile); // create map by def file
230 bool Relight(C4Rect To);
231 bool ApplyLighting(C4Rect To);
232 bool UpdateAnimationSurface(C4Rect To);
233 uint32_t GetClrByTex(int32_t iX, int32_t iY);
234 bool Mat2Pal(); // assign material colors to landscape palette
235
236 void DigFreeSinglePix(int32_t x, int32_t y, int32_t dx, int32_t dy)
237 {
238 if (GetDensity(x, y) > GetDensity(x: x + dx, y: y + dy))
239 DigFreePix(tx: x, ty: y);
240 }
241
242 void UpdatePixCnt(const class C4Rect &Rect, bool fCheck = false);
243 void UpdateMatCnt(C4Rect Rect, bool fPlus);
244 void PrepareChange(C4Rect BoundingBox, bool updateMatCnt = true);
245 void FinishChange(C4Rect BoundingBox, bool updateMatAndPixCnt = true);
246 static bool DrawLineLandscape(int32_t iX, int32_t iY, int32_t iGrade);
247
248public:
249 void CompileFunc(StdCompiler *pComp); // without landscape bitmaps and sky
250};
251
252/* Some global landscape functions */
253
254bool AboveSolid(int32_t &rx, int32_t &ry);
255bool AboveSemiSolid(int32_t &rx, int32_t &ry);
256bool SemiAboveSolid(int32_t &rx, int32_t &ry);
257bool FindSolidGround(int32_t &rx, int32_t &ry, int32_t width);
258bool FindLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height);
259bool FindSurfaceLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height);
260bool FindLevelGround(int32_t &rx, int32_t &ry, int32_t width, int32_t hrange);
261bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt, uint32_t category, int32_t hrange = -1);
262bool FindThrowingPosition(int32_t iTx, int32_t iTy, C4Fixed fXDir, C4Fixed fYDir, int32_t iHeight, int32_t &rX, int32_t &rY);
263bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix = nullptr, int32_t *iy = nullptr);
264bool PathFreeIgnoreVehicle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix = nullptr, int32_t *iy = nullptr);
265bool FindClosestFree(int32_t &rX, int32_t &rY, int32_t iAngle1, int32_t iAngle2, int32_t iExcludeAngle1, int32_t iExcludeAngle2);
266bool ConstructionCheck(C4ID id, int32_t iX, int32_t iY, C4Object *pByObj = nullptr);
267