Пример #1
0
void Splash(int32_t tx, int32_t ty, int32_t amt, C4Object *pByObj) {
  // Splash only if there is free space above
  if (GBackSemiSolid(tx, ty - 15))
    return;
  // get back mat
  int32_t iMat = GBackMat(tx, ty);
  // check liquid
  if (MatValid(iMat))
    if (DensityLiquid(Game.Material.Map[iMat].Density) &&
        Game.Material.Map[iMat].Instable) {
      int32_t sy = ty;
      while (GBackLiquid(tx, sy) && sy > ty - 20 && sy >= 0)
        sy--;
      // Splash bubbles and liquid
      for (int32_t cnt = 0; cnt < amt; cnt++) {
        BubbleOut(tx + Random(16) - 8, ty + Random(16) - 6);
        if (GBackLiquid(tx, ty) && !GBackSemiSolid(tx, sy))
          Game.PXS.Create(Game.Landscape.ExtractMaterial(tx, ty), itofix(tx),
                          itofix(sy), FIXED100(Random(151) - 75),
                          FIXED100(-Random(200)));
      }
    }
  // Splash sound
  if (amt >= 20)
    StartSoundEffect("Splash2", false, 100, pByObj);
  else if (amt > 1)
    StartSoundEffect("Splash1", false, 100, pByObj);
}
Пример #2
0
void Splash(int32_t tx, int32_t ty, int32_t amt, C4Object *pByObj)
{
	// Splash only if there is free space above
	if (GBackSemiSolid(tx, ty - 15)) return;
	// get back mat
	int32_t iMat = GBackMat(tx, ty);
	// check liquid
	if (MatValid(iMat))
		if (DensityLiquid(::MaterialMap.Map[iMat].Density) && ::MaterialMap.Map[iMat].Instable)
		{
			int32_t sy = ty;
			while (GBackLiquid(tx, sy) && sy > ty - 20 && sy >= 0) sy--;
			// Splash bubbles and liquid
			for (int32_t cnt=0; cnt<amt; cnt++)
			{
				int32_t bubble_x = tx+Random(16)-8;
				int32_t bubble_y = ty+Random(16)-6;
				BubbleOut(bubble_x,bubble_y);
				if (GBackLiquid(tx,ty) && !GBackSemiSolid(tx, sy))
				{
					C4Real xdir = C4REAL100(Random(151)-75);
					C4Real ydir = C4REAL100(-Random(200));
					::PXS.Create(::Landscape.ExtractMaterial(tx,ty,false),
					             itofix(tx),itofix(sy),
					             xdir,
					             ydir);
				}
			}
		}
	// Splash sound
	if (amt>=20)
		StartSoundEffect("Splash2",false,100,pByObj);
	else if (amt>1) StartSoundEffect("Splash1",false,100,pByObj);
}
Пример #3
0
bool SimFlightHitsLiquid(C4Real fcx, C4Real fcy, C4Real xdir, C4Real ydir)
{
	// Start in water?
	int temp;
	if (DensityLiquid(GBackDensity(fixtoi(fcx), fixtoi(fcy))))
		if (!SimFlight(fcx, fcy, xdir, ydir, 0, C4M_Liquid - 1, temp=10))
			return false;
	// Hits liquid?
	if (!SimFlight(fcx, fcy, xdir, ydir, C4M_Liquid, 100, temp=-1))
		return false;
	// liquid & deep enough?
	return GBackLiquid(fixtoi(fcx), fixtoi(fcy)) && GBackLiquid(fixtoi(fcx), fixtoi(fcy) + 9);
}
Пример #4
0
bool C4TexMapEntry::Init()
	{
#ifdef C4ENGINE
	// Find material
	iMaterialIndex = Game.Material.Get(Material.getData());
	if(!MatValid(iMaterialIndex))
		{
		DebugLogF("Error initializing material %s-%s: Invalid material!", Material.getData(), Texture.getData());
		return false;
		}
	pMaterial = &Game.Material.Map[iMaterialIndex];
	// Special, hardcoded crap: change <liquid>-Smooth to <liquid>-Liquid
	const char *szTexture = Texture.getData();
	if (DensityLiquid(pMaterial->Density))
		if (SEqualNoCase(szTexture, "Smooth"))
			szTexture = "Liquid";
	// Find texture
	C4Texture * sfcTexture = Game.TextureMap.GetTexture(szTexture);
	if(!sfcTexture)
		{
		DebugLogF("Error initializing material %s-%s: Invalid texture!", Material.getData(), Texture.getData());
		Clear();
		return false;
		}
	// Get overlay properties
	int32_t iOverlayType=pMaterial->OverlayType;
	bool fMono = !!(iOverlayType & C4MatOv_Monochrome);
	int32_t iZoom=0;
	if (iOverlayType & C4MatOv_Exact) iZoom=1;
	if (iOverlayType & C4MatOv_HugeZoom) iZoom=4;
	// Create pattern
	if (sfcTexture->Surface32)
		MatPattern.Set(sfcTexture->Surface32, iZoom, fMono);
	else
		MatPattern.Set(sfcTexture->Surface8, iZoom, fMono);
	MatPattern.SetColors(pMaterial->Color, pMaterial->Alpha);
#endif
	return true;
	}
Пример #5
0
bool C4MaterialCore::Load(C4Group &hGroup,
                          const char *szEntryName)
{
	StdStrBuf Source;
	if (!hGroup.LoadEntryString(szEntryName,&Source))
		return false;
	StdStrBuf Name = hGroup.GetFullName() + DirSep + szEntryName;
	if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(*this, Source, Name.getData()))
		return false;
	// adjust placement, if not specified
	if (!Placement)
	{
		if (DensitySolid(Density))
		{
			Placement=30;
			if (!DigFree) Placement+=20;
			if (!BlastFree) Placement+=10;
		}
		else if (DensityLiquid(Density))
			Placement=10;
		else Placement=5;
	}
	return true;
}
Пример #6
0
bool C4MaterialMap::CrossMapMaterials(const char* szEarthMaterial) // Called after load
{
	// Check material number
	if (::MaterialMap.Num>C4MaxMaterial)
		{ LogFatal(LoadResStr("IDS_PRC_TOOMANYMATS")); return false; }
	// build reaction function map
	delete [] ppReactionMap;
	typedef C4MaterialReaction * C4MaterialReactionPtr;
	ppReactionMap = new C4MaterialReactionPtr[(Num+1)*(Num+1)];
	for (int32_t iMatPXS=-1; iMatPXS<Num; iMatPXS++)
	{
		C4Material *pMatPXS = (iMatPXS+1) ? Map+iMatPXS : NULL;
		for (int32_t iMatLS=-1; iMatLS<Num; iMatLS++)
		{
			C4MaterialReaction *pReaction = NULL;
			C4Material *pMatLS  = ( iMatLS+1) ? Map+ iMatLS : NULL;
			// natural stuff: material conversion here?
			if (pMatPXS && pMatPXS->sInMatConvert.getLength() && SEqualNoCase(pMatPXS->sInMatConvert.getData(), pMatLS ? pMatLS->Name : C4TLS_MatSky))
				pReaction = &DefReactConvert;
			// non-sky reactions
			else if (pMatPXS && pMatLS)
			{
				// incindiary vs extinguisher
				if ((pMatPXS->Incendiary && pMatLS->Extinguisher) || (pMatPXS->Extinguisher && pMatLS->Incendiary))
					pReaction = &DefReactPoof;
				// incindiary vs inflammable
				else if ((pMatPXS->Incendiary && pMatLS->Inflammable) || (pMatPXS->Inflammable && pMatLS->Incendiary))
					pReaction = &DefReactIncinerate;
				// corrosive vs corrode
				else if (pMatPXS->Corrosive && pMatLS->Corrode)
					pReaction = &DefReactCorrode;
				// liquid hitting liquid or solid: Material insertion
				else if (DensityLiquid(MatDensity(iMatPXS)) && DensitySemiSolid(MatDensity(iMatLS)))
					pReaction = &DefReactInsert;
				// solid hitting solid: Material insertion
				else if (DensitySolid(MatDensity(iMatPXS)) && DensitySolid(MatDensity(iMatLS)))
					pReaction = &DefReactInsert;
			}
			// assign the function; or NULL for no reaction
			SetMatReaction(iMatPXS, iMatLS, pReaction);
		}
	}
	// reset max shape size
	max_shape_width=max_shape_height=0;
	// material-specific initialization
	int32_t cnt;
	for (cnt=0; cnt<Num; cnt++)
	{
		C4Material *pMat = Map+cnt;
		const char *szTextureOverlay = NULL;
		// newgfx: init pattern
		if (Map[cnt].sTextureOverlay.getLength())
			if (::TextureMap.GetTexture(Map[cnt].sTextureOverlay.getLength()))
			{
				szTextureOverlay = Map[cnt].sTextureOverlay.getData();
				// backwards compatibility: if a pattern was specified although the no-pattern flag was set, overwrite that flag
				if (Map[cnt].OverlayType & C4MatOv_None)
				{
					DebugLogF("Error in overlay of material %s: Flag C4MatOv_None ignored because a custom overlay (%s) was specified!", Map[cnt].Name, szTextureOverlay);
					Map[cnt].OverlayType &= ~C4MatOv_None;
				}
			}
		// default to first texture in texture map
		int iTexMapIx;
		if (!szTextureOverlay && (iTexMapIx = ::TextureMap.GetIndex(Map[cnt].Name, NULL, false)))
			szTextureOverlay = TextureMap.GetEntry(iTexMapIx)->GetTextureName();
		// default to smooth
		if (!szTextureOverlay)
			szTextureOverlay = "none";
		// search/create entry in texmap
		Map[cnt].DefaultMatTex = ::TextureMap.GetIndex(Map[cnt].Name, szTextureOverlay, true,
		                         FormatString("DefaultMatTex of mat %s", Map[cnt].Name).getData());
		// init PXS facet
		C4Surface * sfcTexture;
		C4Texture * Texture;
		if (Map[cnt].sPXSGfx.getLength())
			if ((Texture=::TextureMap.GetTexture(Map[cnt].sPXSGfx.getData())))
				if ((sfcTexture=Texture->Surface32))
					Map[cnt].PXSFace.Set(sfcTexture, Map[cnt].PXSGfxRt.x, Map[cnt].PXSGfxRt.y, Map[cnt].PXSGfxRt.Wdt, Map[cnt].PXSGfxRt.Hgt);
		// evaluate reactions for that material
		for (unsigned int iRCnt = 0; iRCnt < pMat->CustomReactionList.size(); ++iRCnt)
		{
			C4MaterialReaction *pReact = &(pMat->CustomReactionList[iRCnt]);
			if (pReact->sConvertMat.getLength()) pReact->iConvertMat = Get(pReact->sConvertMat.getData()); else pReact->iConvertMat = -1;
			// evaluate target spec
			int32_t tmat;
			if (MatValid(tmat=Get(pReact->TargetSpec.getData())))
			{
				// single material target
				if (pReact->fInverseSpec)
					for (int32_t cnt2=-1; cnt2<Num; cnt2++) {
						if (cnt2!=tmat)
							SetMatReaction(cnt, cnt2, pReact);
						else
							SetMatReaction(cnt, tmat, pReact);
					}
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "All"))
			{
				// add to all materials, including sky
				if (!pReact->fInverseSpec) for (int32_t cnt2=-1; cnt2<Num; cnt2++) SetMatReaction(cnt, cnt2, pReact);
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "Solid"))
			{
				// add to all solid materials
				if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
				for (int32_t cnt2=0; cnt2<Num; cnt2++) if (DensitySolid(Map[cnt2].Density) != pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "SemiSolid"))
			{
				// add to all semisolid materials
				if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
				for (int32_t cnt2=0; cnt2<Num; cnt2++) if (DensitySemiSolid(Map[cnt2].Density) != pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "Background"))
			{
				// add to all BG materials, including sky
				if (!pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
				for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Density != pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "Sky"))
			{
				// add to sky
				if (!pReact->fInverseSpec)
					SetMatReaction(cnt, -1, pReact);
				else
					for (int32_t cnt2=0; cnt2<Num; cnt2++) SetMatReaction(cnt, cnt2, pReact);
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "Incendiary") || SEqualNoCase(pReact->TargetSpec.getData(), "Incindiary"))
			{
				// add to all incendiary materials
				if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
				for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Incendiary == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "Extinguisher"))
			{
				// add to all incendiary materials
				if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
				for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Extinguisher == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "Inflammable"))
			{
				// add to all incendiary materials
				if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
				for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Inflammable == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "Corrosive"))
			{
				// add to all incendiary materials
				if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
				for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Corrosive == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
			}
			else if (SEqualNoCase(pReact->TargetSpec.getData(), "Corrode"))
			{
				// add to all incendiary materials
				if (pReact->fInverseSpec) SetMatReaction(cnt, -1, pReact);
				for (int32_t cnt2=0; cnt2<Num; cnt2++) if (!Map[cnt2].Corrode == pReact->fInverseSpec) SetMatReaction(cnt, cnt2, pReact);
			}
		}
	}
	// second loop (DefaultMatTex is needed by GetIndexMatTex)
	for (cnt=0; cnt<Num; cnt++)
	{
		if (Map[cnt].sBlastShiftTo.getLength())
			Map[cnt].BlastShiftTo=::TextureMap.GetIndexMatTex(Map[cnt].sBlastShiftTo.getData(), NULL, true, FormatString("BlastShiftTo of mat %s", Map[cnt].Name).getData());
		if (Map[cnt].sInMatConvertTo.getLength())
			Map[cnt].InMatConvertTo=Get(Map[cnt].sInMatConvertTo.getData());
		if (Map[cnt].sBelowTempConvertTo.getLength())
			Map[cnt].BelowTempConvertTo=::TextureMap.GetIndexMatTex(Map[cnt].sBelowTempConvertTo.getData(), NULL, true, FormatString("BelowTempConvertTo of mat %s", Map[cnt].Name).getData());
		if (Map[cnt].sAboveTempConvertTo.getLength())
			Map[cnt].AboveTempConvertTo=::TextureMap.GetIndexMatTex(Map[cnt].sAboveTempConvertTo.getData(), NULL, true, FormatString("AboveTempConvertTo of mat %s", Map[cnt].Name).getData());
	}

	// Get hardcoded system material indices
	const C4TexMapEntry* earth_entry = ::TextureMap.GetEntry(::TextureMap.GetIndexMatTex(szEarthMaterial));
	if(!earth_entry)
		{ LogFatal(FormatString("Earth material \"%s\" not found!", szEarthMaterial).getData()); return false; }

	MVehic     = Get("Vehicle");     MCVehic     = Mat2PixColDefault(MVehic);
	MHalfVehic = Get("HalfVehicle"); MCHalfVehic = Mat2PixColDefault(MHalfVehic);
	MTunnel    = Get("Tunnel");
	MWater     = Get("Water");
	MEarth     = Get(earth_entry->GetMaterialName());

	if ((MVehic==MNone) || (MTunnel==MNone))
		{ LogFatal(LoadResStr("IDS_PRC_NOSYSMATS")); return false; }

	return true;
}
Пример #7
0
void C4MapScriptMatTexMask::UnmaskSpec(C4String *spec)
{
	// Mask all indices of material-texture definitions
	// Possible definitions:
	// Material-Texture - Given material-texture combination (both sky and tunnel background)
	// Material         - All defined default textures of given material
	// *                - All materials including sky
	// Sky              - Index C4M_MaxTexIndex
	// Transparent      - Index 0
	// Background       - All tunnel materials plus sky
	// Liquid           - All liquid materials
	// Solid            - All solid materials
	// Possible modifiers:
	// ^Material        - Given material only with sky background
	// &Material        - Given material only with tunnel background
	// ~Material        - Inverse of given definition; i.e. everything except Material
	if (!spec || !spec->GetCStr()) return;
	const char *cspec = spec->GetCStr();
	bool invert=false, bgsky=false, bgtunnel=false, prefix_done=false;
	while (*cspec)
	{
		switch (*cspec)
		{
		case '~': invert=!invert; break;
		case '^': bgsky=true; break;
		case '&': bgtunnel=true; break;
		default: prefix_done=true; break;
		}
		if (prefix_done) break;
		++cspec;
	}
	std::vector<bool> mat_mask(C4M_MaxTexIndex+1, false);
	if (SEqual(cspec, DrawFn_Transparent_Name))
	{
		// "Transparent" is zero index. Force to non-IFT
		mat_mask[0] = true;
	}
	else if (SEqual(cspec, DrawFn_Sky_Name))
	{
		// Sky material
		mat_mask[C4M_MaxTexIndex] = true;
	}
	else if (SEqual(cspec, DrawFn_Background_Name))
	{
		// All background materials
		for (int32_t i=1; i<C4M_MaxTexIndex; ++i) if (!DensitySemiSolid(Landscape.GetPixDensity(i))) mat_mask[i] = true;
		// Background includes sky
		mat_mask[C4M_MaxTexIndex] = true;
	}
	else if (SEqual(cspec, DrawFn_Liquid_Name))
	{
		// All liquid materials
		for (int32_t i=1; i<C4M_MaxTexIndex; ++i) if (DensityLiquid(Landscape.GetPixDensity(i))) mat_mask[i] = true;
	}
	else if (SEqual(cspec, DrawFn_Solid_Name))
	{
		// All solid materials
		for (int32_t i=1; i<C4M_MaxTexIndex; ++i) if (DensitySolid(Landscape.GetPixDensity(i))) mat_mask[i] = true;
	}
	else if (SEqual(cspec, "*"))
	{
		// All materials
		for (int32_t i=1; i<C4M_MaxTexIndex; ++i) mat_mask[i] = true;
		// Including sky
		mat_mask[C4M_MaxTexIndex] = true;
	}
	else
	{
		// Specified material
		if (SCharCount('-', cspec))
		{
			// Material+Texture
			int32_t col = ::MapScript.pTexMap->GetIndexMatTex(cspec, NULL, false);
			if (col) mat_mask[col] = true;
		}
		else
		{
			// Only material: Mask all textures of this material
			int32_t mat = ::MapScript.pMatMap->Get(cspec);
			if (mat!=MNone)
			{
				const char *tex_name;
				int32_t col;
				for (int32_t itex=0; (tex_name=::MapScript.pTexMap->GetTexture(itex)); itex++)
					if ((col = ::MapScript.pTexMap->GetIndex(cspec,tex_name,false)))
						mat_mask[col] = true;
			}
		}
	}

	// 'OR' spec onto this->sky_mask and this->tunnel_mask. Apply bgsky, bgtunnel and invert.
	for (int32_t i=0; i<C4M_MaxTexIndex + 1; ++i)
	{
		if ((mat_mask[i] && (bgsky || !bgtunnel)) != invert)
			sky_mask[i] = true;
		if ((mat_mask[i] && (!bgsky || bgtunnel)) != invert)
			tunnel_mask[i] = true;
	}
}