Example #1
0
int32_t C4TextureMap::GetIndex(const char *szMaterial, const char *szTexture, BOOL fAddIfNotExist, const char *szErrorIfFailed)
  {
  BYTE byIndex;
  // Find existing
	for (byIndex = 1; byIndex < C4M_MaxTexIndex; byIndex++)
		if (!Entry[byIndex].isNull())
			if (SEqualNoCase(Entry[byIndex].GetMaterialName(), szMaterial))
				if (!szTexture || SEqualNoCase(Entry[byIndex].GetTextureName(), szTexture))
					return byIndex;
  // Add new entry
  if (fAddIfNotExist)
    for (byIndex=1; byIndex<C4M_MaxTexIndex; byIndex++)
      if (Entry[byIndex].isNull())
        {
        if (AddEntry(byIndex, szMaterial, szTexture))
					{
					fEntriesAdded=true;
					return byIndex;
					}
#ifdef C4ENGINE
				if (szErrorIfFailed) DebugLogF("Error getting MatTex %s-%s for %s from TextureMap: Init failed.", szMaterial, szTexture, szErrorIfFailed);
#endif
        return 0;
        }
  // Else, fail
#ifdef C4ENGINE
	if (szErrorIfFailed) DebugLogF("Error getting MatTex %s-%s for %s from TextureMap: %s.", szMaterial, szTexture, szErrorIfFailed, fAddIfNotExist ? "Map is full!" : "Entry not found.");
#endif
  return 0;  
  }
Example #2
0
bool C4TexMapEntry::Init()
{
	// Find material
	iMaterialIndex = ::MaterialMap.Get(Material.getData());
	if (!MatValid(iMaterialIndex))
	{
		DebugLogF("Error initializing material %s-%s: Invalid material!", Material.getData(), Texture.getData());
		return false;
	}
	pMaterial = &::MaterialMap.Map[iMaterialIndex];
	// Find texture
	StdStrBuf FirstTexture;
	FirstTexture.CopyUntil(Texture.getData(), '-');
	C4Texture * sfcTexture = ::TextureMap.GetTexture(FirstTexture.getData());
	if (!sfcTexture)
	{
		DebugLogF("Error initializing material %s-%s: Invalid texture!", Material.getData(), FirstTexture.getData());
		Clear();
		return false;
	}
	// Get overlay properties
	int32_t iOverlayType=pMaterial->OverlayType;
	int32_t iZoom=0;
	if (iOverlayType & C4MatOv_Exact) iZoom=1;
	if (iOverlayType & C4MatOv_HugeZoom) iZoom=4;
	// Create pattern
	MatPattern.Set(sfcTexture->Surface32, iZoom);
	return true;
}
void StdCompilerWarnCallback(void *pData, const char *szPosition, const char *szError)
{
	const char *szName = reinterpret_cast<const char *>(pData);
	if (!szPosition || !*szPosition)
		DebugLogF("WARNING: %s (in %s)", szError, szName);
	else
		DebugLogF("WARNING: %s (in %s, %s)", szError, szPosition, szName);
}
Example #4
0
void C4Def::LoadMeshMaterials(C4Group &hGroup, C4DefGraphicsPtrBackup *gfx_backup)
{
	// Load all mesh materials from this folder
	C4DefAdditionalResourcesLoader loader(hGroup);
	hGroup.ResetSearch();
	char MaterialFilename[_MAX_PATH + 1]; *MaterialFilename = 0;
	
	for (const auto &mat : mesh_materials)
	{
		::MeshMaterialManager.Remove(mat, &gfx_backup->GetUpdater());
	}
	mesh_materials.clear();
	while (hGroup.FindNextEntry(C4CFN_DefMaterials, MaterialFilename, NULL, !!*MaterialFilename))
	{
		StdStrBuf material;
		if (hGroup.LoadEntryString(MaterialFilename, &material))
		{
			try
			{
				StdStrBuf buf;
				buf.Copy(hGroup.GetName());
				buf.Append("/"); buf.Append(MaterialFilename);
				auto new_materials = ::MeshMaterialManager.Parse(material.getData(), buf.getData(), loader);
				mesh_materials.insert(new_materials.begin(), new_materials.end());
			}
			catch (const StdMeshMaterialError& ex)
			{
				DebugLogF("Failed to read material script: %s", ex.what());
			}
		}
	}
}
Example #5
0
int32_t C4TextureMap::GetIndexMatTex(const char *szMaterialTexture,
                                     const char *szDefaultTexture,
                                     BOOL fAddIfNotExist,
                                     const char *szErrorIfFailed) {
  // split material/texture pair
  StdStrBuf Material, Texture;
  Material.CopyUntil(szMaterialTexture, '-');
  Texture.Copy(SSearch(szMaterialTexture, "-"));
  // texture not given or invalid?
  int32_t iMatTex = 0;
  if (Texture.getData())
    if (iMatTex =
            GetIndex(Material.getData(), Texture.getData(), fAddIfNotExist))
      return iMatTex;
  if (szDefaultTexture)
    if (iMatTex =
            GetIndex(Material.getData(), szDefaultTexture, fAddIfNotExist))
      return iMatTex;
#ifdef C4ENGINE
  // search material
  long iMaterial = Game.Material.Get(szMaterialTexture);
  if (!MatValid(iMaterial)) {
    if (szErrorIfFailed)
      DebugLogF("Error getting MatTex for %s: Invalid material",
                szErrorIfFailed);
    return 0;
  }
  // return default map entry
  return Game.Material.Map[iMaterial].DefaultMatTex;
#else
  return 0;
#endif
}
bool C4DefGraphics::LoadMesh(C4Group &hGroup, const char* szFileName, StdMeshSkeletonLoader& loader)
{
	char* buf = NULL;
	size_t size;

	try
	{
		if(!hGroup.LoadEntry(szFileName, &buf, &size, 1)) return false;

		if (SEqualNoCase(GetExtension(szFileName), "xml"))
		{
			Mesh = StdMeshLoader::LoadMeshXml(buf, size, ::MeshMaterialManager, loader, hGroup.GetName());
		}
		else
		{
			Mesh = StdMeshLoader::LoadMeshBinary(buf, size, ::MeshMaterialManager, loader, hGroup.GetName());
		}
		delete[] buf;

		Mesh->SetLabel(pDef->id.ToString());

		// order submeshes
		Mesh->PostInit();
	}
	catch (const std::runtime_error& ex)
	{
		DebugLogF("Failed to load mesh in definition %s: %s", hGroup.GetName(), ex.what());
		delete[] buf;
		return false;
	}

	Type = TYPE_Mesh;
	return true;
}
bool C4DefGraphics::LoadSkeleton(C4Group &hGroup, const char* szFileName, StdMeshSkeletonLoader& loader)
{
	char* buf = NULL;
	size_t size;

	try
	{
		if (!hGroup.LoadEntry(szFileName, &buf, &size, 1)) return false;

		// delete skeleton from the map for reloading, or else if you delete or rename
		// a skeleton file in the folder the old skeleton will still exist in the map
		loader.RemoveSkeleton(hGroup.GetName(), szFileName);

		if (SEqualNoCase(GetExtension(szFileName), "xml"))
		{
			loader.LoadSkeletonXml(hGroup.GetName(), szFileName, buf, size);
		}
		else
		{
			loader.LoadSkeletonBinary(hGroup.GetName(), szFileName, buf, size);
		}

		delete[] buf;
	}
	catch (const std::runtime_error& ex)
	{
		DebugLogF("Failed to load skeleton in definition %s: %s", hGroup.GetName(), ex.what());
		delete[] buf;
		return false;
	}

	return true;
}
Example #8
0
bool C4DefGraphics::LoadSkeleton(C4Group &hGroup, const char* szFileName, StdMeshSkeletonLoader& loader)
{
	char* buf = NULL;
	size_t size;

	try
	{
		if (!hGroup.LoadEntry(szFileName, &buf, &size, 1)) return false;

		StdCopyStrBuf filename = StdCopyStrBuf();
		StdMeshSkeletonLoader::MakeFullSkeletonPath(filename, hGroup.GetName(), szFileName);

		if (SEqualNoCase(GetExtension(szFileName), "xml"))
		{
			loader.LoadSkeletonXml(filename, buf, size);
		}
		else
		{
			loader.LoadSkeletonBinary(filename, buf, size);
		}

		delete[] buf;
	}
	catch (const std::runtime_error& ex)
	{
		DebugLogF("Failed to load skeleton in definition %s: %s", hGroup.GetName(), ex.what());
		delete[] buf;
		return false;
	}

	return true;
}
Example #9
0
bool C4Def::LoadGraphics(C4Group &hGroup, StdMeshSkeletonLoader &loader)
{
	// Try to load graphics
	// No fail on error - just have an object without graphics.
	Graphics.Load(hGroup, loader, !!ColorByOwner);

	if (Graphics.Type == C4DefGraphics::TYPE_Bitmap)
	{
		// Bitmap post-load settings
		if (Graphics.GetBitmap())
		{
			// Set MainFace (unassigned bitmap: will be set by GetMainFace())
			MainFace.Set(NULL, 0, 0, Shape.Wdt, Shape.Hgt);
		}

		// Adjust picture rect
		if ((PictureRect.Wdt == 0) || (PictureRect.Hgt == 0))
			PictureRect.Set(0, 0, Shape.Wdt*Graphics.Bmp.Bitmap->Scale, Shape.Hgt*Graphics.Bmp.Bitmap->Scale);

		// validate TopFace
		if (TopFace.x<0 || TopFace.y<0 || TopFace.x + TopFace.Wdt>Graphics.Bmp.Bitmap->Wdt || TopFace.y + TopFace.Hgt>Graphics.Bmp.Bitmap->Hgt)
		{
			TopFace.Default();
			// warn in debug mode
			DebugLogF("invalid TopFace in %s (%s)", GetName(), id.ToString());
		}
	}
	else
	{
		TopFace.Default();
	}

	return true;
}
Example #10
0
bool C4ParticleDef::Load(C4Group &group)
{
	// store file
	Filename.Copy(group.GetFullName());
	// load
	char *particle_source;
	if (group.LoadEntry(C4CFN_ParticleCore,&particle_source,NULL,1))
	{
		if (!Compile(particle_source, Filename.getData()))
		{
			DebugLogF("invalid particle def at '%s'", group.GetFullName().getData());
			delete [] particle_source; return false;
		}
		delete [] particle_source;
		// load graphics
		if (!Gfx.Load(group, C4CFN_DefGraphics, C4FCT_Full, C4FCT_Full, false, C4SF_MipMap))
		{
			DebugLogF("particle %s has no valid graphics defined", Name.getData());
			return false;
		}
		// set facet, if assigned - otherwise, assume full surface
		if (GfxFace.Wdt) Gfx.Set(Gfx.Surface, GfxFace.x, GfxFace.y, GfxFace.Wdt, GfxFace.Hgt);
		// set phase num
		int32_t Q; Gfx.GetPhaseNum(PhasesX, Q);
		Length = PhasesX * Q;
		if (!Length)
		{
			DebugLogF("invalid facet for particle '%s'", Name.getData());
			return false;
		}
				// calc aspect
		Aspect=(float) Gfx.Hgt/Gfx.Wdt;
		
		// particle overloading
		C4ParticleDef *def_overload;
		if ((def_overload = Particles.definitions.GetDef(Name.getData(), this)))
		{
			if (Config.Graphics.VerboseObjectLoading >= 1)
				{ char ostr[250]; sprintf(ostr,LoadResStr("IDS_PRC_DEFOVERLOAD"),def_overload->Name.getData(),"<particle>"); Log(ostr); }
			delete def_overload;
		}
		// success
		return true;
	}
	return false;
}
Example #11
0
void C4MaterialReaction::ResolveScriptFuncs(const char *szMatName)
{
	// get script func for script-defined behaviour
	if (pFunc == &C4MaterialMap::mrfScript)
	{
		pScriptFunc = ::ScriptEngine.GetPropList()->GetFunc(this->ScriptFunc.getData());
		if (!pScriptFunc)
			DebugLogF("Error getting function \"%s\" for Material reaction of \"%s\"", this->ScriptFunc.getData(), szMatName);
	}
	else
		pScriptFunc = NULL;
}
Example #12
0
bool C4Def::LoadSolidMask(C4Group &hGroup)
{
	if (hGroup.FindEntry(C4CFN_SolidMask))
	{
		pSolidMask = C4SolidMask::LoadMaskFromFile(hGroup, C4CFN_SolidMask);
		if (!pSolidMask)
		{
			DebugLogF("  Error loading SolidMask of %s (%s)", hGroup.GetFullName().getData(), id.ToString());
			return false;
		}
		// check SolidMask size
		if (SolidMask.x<0 || SolidMask.y<0 || SolidMask.x + SolidMask.Wdt>pSolidMask->Wdt || SolidMask.y + SolidMask.Hgt>pSolidMask->Hgt) SolidMask.Default();
	}
	else if (SolidMask.Wdt)
	{
		// Warning in case someone wants to define SolidMasks the old way (in the main graphics file)
		DebugLogF("WARNING: Definition %s (%s) defines SolidMask in DefCore but has no SolidMask file!", hGroup.GetFullName().getData(), id.ToString());
		SolidMask.Default();
	}

	return true;
}
Example #13
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;
	}
C4SoundInstance *C4SoundSystem::NewEffect(const char *szSndName, bool fLoop, int32_t iVolume, C4Object *pObj, int32_t iCustomFalloffDistance, int32_t iPitch, C4SoundModifier *modifier)
{
	// Sound not active
	if (!Config.Sound.RXSound) return NULL;
	// Get sound
	C4SoundEffect *csfx;
	if (!(csfx = GetEffect(szSndName)))
	{
		// Warn about missing or incorrectly spelled sound to allow finding mistakes earlier.
		DebugLogF("Warning: could not find sound matching '%s'", szSndName);
		return NULL;
	}
	// Play
	return csfx->New(fLoop, iVolume, pObj, iCustomFalloffDistance, iPitch, modifier);
}
void CStdMultimediaTimerProc::SetDelay(uint32_t iDelay)
{

	// Kill old timer (of any)
	if (idCriticalTimer)
		timeKillEvent(idCriticalTimer);

	// Set new delay
	uCriticalTimerDelay = iDelay;

	// Set critical timer
	idCriticalTimer=timeSetEvent(
	                  uCriticalTimerDelay,uCriticalTimerResolution,
	                  (LPTIMECALLBACK) Event.GetEvent(),0,TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);

	if(idCriticalTimer == 0)
		DebugLogF("Creating Critical Timer failed: %d", GetLastError());
}
Example #16
0
bool C4Def::LoadDefCore(C4Group &hGroup)
{
	StdStrBuf Source;
	if (hGroup.LoadEntryString(C4CFN_DefCore,&Source))
	{
		StdStrBuf Name = hGroup.GetFullName() + (const StdStrBuf &)FormatString("%cDefCore.txt", DirectorySeparator);
		if (!Compile(Source.getData(), Name.getData()))
			return false;
		Source.Clear();

		// Check mass
		if (Mass < 0)
		{
			DebugLogF("WARNING: Def %s (%s) at %s has invalid mass!", GetName(), id.ToString(), hGroup.GetFullName().getData());
			Mass = 0;
		}

		return true;
	}
	return false;
}
Example #17
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;
}
bool C4DefGraphics::LoadBitmap(C4Group &hGroup, const char *szFilename, const char *szOverlay, const char *szNormal, bool fColorByOwner)
{
	if (!szFilename) return false;
	Type = TYPE_Bitmap; // will be reset to TYPE_None in Clear() if loading fails
	Bmp.Bitmap = new C4Surface();
	if (!Bmp.Bitmap->Load(hGroup, szFilename, false, true, C4SF_MipMap))
	{
		Clear();
		return false;
	}

	// Create owner color bitmaps
	if (fColorByOwner)
	{
		// Create additionmal bitmap
		Bmp.BitmapClr=new C4Surface();
		// if overlay-surface is present, load from that
		if (szOverlay && Bmp.BitmapClr->Load(hGroup, szOverlay, false, false, C4SF_MipMap))
		{
			// set as Clr-surface, also checking size
			if (!Bmp.BitmapClr->SetAsClrByOwnerOf(Bmp.Bitmap))
			{
				DebugLogF("    Gfx loading error in %s: %s (%d x %d) doesn't match overlay %s (%d x %d) - invalid file or size mismatch",
				          hGroup.GetFullName().getData(), szFilename, Bmp.Bitmap ? Bmp.Bitmap->Wdt : -1, Bmp.Bitmap ? Bmp.Bitmap->Hgt : -1,
				          szOverlay, Bmp.BitmapClr->Wdt, Bmp.BitmapClr->Hgt);
				Clear();
				return false;
			}
		}
		else
		{
			// otherwise, create by all blue shades
			if (!Bmp.BitmapClr->CreateColorByOwner(Bmp.Bitmap))
			{
				Clear();
				return false;
			}
		}
		fColorBitmapAutoCreated = true;
	}

	if (szNormal)
	{
		Bmp.BitmapNormal = new C4Surface();
		if (Bmp.BitmapNormal->Load(hGroup, szNormal, false, true, C4SF_MipMap))
		{
			// Normal map loaded. Sanity check and link.
			if(Bmp.BitmapNormal->Wdt != Bmp.Bitmap->Wdt ||
			   Bmp.BitmapNormal->Hgt != Bmp.Bitmap->Hgt)
			{
				DebugLogF("    Gfx loading error in %s: %s (%d x %d) doesn't match normal %s (%d x %d) - invalid file or size mismatch",
				          hGroup.GetFullName().getData(), szFilename, Bmp.Bitmap ? Bmp.Bitmap->Wdt : -1, Bmp.Bitmap ? Bmp.Bitmap->Hgt : -1,
				          szNormal, Bmp.BitmapNormal->Wdt, Bmp.BitmapNormal->Hgt);
				Clear();
				return false;
			}

			Bmp.Bitmap->pNormalSfc = Bmp.BitmapNormal;
			if(Bmp.BitmapClr) Bmp.BitmapClr->pNormalSfc = Bmp.BitmapNormal;
		}
		else
		{
			// No normal map
			delete Bmp.BitmapNormal;
			Bmp.BitmapNormal = NULL;
		}
	}

	Type = TYPE_Bitmap;
	// success
	return true;
}
Example #19
0
	void OnError(const char *msg) override
	{
		DebugLogF("ERROR: %s", msg);
		++::ScriptEngine.errCnt;
	}
Example #20
0
	void OnWarning(const char *msg) override
	{
		DebugLogF("WARNING: %s", msg);
		++::ScriptEngine.warnCnt;
	}
Example #21
0
void C4GameObjects::FixObjectOrder() {
  // fixes the object order so it matches the global object order sorting
  // constraints
  C4ObjectLink *pLnk0 = First, *pLnkL = Last;
  while (pLnk0 != pLnkL) {
    C4ObjectLink *pLnk1stUnsorted = NULL, *pLnkLastUnsorted = NULL,
                 *pLnkPrev = NULL, *pLnk;
    C4Object *pLastWarnObj = NULL;
    // forward fix
    uint32_t dwLastCategory = C4D_SortLimit;
    for (pLnk = pLnk0; pLnk != pLnkL->Next; pLnk = pLnk->Next) {
      C4Object *pObj = pLnk->Obj;
      if (pObj->Unsorted || !pObj->Status) continue;
      DWORD dwCategory = pObj->Category & C4D_SortLimit;
      // must have exactly one SortOrder-bit set
      if (!dwCategory) {
        DebugLogF("Objects.txt: Object #%d is missing sorting category!",
                  (int)pObj->Number);
        ++pObj->Category;
        dwCategory = 1;
      } else {
        DWORD dwCat2 = dwCategory;
        int i = 0;
        while (~dwCat2 & 1) {
          dwCat2 = dwCat2 >> 1;
          ++i;
        }
        if (dwCat2 != 1) {
          DebugLogF("Objects.txt: Object #%d has invalid sorting category %x!",
                    (int)pObj->Number, (unsigned int)dwCategory);
          dwCategory = (1 << i);
          pObj->Category = (pObj->Category & ~C4D_SortLimit) | dwCategory;
        }
      }
      // fix order
      if (dwCategory > dwLastCategory) {
        // SORT ERROR! (note that pLnkPrev can't be 0)
        if (pLnkPrev->Obj != pLastWarnObj) {
          DebugLogF("Objects.txt: Wrong object order of #%d-#%d! (down)",
                    (int)pObj->Number, (int)pLnkPrev->Obj->Number);
          pLastWarnObj = pLnkPrev->Obj;
        }
        pLnk->Obj = pLnkPrev->Obj;
        pLnkPrev->Obj = pObj;
        pLnkLastUnsorted = pLnkPrev;
      } else
        dwLastCategory = dwCategory;
      pLnkPrev = pLnk;
    }
    if (!pLnkLastUnsorted) break;  // done
    pLnkL = pLnkLastUnsorted;
    // backwards fix
    dwLastCategory = 0;
    for (pLnk = pLnkL; pLnk != pLnk0->Prev; pLnk = pLnk->Prev) {
      C4Object *pObj = pLnk->Obj;
      if (pObj->Unsorted || !pObj->Status) continue;
      DWORD dwCategory = pObj->Category & C4D_SortLimit;
      if (dwCategory < dwLastCategory) {
        // SORT ERROR! (note that pLnkPrev can't be 0)
        if (pLnkPrev->Obj != pLastWarnObj) {
          DebugLogF("Objects.txt: Wrong object order of #%d-#%d! (up)",
                    (int)pObj->Number, (int)pLnkPrev->Obj->Number);
          pLastWarnObj = pLnkPrev->Obj;
        }
        pLnk->Obj = pLnkPrev->Obj;
        pLnkPrev->Obj = pObj;
        pLnk1stUnsorted = pLnkPrev;
      } else
        dwLastCategory = dwCategory;
      pLnkPrev = pLnk;
    }
    if (!pLnk1stUnsorted) break;  // done
    pLnk0 = pLnk1stUnsorted;
  }
  // objects fixed!
}
Example #22
0
int C4GameObjects::Load(C4Group &hGroup, bool fKeepInactive) {
  Clear(!fKeepInactive);

  // Load data component
  StdStrBuf Source;
  if (!hGroup.LoadEntryString(C4CFN_ScenarioObjects, Source)) return 0;

  // Compile
  StdStrBuf Name = hGroup.GetFullName() + DirSep C4CFN_ScenarioObjects;
  if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(mkParAdapt(*this, false),
                                                  Source, Name.getData()))
    return 0;

  // Process objects
  C4ObjectLink *cLnk = nullptr;
  C4Object *pObj = nullptr;
  bool fObjectNumberCollision = false;
  int32_t iMaxObjectNumber = 0;
  for (cLnk = Last; cLnk; cLnk = cLnk->Prev) {
    C4Object *pObj = cLnk->Obj;
    // check object number collision with inactive list
    if (fKeepInactive) {
      for (C4ObjectLink *clnk = InactiveObjects.First; clnk; clnk = clnk->Next)
        if (clnk->Obj->Number == pObj->Number) fObjectNumberCollision = true;
    }
    // keep track of numbers
    iMaxObjectNumber = Max<long>(iMaxObjectNumber, pObj->Number);
    // add to list of backobjects
    if (pObj->Category & C4D_Background)
      Game.BackObjects.Add(pObj, C4ObjectList::stMain, this);
    // add to list of foreobjects
    if (pObj->Category & C4D_Foreground)
      Game.ForeObjects.Add(pObj, C4ObjectList::stMain, this);
    // Unterminate end
  }

  // Denumerate pointers
  // if object numbers collideded, numbers will be adjusted afterwards
  // so fake inactive object list empty meanwhile
  C4ObjectLink *pInFirst = nullptr;
  if (fObjectNumberCollision) {
    pInFirst = InactiveObjects.First;
    InactiveObjects.First = NULL;
  }
  // denumerate pointers
  Denumerate();
  // update object enumeration index now, because calls like UpdateTransferZone
  // might create objects
  Game.ObjectEnumerationIndex =
      Max(Game.ObjectEnumerationIndex, iMaxObjectNumber);
  // end faking and adjust object numbers
  if (fObjectNumberCollision) {
    InactiveObjects.First = pInFirst;
    // simply renumber all inactive objects
    for (cLnk = InactiveObjects.First; cLnk; cLnk = cLnk->Next)
      if ((pObj = cLnk->Obj)->Status)
        pObj->Number = ++Game.ObjectEnumerationIndex;
  }

  // special checks:
  // -contained/contents-consistency
  // -StaticBack-objects zero speed
  for (cLnk = First; cLnk; cLnk = cLnk->Next)
    if ((pObj = cLnk->Obj)->Status) {
      // staticback must not have speed
      if (pObj->Category & C4D_StaticBack) {
        pObj->xdir = pObj->ydir = 0;
      }
      // contained must be in contents list
      if (pObj->Contained)
        if (!pObj->Contained->Contents.GetLink(pObj)) {
          DebugLogF(
              "Error in Objects.txt: Container of #%d is #%d, but not found in "
              "contents list!",
              pObj->Number, pObj->Contained->Number);
          pObj->Contained->Contents.Add(pObj, C4ObjectList::stContents);
        }
      // all contents must have contained set; otherwise, remove them!
      C4Object *pObj2;
      for (C4ObjectLink *cLnkCont = pObj->Contents.First; cLnkCont;
           cLnkCont = cLnkCont->Next) {
        // check double links
        if (pObj->Contents.GetLink(cLnkCont->Obj) != cLnkCont) {
          DebugLogF("Error in Objects.txt: Double containment of #%d by #%d!",
                    cLnkCont->Obj->Number, pObj->Number);
          // this remove-call will only remove the previous (dobuled) link, so
          // cLnkCont should be save
          pObj->Contents.Remove(cLnkCont->Obj);
          // contents checked already
          continue;
        }
        // check contents/contained-relation
        if ((pObj2 = cLnkCont->Obj)->Status)
          if (pObj2->Contained != pObj) {
            DebugLogF(
                "Error in Objects.txt: Object #%d not in container #%d as "
                "referenced!",
                pObj2->Number, pObj->Number);
            pObj2->Contained = pObj;
          }
      }
    }
  // sort out inactive objects
  C4ObjectLink *cLnkNext;
  for (cLnk = First; cLnk; cLnk = cLnkNext) {
    cLnkNext = cLnk->Next;
    if (cLnk->Obj->Status == C4OS_INACTIVE) {
      if (cLnk->Prev)
        cLnk->Prev->Next = cLnkNext;
      else
        First = cLnkNext;
      if (cLnkNext)
        cLnkNext->Prev = cLnk->Prev;
      else
        Last = cLnk->Prev;
      if (cLnk->Prev = InactiveObjects.Last)
        InactiveObjects.Last->Next = cLnk;
      else
        InactiveObjects.First = cLnk;
      InactiveObjects.Last = cLnk;
      cLnk->Next = NULL;
      Mass -= pObj->Mass;
    }
  }

  {
    C4DebugRecOff DBGRECOFF;  // - script callbacks that would kill
                              // DebugRec-sync for runtime start
    // update graphics
    UpdateGraphics(false);
    // Update faces
    UpdateFaces(false);
    // Update ocf
    SetOCF();
  }

  // make sure list is sorted by category - after sorting out inactives, because
  // inactives aren't sorted into the main list
  FixObjectOrder();

  // Sectors.Dump();

  // misc updates
  for (cLnk = First; cLnk; cLnk = cLnk->Next)
    if ((pObj = cLnk->Obj)->Status) {
      // add to plrview
      pObj->PlrFoWActualize();
      // update flipdir (for old objects.txt with no flipdir defined)
      // assigns Action.DrawDir as well
      pObj->UpdateFlipDir();
    }
  // Done
  return ObjectCount();
}
Example #23
0
int32_t FnFxFireStart(C4AulContext *ctx, C4Object *pObj, int32_t iNumber,
                      int32_t iTemp, int32_t iCausedBy, bool fBlasted,
                      C4Object *pIncineratingObject) {
  // safety
  if (!pObj)
    return -1;
  // temp readd
  if (iTemp) {
    pObj->SetOnFire(true);
    return 1;
  }
  // fail if already on fire
  if (pObj->GetOnFire())
    return -1;
  // get associated effect
  C4Effect *pEffect;
  if (!(pEffect = pObj->pEffects))
    return -1;
  if (!(pEffect = pEffect->Get(iNumber, true)))
    return -1;
  // structures must eject contents now, because DoCon is not guaranteed to be
  // executed!
  // In extinguishing material
  BOOL fFireCaused = TRUE;
  int32_t iMat;
  if (MatValid(iMat = GBackMat(pObj->x, pObj->y)))
    if (Game.Material.Map[iMat].Extinguisher) {
      // blasts should changedef in water, too!
      if (fBlasted)
        if (pObj->Def->BurnTurnTo != C4ID_None)
          pObj->ChangeDef(pObj->Def->BurnTurnTo);
      // no fire caused
      fFireCaused = FALSE;
    }
  // BurnTurnTo
  if (fFireCaused)
    if (pObj->Def->BurnTurnTo != C4ID_None)
      pObj->ChangeDef(pObj->Def->BurnTurnTo);
  // eject contents
  C4Object *cobj;
  if (!pObj->Def->IncompleteActivity && !pObj->Def->NoBurnDecay)
    while (cobj = pObj->Contents.GetObject()) {
      cobj->Controller = iCausedBy; // update controller, so incinerating a hut
                                    // full of flints attributes the damage to
                                    // the incinerator
      if (pObj->Contained)
        cobj->Enter(pObj->Contained);
      else
        cobj->Exit(cobj->x, cobj->y);
    }
  // Detach attached objects
  cobj = 0;
  if (!pObj->Def->IncompleteActivity && !pObj->Def->NoBurnDecay)
    while (cobj = Game.FindObject(0, 0, 0, 0, 0, OCF_All, 0, pObj, 0, 0,
                                  ANY_OWNER, cobj))
      if ((cobj->Action.Act > ActIdle) &&
          (cobj->Def->ActMap[cobj->Action.Act].Procedure == DFA_ATTACH))
        cobj->SetAction(ActIdle);
  // fire caused?
  if (!fFireCaused) {
    // if object was blasted but not incinerated (i.e., inside extinguisher)
    // do a script callback
    if (fBlasted)
      pObj->Call(PSF_IncinerationEx, &C4AulParSet(C4VInt(iCausedBy)));
    return -1;
  }
  // determine fire appearance
  int32_t iFireMode;
  if (!(iFireMode = pObj->Call(PSF_FireMode).getInt())) {
    // set default fire modes
    DWORD dwCat = pObj->Category;
    if (dwCat & (C4D_Living | C4D_StaticBack)) // Tiere, Bäume
      iFireMode = C4Fx_FireMode_LivingVeg;
    else if (dwCat & (C4D_Structure | C4D_Vehicle)) // Gebäude und Fahrzeuge
                                                    // sind unten meist kantig
      iFireMode = C4Fx_FireMode_StructVeh;
    else
      iFireMode = C4Fx_FireMode_Object;
  } else if (!Inside<int32_t>(iFireMode, 1, C4Fx_FireMode_Last)) {
    DebugLogF("Warning: FireMode %d of object %s (%s) is invalid!", iFireMode,
              pObj->GetName(), pObj->Def->GetName());
    iFireMode = C4Fx_FireMode_Object;
  }
  // store causes in effect vars
  FxFireVarMode(pEffect).SetInt(iFireMode);
  FxFireVarCausedBy(pEffect)
      .SetInt(iCausedBy); // used in C4Object::GetFireCause and timer!
  FxFireVarBlasted(pEffect).SetBool(fBlasted);
  FxFireVarIncineratingObj(pEffect).SetObject(pIncineratingObject);
  // Set values
  pObj->SetOnFire(true);
  pObj->FirePhase = Random(MaxFirePhase);
  if (pObj->Shape.Wdt * pObj->Shape.Hgt > 500)
    StartSoundEffect("Inflame", false, 100, pObj);
  if (pObj->Def->Mass >= 100)
    StartSoundEffect("Fire", true, 100, pObj);
  // Engine script call
  pObj->Call(PSF_Incineration, &C4AulParSet(C4VInt(iCausedBy)));
  // Done, success
  return C4Fx_OK;
}