forked from Mirrors/openclonk
320 lines
11 KiB
C++
320 lines
11 KiB
C++
/*
|
|
* OpenClonk, http://www.openclonk.org
|
|
*
|
|
* Copyright (c) 1998-2000, Matthes Bender
|
|
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
|
|
* Copyright (c) 2009-2013, The OpenClonk Team and contributors
|
|
*
|
|
* Distributed under the terms of the ISC license; see accompanying file
|
|
* "COPYING" for details.
|
|
*
|
|
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
|
* See accompanying file "TRADEMARK" for details.
|
|
*
|
|
* To redistribute this file separately, substitute the full license texts
|
|
* for the above references.
|
|
*/
|
|
|
|
/* Material definitions used by the landscape */
|
|
|
|
#ifndef INC_C4Material
|
|
#define INC_C4Material
|
|
|
|
#include "C4Real.h"
|
|
#include <C4Id.h>
|
|
#include <C4Shape.h>
|
|
#include <C4Facet.h>
|
|
#include <vector>
|
|
|
|
#define C4MatOv_Default 0
|
|
#define C4MatOv_Exact 1
|
|
#define C4MatOv_None 2
|
|
#define C4MatOv_HugeZoom 4
|
|
|
|
enum MaterialInteractionEvent
|
|
{
|
|
meePXSPos=0, // PXS check before movement
|
|
meePXSMove=1, // PXS movement
|
|
meeMassMove=2 // MassMover-movement
|
|
};
|
|
|
|
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);
|
|
|
|
struct C4MaterialReaction
|
|
{
|
|
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; }
|
|
|
|
C4MaterialReactionFunc pFunc; // Guarantueed to be non-NULL
|
|
bool fUserDefined; // false for internal reactions generated by material parameters
|
|
StdCopyStrBuf TargetSpec; // target material specification
|
|
StdCopyStrBuf ScriptFunc; // for reaction func 'script': Script func to be called for reaction evaluation
|
|
C4AulFunc *pScriptFunc; // resolved script function
|
|
uint32_t iExecMask; // execution mask: Bit mask with indices into MaterialInteractionEvent
|
|
bool fReverse; // if set, spec will be handled as if specified in target mat def
|
|
bool fInverseSpec; // if set, all mats except the given are used
|
|
bool fInsertionCheck; // if set, splash/slide checks are done prior to reaction execution
|
|
int32_t iDepth; // in mat conversion depth
|
|
StdCopyStrBuf sConvertMat;// in mat conversion material (string)
|
|
int32_t iConvertMat; // in mat conversion material; evaluated in CrossMapMaterials
|
|
int32_t iCorrosionRate; // chance of doing a corrosion
|
|
|
|
C4MaterialReaction(C4MaterialReactionFunc pFunc) : pFunc(pFunc), fUserDefined(false), pScriptFunc(NULL), iExecMask(~0u), fReverse(false), fInverseSpec(false), fInsertionCheck(true), iDepth(0), iConvertMat(-1), iCorrosionRate(100) {}
|
|
C4MaterialReaction() : pFunc(&NoReaction), fUserDefined(true), pScriptFunc(NULL), iExecMask(~0u), fReverse(false), fInverseSpec(false), fInsertionCheck(true), iDepth(0), iConvertMat(-1), iCorrosionRate(100) { }
|
|
|
|
void CompileFunc(StdCompiler *pComp);
|
|
|
|
void ResolveScriptFuncs(const char *szMatName);
|
|
|
|
bool operator ==(const C4MaterialReaction &rCmp) const { return false; } // never actually called; only comparing with empty vector of C4MaterialReactions
|
|
};
|
|
|
|
// Custom material shape: Vectorized texture
|
|
class C4MaterialShape
|
|
{
|
|
private:
|
|
int32_t prepared_for_zoom; // zoom for which internal overlap data has been calculated
|
|
|
|
bool DoPrepareForZoom(int32_t zoom);
|
|
public:
|
|
struct Pt
|
|
{
|
|
int32_t x,y;
|
|
|
|
Pt(int32_t x, int32_t y) : x(x), y(y) {}
|
|
Pt() {}
|
|
void CompileFunc(StdCompiler *comp);
|
|
};
|
|
|
|
typedef std::vector<Pt> PtVec;
|
|
|
|
struct Poly : PtVec
|
|
{
|
|
Pt center,min,max; // arithmetic middle, minimum and maximum of all border points
|
|
PtVec overlaps; // map pixels that are overlapped by this shape for current zoom
|
|
|
|
void CompileFunc(StdCompiler *comp);
|
|
void PrepareForZoom(int32_t zoom);
|
|
bool IsPtContained(int32_t x, int32_t y) const;
|
|
};
|
|
typedef std::vector<Poly> PolyVec;
|
|
|
|
PolyVec polys;
|
|
int32_t wdt,hgt;
|
|
int32_t overlap_left,overlap_top,overlap_right,overlap_bottom; // amount by which the polygons extend past the rectangle (0,0)-(wdt,hgt)
|
|
int32_t max_poly_width, max_poly_height; // maximum size of any polygon in the list
|
|
public:
|
|
C4MaterialShape();
|
|
|
|
void Clear();
|
|
bool Load(C4Group &group, const char *filename);
|
|
|
|
void CompileFunc(StdCompiler *comp);
|
|
bool operator ==(const C4MaterialShape &cmp) const;
|
|
|
|
bool PrepareForZoom(int32_t zoom) { if (zoom != prepared_for_zoom) return DoPrepareForZoom(zoom); else return true; }
|
|
};
|
|
|
|
typedef std::map<StdCopyStrBuf, C4MaterialShape> C4MaterialShapeMap;
|
|
|
|
enum C4MaterialCoreShape
|
|
{
|
|
C4M_Flat = 0,
|
|
C4M_TopFlat = 1,
|
|
C4M_Smooth = 2,
|
|
C4M_Rough = 3,
|
|
C4M_Octagon = 4,
|
|
C4M_Smoother= 5,
|
|
};
|
|
|
|
class C4MaterialCore
|
|
{
|
|
public:
|
|
C4MaterialCore();
|
|
~C4MaterialCore() { Clear(); }
|
|
|
|
std::vector<C4MaterialReaction> CustomReactionList;
|
|
|
|
char Name[C4M_MaxName+1];
|
|
|
|
C4MaterialCoreShape MapChunkType;
|
|
StdCopyStrBuf ShapeTexture;
|
|
int32_t Density;
|
|
int32_t Friction;
|
|
int32_t DigFree;
|
|
int32_t BlastFree;
|
|
C4ID Dig2Object;
|
|
int32_t Dig2ObjectRatio;
|
|
int32_t Dig2ObjectCollect;
|
|
C4ID Blast2Object;
|
|
int32_t Blast2ObjectRatio;
|
|
int32_t Blast2PXSRatio;
|
|
int32_t Instable;
|
|
int32_t MaxAirSpeed;
|
|
int32_t MaxSlide;
|
|
int32_t WindDrift;
|
|
int32_t Inflammable;
|
|
int32_t Incindiary;
|
|
int32_t Extinguisher;
|
|
int32_t Corrosive;
|
|
int32_t Corrode;
|
|
int32_t Soil;
|
|
int32_t Placement; // placement order for landscape shading
|
|
int32_t Light; // ambient light range for underground materials. currently only 1/0 for ambient light on/off
|
|
StdCopyStrBuf sTextureOverlay; // overlayed texture for this material
|
|
int32_t OverlayType; // defines the way in which the overlay texture is applied
|
|
StdCopyStrBuf sPXSGfx; // newgfx: picture used for loose pxs
|
|
C4TargetRect PXSGfxRt; // newgfx: facet rect of pixture used for loose pixels
|
|
int32_t PXSGfxSize;
|
|
StdCopyStrBuf sBlastShiftTo;
|
|
StdCopyStrBuf sInMatConvert;
|
|
StdCopyStrBuf sInMatConvertTo;
|
|
int32_t InMatConvertDepth; // material converts only if it finds the same material above
|
|
int32_t BelowTempConvert;
|
|
int32_t BelowTempConvertDir;
|
|
StdCopyStrBuf sBelowTempConvertTo;
|
|
int32_t AboveTempConvert;
|
|
int32_t AboveTempConvertDir;
|
|
StdCopyStrBuf sAboveTempConvertTo;
|
|
int32_t TempConvStrength;
|
|
int32_t MinHeightCount; // minimum material thickness in order for it to be counted
|
|
int32_t SplashRate;
|
|
bool KeepSinglePixels; // if true, single pixels are not destroyed (for vehicle)
|
|
int32_t AnimationSpeed; // frames per animation phase
|
|
int32_t LightAngle; // light angle at which we have maximum reflection
|
|
int32_t LightEmit[3]; // amount the material lights up itself
|
|
int32_t LightSpot[3]; // spot strength
|
|
|
|
void Clear();
|
|
void Default();
|
|
bool Load(C4Group &hGroup, const char *szEntryName);
|
|
void CompileFunc(StdCompiler *pComp);
|
|
};
|
|
|
|
class C4Material: public C4MaterialCore
|
|
{
|
|
public:
|
|
C4Material();
|
|
public:
|
|
// Cross-mapped material values
|
|
int32_t BlastShiftTo; // MatTex
|
|
int32_t InMatConvertTo; // Mat
|
|
int32_t BelowTempConvertTo; // MatTex
|
|
int32_t AboveTempConvertTo; // MatTex
|
|
int32_t DefaultMatTex; // texture used for single pixel values
|
|
|
|
C4Facet PXSFace; // loose pixel facet
|
|
|
|
C4MaterialShape *CustomShape;
|
|
|
|
void UpdateScriptPointers(); // set all material script pointers
|
|
};
|
|
|
|
class C4MaterialMap
|
|
{
|
|
public:
|
|
C4MaterialMap();
|
|
~C4MaterialMap();
|
|
public:
|
|
int32_t Num;
|
|
C4Material *Map;
|
|
C4MaterialReaction **ppReactionMap;
|
|
C4MaterialShapeMap Shapes;
|
|
int32_t max_shape_width,max_shape_height; // maximum size of the largest polygon in any of the used shapes
|
|
|
|
C4MaterialReaction DefReactConvert, DefReactPoof, DefReactCorrode, DefReactIncinerate, DefReactInsert;
|
|
public:
|
|
// default reactions
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
// user-defined actions
|
|
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);
|
|
public:
|
|
void Default();
|
|
void Clear();
|
|
int32_t Load(C4Group &hGroup);
|
|
bool HasMaterials(C4Group &hGroup) const;
|
|
int32_t Get(const char *szMaterial);
|
|
bool SaveEnumeration(C4Group &hGroup);
|
|
bool LoadEnumeration(C4Group &hGroup);
|
|
C4MaterialReaction *GetReactionUnsafe(int32_t iPXSMat, int32_t iLandscapeMat)
|
|
{
|
|
assert(ppReactionMap); assert(Inside<int32_t>(iPXSMat,-1,Num-1)); assert(Inside<int32_t>(iLandscapeMat,-1,Num-1));
|
|
return ppReactionMap[(iLandscapeMat+1)*(Num+1) + iPXSMat+1];
|
|
}
|
|
C4MaterialReaction *GetReaction(int32_t iPXSMat, int32_t iLandscapeMat);
|
|
void UpdateScriptPointers(); // set all material script pointers
|
|
bool CrossMapMaterials(const char* szEarthMaterial);
|
|
C4MaterialShape *GetShapeByName(const char *name);
|
|
protected:
|
|
void SetMatReaction(int32_t iPXSMat, int32_t iLSMat, C4MaterialReaction *pReact);
|
|
bool SortEnumeration(int32_t iMat, const char *szMatName);
|
|
};
|
|
|
|
extern C4MaterialMap MaterialMap;
|
|
|
|
// Material Density Levels
|
|
const int32_t C4M_Vehicle = 100,
|
|
C4M_Solid = 50,
|
|
C4M_SemiSolid = 25,
|
|
C4M_Liquid = 25,
|
|
C4M_Background= 0;
|
|
|
|
const int32_t MNone = -1;
|
|
|
|
extern int32_t MVehic,MTunnel,MWater,MEarth; // presearched materials
|
|
extern BYTE MCVehic; // precalculated material color
|
|
extern BYTE MCHalfVehic; // precalculated material color
|
|
|
|
inline bool MatValid(int32_t mat)
|
|
{
|
|
return Inside<int32_t>(mat,0,::MaterialMap.Num-1);
|
|
}
|
|
|
|
inline bool MatVehicle(int32_t iMat)
|
|
{
|
|
return iMat == MVehic;
|
|
}
|
|
|
|
inline bool IsMCVehicle(BYTE mat) {
|
|
return mat == MCVehic;
|
|
}
|
|
inline bool IsMCHalfVehicle(BYTE mat) {
|
|
return mat == MCHalfVehic;
|
|
}
|
|
inline bool IsSomeVehicle(BYTE mat) {
|
|
return IsMCVehicle(mat) || IsMCHalfVehicle(mat);
|
|
}
|
|
|
|
inline BYTE MatTex2PixCol(int32_t tex)
|
|
{
|
|
return BYTE(tex);
|
|
}
|
|
|
|
inline BYTE Mat2PixColDefault(int32_t mat)
|
|
{
|
|
return ::MaterialMap.Map[mat].DefaultMatTex;
|
|
}
|
|
|
|
inline int32_t MatDensity(int32_t mat)
|
|
{
|
|
if (!MatValid(mat)) return 0;
|
|
return ::MaterialMap.Map[mat].Density;
|
|
}
|
|
|
|
inline int32_t MatPlacement(int32_t mat)
|
|
{
|
|
if (!MatValid(mat)) return 0;
|
|
return ::MaterialMap.Map[mat].Placement;
|
|
}
|
|
|
|
inline int32_t MatDigFree(int32_t mat)
|
|
{
|
|
if (!MatValid(mat)) return 1;
|
|
return ::MaterialMap.Map[mat].DigFree;
|
|
}
|
|
|
|
#endif
|