OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4Material.cpp
Go to the documentation of this file.
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 #include "C4Include.h"
21 #include "landscape/C4Material.h"
22 #include "c4group/C4Components.h"
23 
24 #include "c4group/C4Group.h"
25 #include "landscape/C4PXS.h"
26 #include "lib/C4Random.h"
27 #include "editor/C4ToolsDlg.h" // For C4TLS_MatSky...
28 #include "landscape/C4Texture.h"
29 #include "script/C4Aul.h"
30 #include "landscape/C4Landscape.h"
31 #include "platform/C4SoundSystem.h"
32 #include "script/C4Effect.h"
33 #include "lib/C4Log.h"
34 #include "game/C4Physics.h" // For GravAccel
35 
36 
40 // -------------------------------------- C4MaterialReaction
41 
42 
44 
46 {
47  { "Script", &C4MaterialMap::mrfScript },
48  { "Convert", &C4MaterialMap::mrfConvert},
49  { "Poof", &C4MaterialMap::mrfPoof },
50  { "Corrode", &C4MaterialMap::mrfCorrode },
51  { "Insert", &C4MaterialMap::mrfInsert },
52  { nullptr, &C4MaterialReaction::NoReaction }
53 };
54 
55 
57 {
58  if (pComp->isDeserializer()) pScriptFunc = nullptr;
59  // compile reaction func ptr
60  StdStrBuf sReactionFuncName;
61  int32_t i=0; while (ReactionFuncMap[i].szRFName && (ReactionFuncMap[i].pFunc != pFunc)) ++i;
62  sReactionFuncName = ReactionFuncMap[i].szRFName;
63  pComp->Value(mkNamingAdapt(mkParAdapt(sReactionFuncName, StdCompiler::RCT_IdtfAllowEmpty), "Type", StdCopyStrBuf() ));
64  i=0; while (ReactionFuncMap[i].szRFName && !SEqual(ReactionFuncMap[i].szRFName, sReactionFuncName.getData())) ++i;
65  pFunc = ReactionFuncMap[i].pFunc;
66  // compile the rest
69  pComp->Value(mkNamingAdapt(iExecMask, "ExecMask", ~0u ));
70  pComp->Value(mkNamingAdapt(fReverse, "Reverse", false ));
71  pComp->Value(mkNamingAdapt(fInverseSpec, "InverseSpec", false ));
72  pComp->Value(mkNamingAdapt(fInsertionCheck, "CheckSlide", true ));
73  pComp->Value(mkNamingAdapt(iDepth, "Depth", 0 ));
75  pComp->Value(mkNamingAdapt(iCorrosionRate, "CorrosionRate", 100 ));
76 }
77 
78 
79 void C4MaterialReaction::ResolveScriptFuncs(const char *szMatName)
80 {
81  // get script func for script-defined behaviour
83  {
85  if (!pScriptFunc)
86  DebugLogF("Error getting function \"%s\" for Material reaction of \"%s\"", this->ScriptFunc.getData(), szMatName);
87  }
88  else
89  pScriptFunc = nullptr;
90 }
91 
92 // -------------------------------------- C4MaterialCore
93 
95 {
96  Clear();
97 }
98 
100 {
101  CustomReactionList.clear();
103  sPXSGfx.Clear();
109  *Name='\0';
111  Density = 0;
112  Friction = 0;
113  DigFree = 0;
114  BlastFree = 0;
116  Dig2ObjectRatio = 0;
117  Dig2ObjectCollect = 0;
119  Blast2ObjectRatio = 0;
120  Blast2PXSRatio = 0;
121  Instable = 0;
122  MaxAirSpeed = 0;
123  MaxSlide = 0;
124  WindDrift = 0;
125  Inflammable = 0;
126  Incendiary = 0;
127  Extinguisher = 0;
128  Corrosive = 0;
129  Corrode = 0;
130  Soil = 0;
131  Placement = 0;
132  Light = 0;
133  OverlayType = 0;
134  PXSGfxRt.Default();
135  PXSGfxSize = 0;
136  InMatConvertDepth = 0;
137  BelowTempConvert = 0;
139  AboveTempConvert = 0;
141  TempConvStrength = 0;
142  MinHeightCount = 0;
143  SplashRate=10;
144  KeepSinglePixels=false;
145  AnimationSpeed = 20;
146  LightAngle = 255;
147  for (int i = 0; i < 3; i++) {
148  LightEmit[i] = 0;
149  LightSpot[i] = 16;
150  }
151  MinShapeOverlap = 25;
152 }
153 
155 {
156  Clear();
157 }
158 
160  const char *szEntryName)
161 {
162  StdStrBuf Source;
163  if (!hGroup.LoadEntryString(szEntryName,&Source))
164  return false;
165  StdStrBuf Name = hGroup.GetFullName() + DirSep + szEntryName;
166  if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(*this, Source, Name.getData()))
167  return false;
168  // adjust placement, if not specified
169  if (!Placement)
170  {
171  if (DensitySolid(Density))
172  {
173  Placement=30;
174  if (!DigFree) Placement+=20;
175  if (!BlastFree) Placement+=10;
176  }
177  else if (DensityLiquid(Density))
178  Placement=10;
179  else Placement=5;
180  }
181  return true;
182 }
183 
185 {
186  assert(pComp->hasNaming());
187  if (pComp->isDeserializer()) Clear();
188  pComp->Name("Material");
189  pComp->Value(mkNamingAdapt(toC4CStr(Name), "Name", ""));
190 
191  const StdEnumEntry<C4MaterialCoreShape> Shapes[] =
192  {
193  { "Flat", C4M_Flat },
194  { "TopFlat", C4M_TopFlat },
195  { "Smooth", C4M_Smooth },
196  { "Rough", C4M_Rough },
197  { "Octagon", C4M_Octagon },
198  { "Smoother", C4M_Smoother },
199  { nullptr, C4M_Flat }
200  };
201  pComp->Value(mkNamingAdapt(mkEnumAdaptT<uint8_t>(MapChunkType, Shapes),
202  "Shape", C4M_Flat));
203  pComp->Value(mkNamingAdapt(Density, "Density", 0));
204  pComp->Value(mkNamingAdapt(Friction, "Friction", 0));
205  pComp->Value(mkNamingAdapt(DigFree, "DigFree", 0));
206  pComp->Value(mkNamingAdapt(BlastFree, "BlastFree", 0));
207  pComp->Value(mkNamingAdapt(Blast2Object, "Blast2Object", C4ID::None));
208  pComp->Value(mkNamingAdapt(Dig2Object, "Dig2Object", C4ID::None));
209  pComp->Value(mkNamingAdapt(Dig2ObjectRatio, "Dig2ObjectRatio", 0));
210  pComp->Value(mkNamingAdapt(Dig2ObjectCollect, "Dig2ObjectCollect", 0));
211  pComp->Value(mkNamingAdapt(Blast2ObjectRatio, "Blast2ObjectRatio", 0));
212  pComp->Value(mkNamingAdapt(Blast2PXSRatio, "Blast2PXSRatio", 0));
213  pComp->Value(mkNamingAdapt(Instable, "Instable", 0));
214  pComp->Value(mkNamingAdapt(MaxAirSpeed, "MaxAirSpeed", 0));
215  pComp->Value(mkNamingAdapt(MaxSlide, "MaxSlide", 0));
216  pComp->Value(mkNamingAdapt(WindDrift, "WindDrift", 0));
217  pComp->Value(mkNamingAdapt(Inflammable, "Inflammable", 0));
218  if (pComp->isDeserializer())
219  {
220  // The value used to have a wrong spelling ("Incindiary"). If there's
221  // no "Incendiary" value, use the wrong spelling instead
222  try
223  {
224  pComp->Value(mkNamingAdapt(Incendiary, "Incendiary"));
225  }
227  {
228  delete ex;
229  pComp->Value(mkNamingAdapt(Incendiary, "Incindiary", 0));
230  }
231  }
232  else
233  {
234  // When serializing, write both spellings because some script might be
235  // calling GetMaterialVal with the wrong one
236  pComp->Value(mkNamingAdapt(Incendiary, "Incendiary"));
237  pComp->Value(mkNamingAdapt(Incendiary, "Incindiary"));
238  }
239  pComp->Value(mkNamingAdapt(Corrode, "Corrode", 0));
240  pComp->Value(mkNamingAdapt(Corrosive, "Corrosive", 0));
241  pComp->Value(mkNamingAdapt(Extinguisher, "Extinguisher", 0));
242  pComp->Value(mkNamingAdapt(Soil, "Soil", 0));
243  pComp->Value(mkNamingAdapt(Placement, "Placement", 0));
244  pComp->Value(mkNamingAdapt(Light, "Light", 0));
246  "TextureOverlay", ""));
247  pComp->Value(mkNamingAdapt(OverlayType, "OverlayType", 0));
249  "PXSGfx", ""));
250  pComp->Value(mkNamingAdapt(PXSGfxRt, "PXSGfxRt", TargetRect0));
251  pComp->Value(mkNamingAdapt(PXSGfxSize, "PXSGfxSize", PXSGfxRt.Wdt));
252  pComp->Value(mkNamingAdapt(TempConvStrength, "TempConvStrength", 0));
254  "BlastShiftTo", ""));
256  "InMatConvert", ""));
258  "InMatConvertTo", ""));
259  pComp->Value(mkNamingAdapt(InMatConvertDepth, "InMatConvertDepth", 0));
260  pComp->Value(mkNamingAdapt(AboveTempConvert, "AboveTempConvert", 0));
261  pComp->Value(mkNamingAdapt(AboveTempConvertDir, "AboveTempConvertDir", 0));
263  "AboveTempConvertTo", ""));
264  pComp->Value(mkNamingAdapt(BelowTempConvert, "BelowTempConvert", 0));
265  pComp->Value(mkNamingAdapt(BelowTempConvertDir, "BelowTempConvertDir", 0));
267  "BelowTempConvertTo", ""));
268  pComp->Value(mkNamingAdapt(MinHeightCount, "MinHeightCount", 0));
269  pComp->Value(mkNamingAdapt(SplashRate, "SplashRate", 10));
270  pComp->Value(mkNamingAdapt(KeepSinglePixels, "KeepSinglePixels", false));
271  pComp->Value(mkNamingAdapt(AnimationSpeed, "AnimationSpeed", 100));
272  pComp->Value(mkNamingAdapt(LightAngle, "LightAngle", 255));
273  pComp->Value(mkNamingAdapt(mkArrayAdaptDM(LightEmit, 0), "LightEmit"));
274  pComp->Value(mkNamingAdapt(mkArrayAdaptDM(LightSpot, 16),"LightSpot"));
275  pComp->Value(mkNamingAdapt(MinShapeOverlap, "MinShapeOverlap", 25));
276  pComp->NameEnd();
277  // material reactions
279  "Reaction", std::vector<C4MaterialReaction>()));
280 }
281 
282 
283 // -------------------------------------- C4Material
284 
286 {
287  BlastShiftTo=0;
291 }
292 
294 {
295  for (uint32_t i = 0; i < CustomReactionList.size(); ++i)
296  CustomReactionList[i].ResolveScriptFuncs(Name);
297 }
298 
299 
300 // -------------------------------------- C4MaterialMap
301 
302 
303 C4MaterialMap::C4MaterialMap() : DefReactConvert(&mrfConvert), DefReactPoof(&mrfPoof), DefReactCorrode(&mrfCorrode), DefReactIncinerate(&mrfIncinerate), DefReactInsert(&mrfInsert)
304 {
305  Default();
306 }
307 
308 
310 {
311  Clear();
312 }
313 
315 {
316  if (Map) delete [] Map; Map=nullptr; Num=0;
317  delete [] ppReactionMap; ppReactionMap = nullptr;
318 }
319 
320 int32_t C4MaterialMap::Load(C4Group &hGroup)
321 {
322  char entryname[256+1];
323 
324  // Determine number of materials in files
325  int32_t mat_num=hGroup.EntryCount(C4CFN_MaterialFiles);
326 
327  // Allocate new map
328  C4Material *pNewMap = new C4Material [mat_num + Num];
329  if (!pNewMap) return 0;
330 
331  // Load material cores to map
332  hGroup.ResetSearch(); int32_t cnt=0;
333  while (hGroup.FindNextEntry(C4CFN_MaterialFiles,entryname))
334  {
335  // Load mat
336  if (!pNewMap[cnt].Load(hGroup,entryname))
337  { delete [] pNewMap; return 0; }
338  // A new material?
339  if (Get(pNewMap[cnt].Name) == MNone)
340  cnt++;
341  }
342 
343  // Take over old materials.
344  for (int32_t i = 0; i < Num; i++)
345  {
346  pNewMap[cnt+i] = Map[i];
347  }
348  delete [] Map;
349  Map = pNewMap;
350 
351  // set material number
352  Num+=cnt;
353 
354  return cnt;
355 }
356 
358 {
359  return !!hGroup.EntryCount(C4CFN_MaterialFiles);
360 }
361 
362 int32_t C4MaterialMap::Get(const char *szMaterial)
363 {
364  int32_t cnt;
365  for (cnt=0; cnt<Num; cnt++)
366  if (SEqualNoCase(szMaterial,Map[cnt].Name))
367  return cnt;
368  return MNone;
369 }
370 
371 
372 bool C4MaterialMap::CrossMapMaterials(const char* szEarthMaterial) // Called after load
373 {
374  // Check material number
376  { LogFatal(LoadResStr("IDS_PRC_TOOMANYMATS")); return false; }
377  // build reaction function map
378  delete [] ppReactionMap;
379  typedef C4MaterialReaction * C4MaterialReactionPtr;
380  ppReactionMap = new C4MaterialReactionPtr[(Num+1)*(Num+1)];
381  for (int32_t iMatPXS=-1; iMatPXS<Num; iMatPXS++)
382  {
383  C4Material *pMatPXS = (iMatPXS+1) ? Map+iMatPXS : nullptr;
384  for (int32_t iMatLS=-1; iMatLS<Num; iMatLS++)
385  {
386  C4MaterialReaction *pReaction = nullptr;
387  C4Material *pMatLS = ( iMatLS+1) ? Map+ iMatLS : nullptr;
388  // natural stuff: material conversion here?
389  if (pMatPXS && pMatPXS->sInMatConvert.getLength() && SEqualNoCase(pMatPXS->sInMatConvert.getData(), pMatLS ? pMatLS->Name : C4TLS_MatSky))
390  pReaction = &DefReactConvert;
391  // non-sky reactions
392  else if (pMatPXS && pMatLS)
393  {
394  // incindiary vs extinguisher
395  if ((pMatPXS->Incendiary && pMatLS->Extinguisher) || (pMatPXS->Extinguisher && pMatLS->Incendiary))
396  pReaction = &DefReactPoof;
397  // incindiary vs inflammable
398  else if ((pMatPXS->Incendiary && pMatLS->Inflammable) || (pMatPXS->Inflammable && pMatLS->Incendiary))
399  pReaction = &DefReactIncinerate;
400  // corrosive vs corrode
401  else if (pMatPXS->Corrosive && pMatLS->Corrode)
402  pReaction = &DefReactCorrode;
403  // liquid hitting liquid or solid: Material insertion
404  else if (DensityLiquid(MatDensity(iMatPXS)) && DensitySemiSolid(MatDensity(iMatLS)))
405  pReaction = &DefReactInsert;
406  // solid hitting solid: Material insertion
407  else if (DensitySolid(MatDensity(iMatPXS)) && DensitySolid(MatDensity(iMatLS)))
408  pReaction = &DefReactInsert;
409  }
410  // assign the function; or nullptr for no reaction
411  SetMatReaction(iMatPXS, iMatLS, pReaction);
412  }
413  }
414  // reset max shape size
416  // material-specific initialization
417  int32_t cnt;
418  for (cnt=0; cnt<Num; cnt++)
419  {
420  C4Material *pMat = Map+cnt;
421  const char *szTextureOverlay = nullptr;
422  // newgfx: init pattern
423  if (Map[cnt].sTextureOverlay.getLength())
425  {
426  szTextureOverlay = Map[cnt].sTextureOverlay.getData();
427  // backwards compatibility: if a pattern was specified although the no-pattern flag was set, overwrite that flag
428  if (Map[cnt].OverlayType & C4MatOv_None)
429  {
430  DebugLogF("Error in overlay of material %s: Flag C4MatOv_None ignored because a custom overlay (%s) was specified!", Map[cnt].Name, szTextureOverlay);
431  Map[cnt].OverlayType &= ~C4MatOv_None;
432  }
433  }
434  // default to first texture in texture map
435  int iTexMapIx;
436  if (!szTextureOverlay && (iTexMapIx = ::TextureMap.GetIndex(Map[cnt].Name, nullptr, false)))
437  szTextureOverlay = TextureMap.GetEntry(iTexMapIx)->GetTextureName();
438  // default to smooth
439  if (!szTextureOverlay)
440  szTextureOverlay = "none";
441  // search/create entry in texmap
442  Map[cnt].DefaultMatTex = ::TextureMap.GetIndex(Map[cnt].Name, szTextureOverlay, true,
443  FormatString("DefaultMatTex of mat %s", Map[cnt].Name).getData());
444  // init PXS facet
445  C4Surface * sfcTexture;
446  C4Texture * Texture;
447  if (Map[cnt].sPXSGfx.getLength())
448  if ((Texture=::TextureMap.GetTexture(Map[cnt].sPXSGfx.getData())))
449  if ((sfcTexture=Texture->Surface32))
450  Map[cnt].PXSFace.Set(sfcTexture, Map[cnt].PXSGfxRt.x, Map[cnt].PXSGfxRt.y, Map[cnt].PXSGfxRt.Wdt, Map[cnt].PXSGfxRt.Hgt);
451  // evaluate reactions for that material
452  for (unsigned int iRCnt = 0; iRCnt < pMat->CustomReactionList.size(); ++iRCnt)
453  {
454  C4MaterialReaction *pReact = &(pMat->CustomReactionList[iRCnt]);
455  if (pReact->sConvertMat.getLength()) pReact->iConvertMat = Get(pReact->sConvertMat.getData()); else pReact->iConvertMat = -1;
456  // evaluate target spec
457  int32_t tmat;
458  if (MatValid(tmat=Get(pReact->TargetSpec.getData())))
459  {
460  // single material target
461  if (pReact->fInverseSpec)
462  for (int32_t cnt2=-1; cnt2<Num; cnt2++) {
463  if (cnt2!=tmat)
464  SetMatReaction(cnt, cnt2, pReact);
465  else
466  SetMatReaction(cnt, tmat, pReact);
467  }
468  }
469  else if (SEqualNoCase(pReact->TargetSpec.getData(), "All"))
470  {
471  // add to all materials, including sky
472  if (!pReact->fInverseSpec) for (int32_t cnt2=-1; cnt2<Num; cnt2++) SetMatReaction(cnt, cnt2, pReact);
473  }
474  else if (SEqualNoCase(pReact->TargetSpec.getData(), "Solid"))
475  {
476  // add to all solid materials
477  if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
478  for (int32_t cnt2=0; cnt2<Num; cnt2++) if (DensitySolid(Map[cnt2].Density) != pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
479  }
480  else if (SEqualNoCase(pReact->TargetSpec.getData(), "SemiSolid"))
481  {
482  // add to all semisolid materials
483  if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
484  for (int32_t cnt2=0; cnt2<Num; cnt2++) if (DensitySemiSolid(Map[cnt2].Density) != pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
485  }
486  else if (SEqualNoCase(pReact->TargetSpec.getData(), "Background"))
487  {
488  // add to all BG materials, including sky
489  if (!pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
490  for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Density != pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
491  }
492  else if (SEqualNoCase(pReact->TargetSpec.getData(), "Sky"))
493  {
494  // add to sky
495  if (!pReact->fInverseSpec)
496  SetMatReaction(cnt, -1, pReact);
497  else
498  for (int32_t cnt2=0; cnt2<Num; cnt2++) SetMatReaction(cnt, cnt2, pReact);
499  }
500  else if (SEqualNoCase(pReact->TargetSpec.getData(), "Incendiary") || SEqualNoCase(pReact->TargetSpec.getData(), "Incindiary"))
501  {
502  // add to all incendiary materials
503  if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
504  for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Incendiary == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
505  }
506  else if (SEqualNoCase(pReact->TargetSpec.getData(), "Extinguisher"))
507  {
508  // add to all incendiary materials
509  if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
510  for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Extinguisher == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
511  }
512  else if (SEqualNoCase(pReact->TargetSpec.getData(), "Inflammable"))
513  {
514  // add to all incendiary materials
515  if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
516  for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Inflammable == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
517  }
518  else if (SEqualNoCase(pReact->TargetSpec.getData(), "Corrosive"))
519  {
520  // add to all incendiary materials
521  if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
522  for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Corrosive == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
523  }
524  else if (SEqualNoCase(pReact->TargetSpec.getData(), "Corrode"))
525  {
526  // add to all incendiary materials
527  if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
528  for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Corrode == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
529  }
530  }
531  }
532  // second loop (DefaultMatTex is needed by GetIndexMatTex)
533  for (cnt=0; cnt<Num; cnt++)
534  {
535  if (Map[cnt].sBlastShiftTo.getLength())
536  Map[cnt].BlastShiftTo=::TextureMap.GetIndexMatTex(Map[cnt].sBlastShiftTo.getData(), nullptr, true, FormatString("BlastShiftTo of mat %s", Map[cnt].Name).getData());
537  if (Map[cnt].sInMatConvertTo.getLength())
538  Map[cnt].InMatConvertTo=Get(Map[cnt].sInMatConvertTo.getData());
539  if (Map[cnt].sBelowTempConvertTo.getLength())
540  Map[cnt].BelowTempConvertTo=::TextureMap.GetIndexMatTex(Map[cnt].sBelowTempConvertTo.getData(), nullptr, true, FormatString("BelowTempConvertTo of mat %s", Map[cnt].Name).getData());
541  if (Map[cnt].sAboveTempConvertTo.getLength())
542  Map[cnt].AboveTempConvertTo=::TextureMap.GetIndexMatTex(Map[cnt].sAboveTempConvertTo.getData(), nullptr, true, FormatString("AboveTempConvertTo of mat %s", Map[cnt].Name).getData());
543  }
544 
545  // Get hardcoded system material indices
546  const C4TexMapEntry* earth_entry = ::TextureMap.GetEntry(::TextureMap.GetIndexMatTex(szEarthMaterial));
547  if(!earth_entry)
548  { LogFatal(FormatString("Earth material \"%s\" not found!", szEarthMaterial).getData()); return false; }
549 
550  MVehic = Get("Vehicle"); MCVehic = Mat2PixColDefault(MVehic);
552  MTunnel = Get("Tunnel");
553  MWater = Get("Water");
554  MEarth = Get(earth_entry->GetMaterialName());
555 
556  if ((MVehic==MNone) || (MTunnel==MNone))
557  { LogFatal(LoadResStr("IDS_PRC_NOSYSMATS")); return false; }
558 
559  return true;
560 }
561 
562 
563 void C4MaterialMap::SetMatReaction(int32_t iPXSMat, int32_t iLSMat, C4MaterialReaction *pReact)
564 {
565  // evaluate reaction swap
566  if (pReact && pReact->fReverse) std::swap(iPXSMat, iLSMat);
567  // set it
568  ppReactionMap[(iLSMat+1)*(Num+1) + iPXSMat+1] = pReact;
569 }
570 
572 {
573  char *mapbuf = new char [1000];
574  mapbuf[0]=0;
575  SAppend("[Enumeration]",mapbuf); SAppend(LineFeed,mapbuf);
576  for (int32_t cnt=0; cnt<Num; cnt++)
577  {
578  SAppend(Map[cnt].Name,mapbuf);
579  SAppend(LineFeed,mapbuf);
580  }
581  return hGroup.Add(C4CFN_MatMap,mapbuf,SLen(mapbuf),false,true);
582 }
583 
585 {
586  // Load enumeration map (from savegame), succeed if not present
587  StdStrBuf mapbuf;
588  if (!hGroup.LoadEntryString(C4CFN_MatMap, &mapbuf)) return true;
589 
590  // Sort material array by enumeration map, fail if some missing
591  const char *csearch;
592  char cmatname[C4M_MaxName+1];
593  int32_t cmat=0;
594  if (!(csearch = SSearch(mapbuf.getData(),"[Enumeration]"))) { return false; }
595  csearch=SAdvanceSpace(csearch);
596  while (IsIdentifier(*csearch))
597  {
598  SCopyIdentifier(csearch,cmatname,C4M_MaxName);
599  if (!SortEnumeration(cmat,cmatname))
600  {
601  // Output error message!
602  return false;
603  }
604  cmat++;
605  csearch+=SLen(cmatname);
606  csearch=SAdvanceSpace(csearch);
607  }
608 
609  return true;
610 }
611 
612 bool C4MaterialMap::SortEnumeration(int32_t iMat, const char *szMatName)
613 {
614 
615  // Not enough materials loaded
616  if (iMat>=Num) return false;
617 
618  // Find requested mat
619  int32_t cmat;
620  for (cmat=iMat; cmat<Num; cmat++)
621  if (SEqual(szMatName,Map[cmat].Name))
622  break;
623  // Not found
624  if (cmat>=Num) return false;
625 
626  // already the same?
627  if (cmat == iMat) return true;
628 
629  // Move requested mat to indexed position
630  C4Material mswap;
631  mswap = Map[iMat];
632  Map[iMat] = Map[cmat];
633  Map[cmat] = mswap;
634 
635  return true;
636 }
637 
639 {
640  Num=0;
641  Map=nullptr;
642  ppReactionMap=nullptr;
644 }
645 
646 C4MaterialReaction *C4MaterialMap::GetReaction(int32_t iPXSMat, int32_t iLandscapeMat)
647 {
648  // safety
649  if (!ppReactionMap) return nullptr;
650  if (!Inside<int32_t>(iPXSMat, -1, Num-1)) return nullptr;
651  if (!Inside<int32_t>(iLandscapeMat, -1, Num-1)) return nullptr;
652  // values OK; get func!
653  return GetReactionUnsafe(iPXSMat, iLandscapeMat);
654 }
655 
656 static void Smoke(int32_t tx, int32_t ty, int32_t level)
657 {
658  // Use scripted function (global func Smoke) to create smoke
659  // Caution: This makes engine internal smoking a synced call.
660  C4AulParSet pars(tx, ty, level);
662 }
663 
664 bool mrfInsertCheck(int32_t &iX, int32_t &iY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, bool *pfPosChanged)
665 {
666  // always manipulating pos/speed here
667  if (pfPosChanged) *pfPosChanged = true;
668 
669  // Move up by up to 3px to account for moving SolidMasks, other material insertions, etc.
670  int32_t mdens = std::min(::MaterialMap.Map[iPxsMat].Density, C4M_Solid);
671  int32_t max_upwards = 3;
672  bool was_pushed_upwards = false;
673  while (max_upwards-- && (::Landscape.GetDensity(iX, iY) >= mdens))
674  {
675  --iY;
676  was_pushed_upwards = true;
677  }
678 
679  // Rough contact? May splash
680  if (fYDir > itofix(1))
681  if (::MaterialMap.Map[iPxsMat].SplashRate && !Random(::MaterialMap.Map[iPxsMat].SplashRate))
682  {
683  fYDir = -fYDir/8;
684  fXDir = fXDir/8 + C4REAL100(Random(200) - 100);
685  if (fYDir) return false;
686  }
687 
688  // Contact: Stop
689  fYDir = -GravAccel;
690 
691  // Incendiary mats smoke on contact even before doing their slide
692  if (::MaterialMap.Map[iPxsMat].Incendiary)
693  if (!Random(25))
694  {
695  Smoke(iX, iY, 4 + Random(3));
696  }
697 
698  // Move by mat path/slide
699  int32_t iSlideX = iX, iSlideY = iY;
700 
701  if (::Landscape.FindMatSlide(iSlideX,iSlideY,Sign(GravAccel),mdens,::MaterialMap.Map[iPxsMat].MaxSlide))
702  {
703  // Sliding on equal material: Move directly to optimize insertion of rain onto lakes
704  // Also move directly when shifted upwards to ensure movement on permamently moving SolidMask
705  if (iPxsMat == iLsMat || was_pushed_upwards)
706  {
707  iX = iSlideX;
708  iY = iSlideY;
709  fXDir = 0;
710  if (was_pushed_upwards)
711  {
712  // When pushed upwards and slide was found into a target position, insert directly to allow additional PXS at same location to solidify in next position in same frame
713  if (::Landscape.GetDensity(iX, iY + Sign(GravAccel)) >= mdens)
714  {
715  return true;
716  }
717  }
718  // Continue existing (and fall down next frame)
719  return false;
720  }
721  // Otherwise, just move using xdir/ydir for nice visuals when rain is moving over landscape
722  // Accelerate into the direction
723  fXDir = (fXDir * 10 + Sign(iSlideX - iX)) / 11 + C4REAL10(Random(5)-2);
724  // Slide target in range? Move there directly.
725  if (Abs(iX - iSlideX) <= Abs(fixtoi(fXDir)))
726  {
727  iX = iSlideX;
728  iY = iSlideY;
729  if (fYDir <= 0) fXDir = 0;
730  }
731  // Continue existance
732  return false;
733  }
734  // insertion OK
735  return true;
736 }
737 
738 bool mrfUserCheck(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)
739 {
740  // check execution mask
741  if ((1<<evEvent) & ~pReaction->iExecMask) return false;
742  // do splash/slide check, if desired
743  if (pReaction->fInsertionCheck && evEvent == meePXSMove)
744  if (!mrfInsertCheck(iX, iY, fXDir, fYDir, iPxsMat, iLsMat, pfPosChanged))
745  return false;
746  // checks OK; reaction may be applied
747  return true;
748 }
749 
750 bool C4MaterialMap::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)
751 {
752  if (pReaction->fUserDefined) if (!mrfUserCheck(pReaction, iX, iY, iLSPosX, iLSPosY, fXDir, fYDir, iPxsMat, iLsMat, evEvent, pfPosChanged)) return false;
753  switch (evEvent)
754  {
755  case meePXSMove: // PXS movement
756  // for hardcoded stuff: only InMatConvert is Snow in Water, which does not have any collision proc
757  if (!pReaction->fUserDefined) break;
758  // user-defined conversions may also convert upon hitting materials
759 
760  case meePXSPos: // PXS check before movement
761  {
762  // Check depth
763  int32_t iDepth = pReaction->fUserDefined ? pReaction->iDepth : ::MaterialMap.Map[iPxsMat].InMatConvertDepth;
764  if (!iDepth || GBackMat(iX, iY - iDepth) == iLsMat)
765  {
766  // Convert
767  iPxsMat = pReaction->fUserDefined ? pReaction->iConvertMat : ::MaterialMap.Map[iPxsMat].InMatConvertTo;
768  if (!MatValid(iPxsMat))
769  // Convert failure (target mat not be loaded, or target may be C4TLS_MatSky): Kill Pix
770  return true;
771  // stop movement after conversion
772  fXDir = fYDir = 0;
773  if (pfPosChanged) *pfPosChanged = true;
774  }
775  }
776  break;
777 
778  case meeMassMove: // MassMover-movement
779  // Conversion-transfer to PXS
780  ::PXS.Create(iPxsMat,itofix(iX),itofix(iY));
781  return true;
782  }
783  // not handled
784  return false;
785 }
786 
787 bool C4MaterialMap::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)
788 {
789  if (pReaction->fUserDefined) if (!mrfUserCheck(pReaction, iX, iY, iLSPosX, iLSPosY, fXDir, fYDir, iPxsMat, iLsMat, evEvent, pfPosChanged)) return false;
790  switch (evEvent)
791  {
792  case meeMassMove: // MassMover-movement
793  case meePXSPos: // PXS check before movement: Kill both landscape and PXS mat
794  ::Landscape.ExtractMaterial(iLSPosX,iLSPosY,false);
795  if (!Random(3)) Smoke(iX,iY,3);
796  if (!Random(3)) StartSoundEffectAt("Liquids::Pshshsh", iX, iY);
797  return true;
798 
799  case meePXSMove: // PXS movement
800  // incindiary/extinguisher/corrosives are always same density proc; so do insertion check first
801  if (!pReaction->fUserDefined)
802  if (!mrfInsertCheck(iX, iY, fXDir, fYDir, iPxsMat, iLsMat, pfPosChanged))
803  // either splash or slide prevented interaction
804  return false;
805  // Always kill both landscape and PXS mat
806  ::Landscape.ExtractMaterial(iLSPosX,iLSPosY,false);
807  if (!Random(3)) Smoke(iX,iY,3);
808  if (!Random(3)) StartSoundEffectAt("Liquids::Pshshsh", iX, iY);
809  return true;
810  }
811  // not handled
812  return false;
813 }
814 
815 bool C4MaterialMap::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)
816 {
817  if (pReaction->fUserDefined) if (!mrfUserCheck(pReaction, iX, iY, iLSPosX, iLSPosY, fXDir, fYDir, iPxsMat, iLsMat, evEvent, pfPosChanged)) return false;
818  switch (evEvent)
819  {
820  case meePXSPos: // PXS check before movement
821  // No corrosion - it would make acid incredibly effective
822  break;
823  case meeMassMove: // MassMover-movement
824  {
825  // evaluate corrosion percentage
826  bool fDoCorrode; int d100 = Random(100);
827  if (pReaction->fUserDefined)
828  fDoCorrode = (d100 < pReaction->iCorrosionRate);
829  else
830  fDoCorrode = (d100 < ::MaterialMap.Map[iPxsMat].Corrosive) && (d100 < ::MaterialMap.Map[iLsMat].Corrode);
831  if (fDoCorrode)
832  {
833  ::Landscape.ClearPix(iLSPosX,iLSPosY);
834  //::Landscape.CheckInstabilityRange(iLSPosX,iLSPosY); - more correct, but makes acid too effective as well
835  if (!Random(5))
836  {
837  Smoke(iX, iY, 3 + Random(3));
838  }
839  if (!Random(20)) StartSoundEffectAt("Liquids::Corrode", iX, iY);
840  return true;
841  }
842  }
843  break;
844 
845  case meePXSMove: // PXS movement
846  {
847  // corrodes to corrosives are always same density proc; so do insertion check first
848  if (!pReaction->fUserDefined)
849  if (!mrfInsertCheck(iX, iY, fXDir, fYDir, iPxsMat, iLsMat, pfPosChanged))
850  // either splash or slide prevented interaction
851  return false;
852  // evaluate corrosion percentage
853  bool fDoCorrode; int d100 = Random(100);
854  if (pReaction->fUserDefined)
855  fDoCorrode = (d100 < pReaction->iCorrosionRate);
856  else
857  fDoCorrode = (d100 < ::MaterialMap.Map[iPxsMat].Corrosive) && (d100 < ::MaterialMap.Map[iLsMat].Corrode);
858  if (fDoCorrode)
859  {
860  ::Landscape.ClearPix(iLSPosX,iLSPosY);
861  ::Landscape.CheckInstabilityRange(iLSPosX,iLSPosY);
862  if (!Random(5))
863  {
864  Smoke(iX,iY,3+Random(3));
865  }
866  if (!Random(20)) StartSoundEffectAt("Liquids::Corrode", iX, iY);
867  return true;
868  }
869  // Else: dead. Insert material here
870  ::Landscape.InsertMaterial(iPxsMat,&iX,&iY);
871  return true;
872  }
873  }
874  // not handled
875  return false;
876 }
877 
878 bool C4MaterialMap::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)
879 {
880  // not available as user reaction
881  assert(!pReaction->fUserDefined);
882  switch (evEvent)
883  {
884  case meeMassMove: // MassMover-movement
885  case meePXSPos: // PXS check before movement
886  if (::Landscape.Incinerate(iX, iY, NO_OWNER)) return true;
887  break;
888 
889  case meePXSMove: // PXS movement
890  // incinerate to inflammables are always same density proc; so do insertion check first
891  if (!mrfInsertCheck(iX, iY, fXDir, fYDir, iPxsMat, iLsMat, pfPosChanged))
892  // either splash or slide prevented interaction
893  return false;
894  // evaluate inflammation (should always succeed)
895  if (::Landscape.Incinerate(iX, iY, NO_OWNER)) return true;
896  // Else: dead. Insert material here
897  ::Landscape.InsertMaterial(iPxsMat,&iX,&iY);
898  return true;
899  }
900  // not handled
901  return false;
902 }
903 
904 bool C4MaterialMap::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)
905 {
906  if (pReaction->fUserDefined) if (!mrfUserCheck(pReaction, iX, iY, iLSPosX, iLSPosY, fXDir, fYDir, iPxsMat, iLsMat, evEvent, pfPosChanged)) return false;
907  switch (evEvent)
908  {
909  case meePXSPos: // PXS check before movement
910  break;
911 
912  case meePXSMove: // PXS movement
913  {
914  // check for bounce/slide
915  if (!pReaction->fUserDefined)
916  if (!mrfInsertCheck(iX, iY, fXDir, fYDir, iPxsMat, iLsMat, pfPosChanged))
917  // continue existing
918  return false;
919  // Else: dead. Insert material here
920  ::Landscape.InsertMaterial(iPxsMat,&iX,&iY);
921  return true;
922  }
923 
924  case meeMassMove: // MassMover-movement
925  break;
926  }
927  // not handled
928  return false;
929 }
930 
931 bool C4MaterialMap::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)
932 {
933  // do generic checks for user-defined reactions
934  if (!mrfUserCheck(pReaction, iX, iY, iLSPosX, iLSPosY, fXDir, fYDir, iPxsMat, iLsMat, evEvent, pfPosChanged))
935  return false;
936 
937  // check script func
938  if (!pReaction->pScriptFunc) return false;
939  // OK - let's call it!
940  // 0 1 2 3 4 5 6 7 8
941  int32_t iXDir1, iYDir1, iXDir2, iYDir2;
942  C4AulParSet pars(iX, iY, iLSPosX, iLSPosY, iXDir1 = fixtoi(fXDir, 100), iYDir1 = fixtoi(fYDir, 100), iPxsMat, iLsMat, int(evEvent));
943  if (!!pReaction->pScriptFunc->Exec(nullptr, &pars, false))
944  {
945  // PXS shall be killed!
946  return true;
947  }
948  // PXS shall exist further: write back parameters
949  iPxsMat = pars[6].getInt();
950  int32_t iX2 = pars[0].getInt(), iY2 = pars[1].getInt();
951  iXDir2 = pars[4].getInt(); iYDir2 = pars[5].getInt();
952  if (iX!=iX2 || iY!=iY2 || iXDir1!=iXDir2 || iYDir1!=iYDir2)
953  {
954  // changes to pos/speed detected
955  if (pfPosChanged) *pfPosChanged = true;
956  iX=iX2; iY=iY2;
957  fXDir = C4REAL100(iXDir2);
958  fYDir = C4REAL100(iYDir2);
959  }
960  // OK; done
961  return false;
962 }
963 
965 {
966  // update in all materials
967  for (int32_t i=0; i<Num; ++i) Map[i].UpdateScriptPointers();
968 }
969 
const char * getData() const
Definition: StdBuf.h:450
C4MaterialReaction * GetReactionUnsafe(int32_t iPXSMat, int32_t iLandscapeMat)
Definition: C4Material.h:193
int32_t BlastShiftTo
Definition: C4Material.h:153
StdCopyStrBuf TargetSpec
Definition: C4Material.h:51
int32_t MHalfVehic
Definition: C4Material.cpp:37
int32_t Extinguisher
Definition: C4Material.h:110
uint32_t iExecMask
Definition: C4Material.h:54
int32_t DefaultMatTex
Definition: C4Material.h:157
virtual bool hasNaming()
Definition: StdCompiler.h:68
int32_t InMatConvertTo
Definition: C4Material.h:154
int EntryCount(const char *szWildCard=nullptr)
Definition: C4Group.cpp:1850
uint32_t Random()
Definition: C4Random.cpp:43
C4MaterialReactionFunc pFunc
Definition: C4Material.cpp:43
Definition: StdAdaptors.h:763
C4PropListStatic * GetPropList()
Definition: C4Aul.h:153
bool Incinerate(int32_t x, int32_t y, int32_t cause_player)
void SAppend(const char *szSource, char *szTarget, int iMaxL)
Definition: Standard.cpp:234
int32_t MaxSlide
Definition: C4Material.h:106
StdCopyStrBuf sTextureOverlay
Definition: C4Material.h:116
C4TargetRect PXSGfxRt
Definition: C4Material.h:119
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
bool LoadEnumeration(C4Group &hGroup)
Definition: C4Material.cpp:584
void Clear()
Definition: StdBuf.h:474
int32_t Corrode
Definition: C4Material.h:112
int32_t Instable
Definition: C4Material.h:104
C4AulFunc * GetFunc(C4PropertyName k) const
Definition: C4PropList.h:107
BYTE MCHalfVehic
Definition: C4Material.cpp:39
#define C4CFN_MatMap
Definition: C4Components.h:81
const char * SSearch(const char *szString, const char *szIndex)
Definition: Standard.cpp:340
int32_t Friction
Definition: C4Material.h:95
C4Material * Map
Definition: C4Material.h:171
C4MaterialReaction DefReactInsert
Definition: C4Material.h:175
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:184
int32_t OverlayType
Definition: C4Material.h:117
const char * SAdvanceSpace(const char *szSPos)
Definition: Standard.cpp:391
C4Surface * Surface32
Definition: C4Texture.h:35
int32_t AnimationSpeed
Definition: C4Material.h:135
#define GravAccel
Definition: C4Physics.h:29
int32_t max_shape_height
Definition: C4Material.h:173
C4Real C4REAL100(int x)
Definition: C4Real.h:267
uint8_t BYTE
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)
Definition: C4Material.h:43
static 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)
Definition: C4Material.h:47
C4TextureMap TextureMap
Definition: C4Texture.cpp:585
virtual bool Name(const char *szName)
Definition: StdCompiler.h:87
int32_t BlastFree
Definition: C4Material.h:97
int Sign(T val)
Definition: Standard.h:47
int32_t MinShapeOverlap
Definition: C4Material.h:139
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)
Definition: C4Material.cpp:787
#define toC4CStr(szString)
Definition: StdAdaptors.h:25
bool InsertMaterial(int32_t mat, int32_t *tx, int32_t *ty, int32_t vx=0, int32_t vy=0, bool query_only=false)
bool Create(int32_t mat, C4Real ix, C4Real iy, C4Real ixdir=Fix0, C4Real iydir=Fix0)
Definition: C4PXS.cpp:206
bool DensitySemiSolid(int32_t dens)
Definition: C4Landscape.h:204
size_t SLen(const char *sptr)
Definition: Standard.h:78
Definition: C4Texture.h:48
const C4TexMapEntry * GetEntry(int32_t iIndex) const
Definition: C4Texture.h:85
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:97
StdCopyStrBuf sConvertMat
Definition: C4Material.h:59
int32_t MTunnel
Definition: C4Material.cpp:37
int32_t MaxAirSpeed
Definition: C4Material.h:105
const C4TargetRect TargetRect0(0, 0, 0, 0, 0, 0)
int32_t MEarth
Definition: C4Material.cpp:37
int32_t Dig2ObjectCollect
Definition: C4Material.h:100
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
int32_t GetIndex(const char *szMaterial, const char *szTexture, bool fAddIfNotExist=true, const char *szErrorIfFailed=nullptr)
Definition: C4Texture.cpp:423
Definition: C4Real.h:58
C4MaterialReactionFunc pFunc
Definition: C4Material.h:49
C4MaterialReaction DefReactIncinerate
Definition: C4Material.h:175
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
Definition: StdAdaptors.h:93
int32_t LightAngle
Definition: C4Material.h:136
StdCopyStrBuf sPXSGfx
Definition: C4Material.h:118
bool SaveEnumeration(C4Group &hGroup)
Definition: C4Material.cpp:571
bool SortEnumeration(int32_t iMat, const char *szMatName)
Definition: C4Material.cpp:612
const int C4M_MaxName
Definition: C4Constants.h:49
C4MaterialReaction DefReactPoof
Definition: C4Material.h:175
int32_t Wdt
Definition: C4Rect.h:32
void SetMatReaction(int32_t iPXSMat, int32_t iLSMat, C4MaterialReaction *pReact)
Definition: C4Material.cpp:563
int32_t MWater
Definition: C4Material.cpp:37
StdCopyStrBuf sBlastShiftTo
Definition: C4Material.h:121
int32_t MatDensity(int32_t mat)
Definition: C4Material.h:242
const int32_t MNone
Definition: C4Constants.h:178
bool DebugLogF(const char *strMessage...)
Definition: C4Log.cpp:281
C4Real C4REAL10(int x)
Definition: C4Real.h:269
const char * GetMaterialName() const
Definition: C4Texture.h:60
char Name[C4M_MaxName+1]
Definition: C4Material.h:91
int32_t y
Definition: C4Rect.h:32
int32_t GetDensity(int32_t x, int32_t y) const
int32_t Light
Definition: C4Material.h:115
int32_t AboveTempConvert
Definition: C4Material.h:128
StdStrBuf GetFullName() const
Definition: C4Group.cpp:2078
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)
Definition: C4Material.cpp:931
bool DensityLiquid(int32_t dens)
Definition: C4Landscape.h:209
const char * GetTextureName() const
Definition: C4Texture.h:61
void UpdateScriptPointers()
Definition: C4Material.cpp:293
C4Landscape Landscape
void CheckInstabilityRange(int32_t tx, int32_t ty)
int32_t MVehic
Definition: C4Material.cpp:37
BYTE MCVehic
Definition: C4Material.cpp:38
int32_t AboveTempConvertDir
Definition: C4Material.h:129
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)
Definition: C4Material.cpp:878
StdCopyStrBuf ScriptFunc
Definition: C4Material.h:52
static const C4ID None
Definition: C4Id.h:42
int32_t Blast2PXSRatio
Definition: C4Material.h:103
void CompileFunc(StdCompiler *pComp)
Definition: C4Material.cpp:184
C4MaterialReaction DefReactConvert
Definition: C4Material.h:175
C4MaterialReaction * GetReaction(int32_t iPXSMat, int32_t iLandscapeMat)
Definition: C4Material.cpp:646
int32_t Blast2ObjectRatio
Definition: C4Material.h:102
int32_t AboveTempConvertTo
Definition: C4Material.h:156
const int NO_OWNER
Definition: C4Constants.h:138
C4Fixed itofix(int32_t x)
Definition: C4Real.h:261
C4MaterialReaction ** ppReactionMap
Definition: C4Material.h:172
C4Value Exec(C4PropList *p=nullptr, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4AulFunc.h:73
StdCopyStrBuf sAboveTempConvertTo
Definition: C4Material.h:130
bool LogFatal(const char *szMessage)
Definition: C4Log.cpp:230
C4PXSSystem PXS
Definition: C4PXS.cpp:526
bool Load(C4Group &hGroup, const char *szEntryName)
Definition: C4Material.cpp:159
int32_t Num
Definition: C4Material.h:170
bool FindMatSlide(int32_t &fx, int32_t &fy, int32_t ydir, int32_t mdens, int32_t mslide) const
int32_t MinHeightCount
Definition: C4Material.h:132
void Value(const T &rStruct)
Definition: StdCompiler.h:171
const int32_t C4M_Solid
Definition: C4Constants.h:173
C4AulFunc * pScriptFunc
Definition: C4Material.h:53
C4MaterialReaction DefReactCorrode
Definition: C4Material.h:175
#define mkArrayAdaptDM(A, D)
Definition: StdAdaptors.h:364
#define C4MatOv_None
Definition: C4Material.h:33
StdCopyStrBuf sInMatConvertTo
Definition: C4Material.h:123
int32_t Dig2ObjectRatio
Definition: C4Material.h:99
#define LineFeed
Definition: Standard.h:151
Definition: C4Material.cpp:43
int32_t Density
Definition: C4Material.h:94
virtual bool isDeserializer()
Definition: StdCompiler.h:63
int32_t x
Definition: C4Rect.h:32
const char * szRFName
Definition: C4Material.cpp:43
int32_t Soil
Definition: C4Material.h:113
int32_t ExtractMaterial(int32_t fx, int32_t fy, bool distant_first)
int32_t PXSGfxSize
Definition: C4Material.h:120
int32_t Get(const char *szMaterial)
Definition: C4Material.cpp:362
const ReactionFuncMapEntry ReactionFuncMap[]
Definition: C4Material.cpp:45
const char * GetTexture(int32_t iIndex)
Definition: C4Texture.cpp:503
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)
Definition: C4Material.cpp:815
int32_t BelowTempConvertTo
Definition: C4Material.h:155
int32_t SplashRate
Definition: C4Material.h:133
int32_t BelowTempConvert
Definition: C4Material.h:125
int32_t WindDrift
Definition: C4Material.h:107
int32_t InMatConvertDepth
Definition: C4Material.h:124
bool LoadEntryString(const char *szEntryName, StdStrBuf *Buf)
Definition: C4Group.cpp:1932
bool FindNextEntry(const char *szWildCard, StdStrBuf *sFileName=nullptr, size_t *iSize=nullptr, bool fStartAtFilename=false)
Definition: C4Group.cpp:1780
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)
Definition: C4Material.cpp:904
StdSTLContainerAdapt< C > mkSTLContainerAdapt(C &rTarget, StdCompiler::Sep eSep=StdCompiler::SEP_SEP)
Definition: StdAdaptors.h:682
int32_t Corrosive
Definition: C4Material.h:111
C4MaterialCoreShape MapChunkType
Definition: C4Material.h:93
int32_t Placement
Definition: C4Material.h:114
bool IsIdentifier(char cChar)
Definition: Standard.cpp:67
bool KeepSinglePixels
Definition: C4Material.h:134
bool mrfInsertCheck(int32_t &iX, int32_t &iY, C4Real &fXDir, C4Real &fYDir, int32_t &iPxsMat, int32_t iLsMat, bool *pfPosChanged)
Definition: C4Material.cpp:664
C4MaterialMap MaterialMap
Definition: C4Material.cpp:970
bool HasMaterials(C4Group &hGroup) const
Definition: C4Material.cpp:357
BYTE Mat2PixColDefault(int32_t mat)
Definition: C4Material.h:237
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)
Definition: C4Material.cpp:750
int32_t Load(C4Group &hGroup)
Definition: C4Material.cpp:320
bool Add(const char *szFile, const char *szAddAs)
Definition: C4Group.cpp:1316
bool ClearPix(int32_t tx, int32_t ty)
const int32_t C4MaxMaterial
Definition: C4Landscape.h:26
int32_t max_shape_width
Definition: C4Material.h:173
void UpdateScriptPointers()
Definition: C4Material.cpp:964
StdParameterAdapt< T, P > mkParAdapt(T &&rObj, P &&rPar)
Definition: StdAdaptors.h:459
int32_t Incendiary
Definition: C4Material.h:109
size_t getLength() const
Definition: StdBuf.h:453
void ResetSearch(bool reload_contents=false)
Definition: C4Group.cpp:1013
#define C4TLS_MatSky
Definition: C4ToolsDlg.h:39
int32_t LightEmit[3]
Definition: C4Material.h:137
int32_t TempConvStrength
Definition: C4Material.h:131
int32_t LightSpot[3]
Definition: C4Material.h:138
int32_t iConvertMat
Definition: C4Material.h:60
int32_t Hgt
Definition: C4Rect.h:32
T Abs(T val)
Definition: Standard.h:44
class C4SoundInstance * StartSoundEffectAt(const char *, int32_t, int32_t, int32_t, int32_t, int32_t, class C4SoundModifier *)
Definition: stub-handle.cpp:41
#define DirSep
StdCopyStrBuf sInMatConvert
Definition: C4Material.h:122
MaterialInteractionEvent
Definition: C4Material.h:36
std::vector< C4MaterialReaction > CustomReactionList
Definition: C4Material.h:89
C4Value Call(C4PropertyName k, C4AulParSet *pPars=0, bool fPassErrors=false)
Definition: C4PropList.h:112
void Default()
Definition: C4Rect.cpp:39
int32_t GetIndexMatTex(const char *szMaterialTexture, const char *szDefaultTexture=nullptr, bool fAddIfNotExist=true, const char *szErrorIfFailed=nullptr)
Definition: C4Texture.cpp:450
void CompileFunc(StdCompiler *pComp)
Definition: C4Material.cpp:56
StdCopyStrBuf sBelowTempConvertTo
Definition: C4Material.h:127
int fixtoi(const C4Fixed &x)
Definition: C4Real.h:259
bool MatValid(int32_t mat)
Definition: C4Material.h:212
int32_t iCorrosionRate
Definition: C4Material.h:61
#define C4CFN_MaterialFiles
Definition: C4Components.h:168
int32_t DigFree
Definition: C4Material.h:96
virtual void NameEnd(bool fBreak=false)
Definition: StdCompiler.h:88
bool DensitySolid(int32_t dens)
Definition: C4Landscape.h:199
int32_t GBackMat(int32_t x, int32_t y)
Definition: C4Landscape.h:222
int32_t BelowTempConvertDir
Definition: C4Material.h:126
bool mrfUserCheck(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)
Definition: C4Material.cpp:738
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:277
int32_t Inflammable
Definition: C4Material.h:108
void SCopyIdentifier(const char *szSource, char *sTarget, int iMaxL)
Definition: Standard.cpp:420
bool CrossMapMaterials(const char *szEarthMaterial)
Definition: C4Material.cpp:372
void ResolveScriptFuncs(const char *szMatName)
Definition: C4Material.cpp:79