1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design)
5 * Copyright (c) 2017-2020, 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/* Some useful wrappers to globals */
18
19#pragma once
20
21#include <C4Id.h>
22#include <C4Game.h>
23#include <C4Landscape.h>
24#include <C4Log.h>
25
26// ID2Def
27
28inline C4Def *C4Id2Def(C4ID id)
29{
30 return Game.Defs.ID2Def(id);
31}
32
33// Graphics Resource
34
35#define GfxR (&(Game.GraphicsResource))
36
37// Ticks
38
39#define Tick2 Game.iTick2
40#define Tick3 Game.iTick3
41#define Tick5 Game.iTick5
42#define Tick10 Game.iTick10
43#define Tick35 Game.iTick35
44#define Tick255 Game.iTick255
45#define Tick1000 Game.iTick1000
46
47// Players
48
49int32_t ValidPlr(int32_t plr);
50int32_t Hostile(int32_t plr1, int32_t plr2);
51
52// IFT
53
54inline uint8_t PixColIFT(uint8_t pixc)
55{
56 return pixc & IFT;
57}
58
59// always use OldGfx-version (used for convert)
60inline uint8_t PixColIFTOld(uint8_t pixc)
61{
62 if (pixc >= GBM + IFTOld) return IFTOld;
63 return 0;
64}
65
66// Density
67
68inline bool DensitySolid(int32_t dens)
69{
70 return (dens >= C4M_Solid);
71}
72
73inline bool DensitySemiSolid(int32_t dens)
74{
75 return (dens >= C4M_SemiSolid);
76}
77
78inline bool DensityLiquid(int32_t dens)
79{
80 return ((dens >= C4M_Liquid) && (dens < C4M_Solid));
81}
82
83// Materials
84
85extern int32_t MVehic, MTunnel, MWater, MSnow, MEarth, MGranite; // presearched materials
86extern uint8_t MCVehic; // precalculated material color
87
88#define GBackWdt Game.Landscape.Width
89#define GBackHgt Game.Landscape.Height
90#define GBackPix Game.Landscape.GetPix
91#define SBackPix Game.Landscape.SetPix
92#define ClearBackPix Game.Landscape.ClearPix
93#define _GBackPix Game.Landscape._GetPix
94#define _SBackPix Game.Landscape._SetPix
95#define _SBackPixIfMask Game.Landscape._SetPixIfMask
96
97int32_t PixCol2MatOld(uint8_t pixc);
98int32_t PixCol2MatOld2(uint8_t pixc);
99
100inline bool MatValid(int32_t mat)
101{
102 return Inside<int32_t>(ival: mat, lbound: 0, rbound: Game.Material.Num - 1);
103}
104
105inline bool MatVehicle(int32_t iMat)
106{
107 return iMat == MVehic;
108}
109
110inline int32_t PixCol2Tex(uint8_t pixc)
111{
112 // Remove IFT
113 int32_t iTex = pixc & (IFT - 1);
114 // Validate
115 if (iTex >= C4M_MaxTexIndex) return 0;
116 // Done
117 return iTex;
118}
119
120inline int32_t PixCol2Mat(uint8_t pixc)
121{
122 // Get texture
123 int32_t iTex = PixCol2Tex(pixc);
124 if (!iTex) return MNone;
125 // Get material-texture mapping
126 const C4TexMapEntry *pTex = Game.TextureMap.GetEntry(iIndex: iTex);
127 // Return material
128 return pTex ? pTex->GetMaterialIndex() : MNone;
129}
130
131inline uint8_t MatTex2PixCol(int32_t tex)
132{
133 return uint8_t(tex);
134}
135
136inline uint8_t Mat2PixColDefault(int32_t mat)
137{
138 return Game.Material.Map[mat].DefaultMatTex;
139}
140
141inline int32_t MatDensity(int32_t mat)
142{
143 if (!MatValid(mat)) return 0;
144 return Game.Material.Map[mat].Density;
145}
146
147inline int32_t MatPlacement(int32_t mat)
148{
149 if (!MatValid(mat)) return 0;
150 return Game.Material.Map[mat].Placement;
151}
152
153inline int32_t MatDigFree(int32_t mat)
154{
155 if (!MatValid(mat)) return 1;
156 return Game.Material.Map[mat].DigFree;
157}
158
159inline uint8_t GBackIFT(int32_t x, int32_t y)
160{
161 return PixColIFT(GBackPix(x, y));
162}
163
164inline int32_t GBackMat(int32_t x, int32_t y)
165{
166 return Game.Landscape.GetMat(x, y);
167}
168
169inline int32_t GBackDensity(int32_t x, int32_t y)
170{
171 return Game.Landscape.GetDensity(x, y);
172}
173
174inline bool GBackSolid(int32_t x, int32_t y)
175{
176 return DensitySolid(dens: GBackDensity(x, y));
177}
178
179inline bool GBackSemiSolid(int32_t x, int32_t y)
180{
181 return DensitySemiSolid(dens: GBackDensity(x, y));
182}
183
184inline bool GBackLiquid(int32_t x, int32_t y)
185{
186 return DensityLiquid(dens: GBackDensity(x, y));
187}
188
189inline int32_t GBackWind(int32_t x, int32_t y)
190{
191 return GBackIFT(x, y) ? 0 : Game.Weather.Wind;
192}
193
194// StdCompiler
195
196void StdCompilerWarnCallback(void *pData, const char *szPosition, const char *szError);
197
198template <class CompT, class StructT>
199bool CompileFromBuf_LogWarn(StructT &&TargetStruct, const typename CompT::InT &SrcBuf, const char *szName)
200{
201 try
202 {
203 CompT Compiler;
204 Compiler.setInput(SrcBuf);
205 Compiler.setWarnCallback(StdCompilerWarnCallback, reinterpret_cast<void *>(const_cast<char *>(szName)));
206 Compiler.Compile(TargetStruct);
207 return true;
208 }
209 catch (const StdCompiler::Exception &e)
210 {
211 if (e.Pos.empty())
212 spdlog::error(fmt: "{} (in {})", args: e.what(), args&: szName);
213 else
214 spdlog::error(fmt: "{} (in {}, {})", args: e.what(), args: e.Pos, args&: szName);
215 return false;
216 }
217}
218
219template <class CompT, class StructT>
220bool DecompileToBuf_Log(StructT &&TargetStruct, typename CompT::OutT *pOut, const char *szName)
221{
222 if (!pOut) return false;
223 try
224 {
225 if constexpr (requires { pOut->Take(DecompileToBuf<CompT>(TargetStruct)); })
226 {
227 pOut->Take(DecompileToBuf<CompT>(TargetStruct));
228 }
229 else
230 {
231 *pOut = DecompileToBuf<CompT>(TargetStruct);
232 }
233
234 return true;
235 }
236 catch (const StdCompiler::Exception &e)
237 {
238 spdlog::error(fmt: "{} (in {})", args: e.what(), args&: szName);
239 return false;
240 }
241}
242