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