/* * 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 #include #include #include #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 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 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 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 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(iPXSMat,-1,Num-1)); assert(Inside(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(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