1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Material definitions used by the landscape */
19 
20 #ifndef INC_C4Material
21 #define INC_C4Material
22 
23 #include "config/C4Constants.h"
24 #include "graphics/C4Facet.h"
25 #include "graphics/CSurface8.h"
26 #include "object/C4Id.h"
27 #include "object/C4Shape.h"
28 
29 #define C4MatOv_Default     0
30 #define C4MatOv_Exact       1
31 #define C4MatOv_None        2
32 #define C4MatOv_HugeZoom    4
33 
34 enum MaterialInteractionEvent
35 {
36 	meePXSPos=0,  // PXS check before movement
37 	meePXSMove=1, // PXS movement
38 	meeMassMove=2 // MassMover-movement
39 };
40 
41 typedef bool (*C4MaterialReactionFunc)(struct C4MaterialReaction *pReaction, int32_t &iX, int32_t &iY, int32_t iLSPosX, int32_t iLSPosY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, MaterialInteractionEvent evEvent, bool *pfPosChanged);
42 
43 struct C4MaterialReaction
44 {
NoReactionC4MaterialReaction45 	static inline bool NoReaction(struct C4MaterialReaction *pReaction, int32_t &iX, int32_t &iY, int32_t iLSPosX, int32_t iLSPosY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, MaterialInteractionEvent evEvent, bool *pfPosChanged) { return false; }
46 
47 	C4MaterialReactionFunc pFunc; // Guarantueed to be non-nullptr
48 	bool fUserDefined{true};        // false for internal reactions generated by material parameters
49 	StdCopyStrBuf TargetSpec; // target material specification
50 	StdCopyStrBuf ScriptFunc; // for reaction func 'script': Script func to be called for reaction evaluation
51 	C4AulFunc *pScriptFunc{nullptr};   // resolved script function
52 	uint32_t iExecMask;       // execution mask: Bit mask with indices into MaterialInteractionEvent
53 	bool fReverse{false};            // if set, spec will be handled as if specified in target mat def
54 	bool fInverseSpec{false};        // if set, all mats except the given are used
55 	bool fInsertionCheck{true};     // if set, splash/slide checks are done prior to reaction execution
56 	int32_t iDepth{0};           // in mat conversion depth
57 	StdCopyStrBuf sConvertMat;// in mat conversion material (string)
58 	int32_t iConvertMat{-1};      // in mat conversion material; evaluated in CrossMapMaterials
59 	int32_t iCorrosionRate{100};   // chance of doing a corrosion
60 
C4MaterialReactionC4MaterialReaction61 	C4MaterialReaction(C4MaterialReactionFunc pFunc) : pFunc(pFunc), fUserDefined(false), pScriptFunc(nullptr), iExecMask(~0u) {}
C4MaterialReactionC4MaterialReaction62 	C4MaterialReaction() : pFunc(&NoReaction),  iExecMask(~0u) { }
63 
64 	void CompileFunc(StdCompiler *pComp);
65 
66 	void ResolveScriptFuncs(const char *szMatName);
67 
68 	bool operator ==(const C4MaterialReaction &rCmp) const { return false; } // never actually called; only comparing with empty vector of C4MaterialReactions
69 };
70 
71 enum C4MaterialCoreShape
72 {
73 	C4M_Flat    = 0,
74 	C4M_TopFlat = 1,
75 	C4M_Smooth  = 2,
76 	C4M_Rough   = 3,
77 	C4M_Octagon = 4,
78 	C4M_Smoother= 5,
79 };
80 
81 class C4MaterialCore
82 {
83 public:
84 	C4MaterialCore();
~C4MaterialCore()85 	~C4MaterialCore() { Clear(); }
86 
87 	std::vector<C4MaterialReaction> CustomReactionList;
88 
89 	char Name[C4M_MaxName+1];
90 
91 	C4MaterialCoreShape MapChunkType;
92 	int32_t  Density;
93 	int32_t  Friction;
94 	int32_t  DigFree;
95 	int32_t  BlastFree;
96 	C4ID Dig2Object;
97 	int32_t  Dig2ObjectRatio;
98 	int32_t  Dig2ObjectCollect;
99 	C4ID Blast2Object;
100 	int32_t  Blast2ObjectRatio;
101 	int32_t  Blast2PXSRatio;
102 	int32_t  Instable;
103 	int32_t  MaxAirSpeed;
104 	int32_t  MaxSlide;
105 	int32_t  WindDrift;
106 	int32_t  Inflammable;
107 	int32_t  Incendiary;
108 	int32_t  Extinguisher;
109 	int32_t  Corrosive;
110 	int32_t  Corrode;
111 	int32_t  Soil;
112 	int32_t  Placement; // placement order for landscape shading
113 	int32_t  Light; // ambient light range for underground materials. currently only 1/0 for ambient light on/off
114 	StdCopyStrBuf sTextureOverlay; // overlayed texture for this material
115 	int32_t  OverlayType; // defines the way in which the overlay texture is applied
116 	StdCopyStrBuf sPXSGfx;      // newgfx: picture used for loose pxs
117 	C4TargetRect PXSGfxRt;          // newgfx: facet rect of pixture used for loose pixels
118 	int32_t  PXSGfxSize;
119 	StdCopyStrBuf sBlastShiftTo;
120 	StdCopyStrBuf sInMatConvert;
121 	StdCopyStrBuf sInMatConvertTo;
122 	int32_t  InMatConvertDepth;         // material converts only if it finds the same material above
123 	int32_t  BelowTempConvert;
124 	int32_t  BelowTempConvertDir;
125 	StdCopyStrBuf sBelowTempConvertTo;
126 	int32_t  AboveTempConvert;
127 	int32_t  AboveTempConvertDir;
128 	StdCopyStrBuf sAboveTempConvertTo;
129 	int32_t  TempConvStrength;
130 	int32_t  MinHeightCount; // minimum material thickness in order for it to be counted
131 	int32_t  SplashRate;
132 	bool KeepSinglePixels; // if true, single pixels are not destroyed (for vehicle)
133 	int32_t  AnimationSpeed; // frames per animation phase
134 	int32_t  LightAngle; // light angle at which we have maximum reflection
135 	int32_t  LightEmit[3]; // amount the material lights up itself
136 	int32_t  LightSpot[3]; // spot strength
137 	int32_t MinShapeOverlap; // if drawn with a texture with custom shapes, minimum overlap of map pixels over shape blocks in percent to force them being drawn
138 
139 	void Clear();
140 	void Default();
141 	bool Load(C4Group &hGroup, const char *szEntryName);
142 	void CompileFunc(StdCompiler *pComp);
143 };
144 
145 class C4Material: public C4MaterialCore
146 {
147 public:
148 	C4Material();
149 public:
150 	// Cross-mapped material values
151 	int32_t BlastShiftTo; // MatTex
152 	int32_t InMatConvertTo; // Mat
153 	int32_t BelowTempConvertTo; // MatTex
154 	int32_t AboveTempConvertTo; // MatTex
155 	int32_t DefaultMatTex;      // texture used for single pixel values
156 
157 	C4Facet PXSFace;        // loose pixel facet
158 
159 	void UpdateScriptPointers(); // set all material script pointers
160 };
161 
162 class C4MaterialMap
163 {
164 public:
165 	C4MaterialMap();
166 	~C4MaterialMap();
167 public:
168 	int32_t Num;
169 	C4Material *Map;
170 	C4MaterialReaction **ppReactionMap;
171 	int32_t max_shape_width,max_shape_height; // maximum size of the largest polygon in any of the used shapes
172 
173 	C4MaterialReaction DefReactConvert, DefReactPoof, DefReactCorrode, DefReactIncinerate, DefReactInsert;
174 public:
175 	// default reactions
176 	static bool mrfConvert(C4MaterialReaction *pReaction, int32_t &iX, int32_t &iY, int32_t iLSPosX, int32_t iLSPosY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, MaterialInteractionEvent evEvent, bool *pfPosChanged);
177 	static bool mrfPoof   (C4MaterialReaction *pReaction, int32_t &iX, int32_t &iY, int32_t iLSPosX, int32_t iLSPosY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, MaterialInteractionEvent evEvent, bool *pfPosChanged);
178 	static bool mrfCorrode(C4MaterialReaction *pReaction, int32_t &iX, int32_t &iY, int32_t iLSPosX, int32_t iLSPosY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, MaterialInteractionEvent evEvent, bool *pfPosChanged);
179 	static bool mrfIncinerate(C4MaterialReaction *pReaction, int32_t &iX, int32_t &iY, int32_t iLSPosX, int32_t iLSPosY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, MaterialInteractionEvent evEvent, bool *pfPosChanged);
180 	static bool mrfInsert (C4MaterialReaction *pReaction, int32_t &iX, int32_t &iY, int32_t iLSPosX, int32_t iLSPosY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, MaterialInteractionEvent evEvent, bool *pfPosChanged);
181 	// user-defined actions
182 	static bool mrfScript(C4MaterialReaction *pReaction, int32_t &iX, int32_t &iY, int32_t iLSPosX, int32_t iLSPosY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, MaterialInteractionEvent evEvent, bool *pfPosChanged);
183 public:
184 	void Default();
185 	void Clear();
186 	int32_t Load(C4Group &hGroup);
187 	bool HasMaterials(C4Group &hGroup) const;
188 	int32_t Get(const char *szMaterial);
189 	bool SaveEnumeration(C4Group &hGroup);
190 	bool LoadEnumeration(C4Group &hGroup);
GetReactionUnsafe(int32_t iPXSMat,int32_t iLandscapeMat)191 	C4MaterialReaction *GetReactionUnsafe(int32_t iPXSMat, int32_t iLandscapeMat)
192 	{
193 		assert(ppReactionMap); assert(Inside<int32_t>(iPXSMat,-1,Num-1)); assert(Inside<int32_t>(iLandscapeMat,-1,Num-1));
194 		return ppReactionMap[(iLandscapeMat+1)*(Num+1) + iPXSMat+1];
195 	}
196 	C4MaterialReaction *GetReaction(int32_t iPXSMat, int32_t iLandscapeMat);
197 	void UpdateScriptPointers(); // set all material script pointers
198 	bool CrossMapMaterials(const char* szEarthMaterial);
199 protected:
200 	void SetMatReaction(int32_t iPXSMat, int32_t iLSMat, C4MaterialReaction *pReact);
201 	bool SortEnumeration(int32_t iMat, const char *szMatName);
202 };
203 
204 extern C4MaterialMap MaterialMap;
205 
206 extern int32_t MVehic,MTunnel,MWater,MEarth; // presearched materials
207 extern BYTE MCVehic; // precalculated material color
208 extern BYTE MCHalfVehic; // precalculated material color
209 
MatValid(int32_t mat)210 inline bool MatValid(int32_t mat)
211 {
212 	return Inside<int32_t>(mat,0,::MaterialMap.Num-1);
213 }
214 
MatVehicle(int32_t iMat)215 inline bool MatVehicle(int32_t iMat)
216 {
217 	return iMat == MVehic;
218 }
219 
IsMCVehicle(BYTE mat)220 inline bool IsMCVehicle(BYTE mat) {
221 	return mat == MCVehic;
222 }
IsMCHalfVehicle(BYTE mat)223 inline bool IsMCHalfVehicle(BYTE mat) {
224 	return mat == MCHalfVehic;
225 }
IsSomeVehicle(BYTE mat)226 inline bool IsSomeVehicle(BYTE mat) {
227 	return IsMCVehicle(mat) || IsMCHalfVehicle(mat);
228 }
229 
MatTex2PixCol(int32_t tex)230 inline BYTE MatTex2PixCol(int32_t tex)
231 {
232 	return BYTE(tex);
233 }
234 
Mat2PixColDefault(int32_t mat)235 inline BYTE Mat2PixColDefault(int32_t mat)
236 {
237 	return ::MaterialMap.Map[mat].DefaultMatTex;
238 }
239 
MatDensity(int32_t mat)240 inline int32_t MatDensity(int32_t mat)
241 {
242 	if (!MatValid(mat)) return 0;
243 	return ::MaterialMap.Map[mat].Density;
244 }
245 
MatPlacement(int32_t mat)246 inline int32_t MatPlacement(int32_t mat)
247 {
248 	if (!MatValid(mat)) return 0;
249 	return ::MaterialMap.Map[mat].Placement;
250 }
251 
MatDigFree(int32_t mat)252 inline int32_t MatDigFree(int32_t mat)
253 {
254 	if (!MatValid(mat)) return 1;
255 	return ::MaterialMap.Map[mat].DigFree;
256 }
257 
258 #endif
259