| 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 | |
| 29 | const uint8_t GBM = 128, |
| 30 | GBM_ColNum = 64, |
| 31 | IFT = 0x80, |
| 32 | IFTOld = GBM_ColNum; |
| 33 | |
| 34 | const uint8_t CSkyDef1 = 104; |
| 35 | |
| 36 | const int32_t C4MaxMaterial = 125; |
| 37 | |
| 38 | const int32_t C4LSC_Undefined = 0, |
| 39 | C4LSC_Dynamic = 1, |
| 40 | C4LSC_Static = 2, |
| 41 | C4LSC_Exact = 3; |
| 42 | |
| 43 | const int32_t C4LS_MaxRelights = 50; |
| 44 | |
| 45 | class C4MapCreatorS2; |
| 46 | class C4Object; |
| 47 | |
| 48 | class C4Landscape |
| 49 | { |
| 50 | public: |
| 51 | C4Landscape(); |
| 52 | ~C4Landscape(); |
| 53 | |
| 54 | public: |
| 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 | |
| 75 | protected: |
| 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 | |
| 84 | public: |
| 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 | |
| 215 | protected: |
| 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 | |
| 248 | public: |
| 249 | void CompileFunc(StdCompiler *pComp); // without landscape bitmaps and sky |
| 250 | }; |
| 251 | |
| 252 | /* Some global landscape functions */ |
| 253 | |
| 254 | bool AboveSolid(int32_t &rx, int32_t &ry); |
| 255 | bool AboveSemiSolid(int32_t &rx, int32_t &ry); |
| 256 | bool SemiAboveSolid(int32_t &rx, int32_t &ry); |
| 257 | bool FindSolidGround(int32_t &rx, int32_t &ry, int32_t width); |
| 258 | bool FindLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height); |
| 259 | bool FindSurfaceLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height); |
| 260 | bool FindLevelGround(int32_t &rx, int32_t &ry, int32_t width, int32_t hrange); |
| 261 | bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt, uint32_t category, int32_t hrange = -1); |
| 262 | bool FindThrowingPosition(int32_t iTx, int32_t iTy, C4Fixed fXDir, C4Fixed fYDir, int32_t iHeight, int32_t &rX, int32_t &rY); |
| 263 | bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix = nullptr, int32_t *iy = nullptr); |
| 264 | bool PathFreeIgnoreVehicle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix = nullptr, int32_t *iy = nullptr); |
| 265 | bool FindClosestFree(int32_t &rX, int32_t &rY, int32_t iAngle1, int32_t iAngle2, int32_t iExcludeAngle1, int32_t iExcludeAngle2); |
| 266 | bool ConstructionCheck(C4ID id, int32_t iX, int32_t iY, C4Object *pByObj = nullptr); |
| 267 | |