示例#1
0
ALERROR WriteSubModules (CTDBCompiler &Ctx, 
						 CXMLElement *pModule,
						 const CString &sFolder, 
						 CDataFile &Out)
	{
	int i, j;

	for (i = 0; i < pModule->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pModule->GetContentElement(i);

		if (strEquals(pItem->GetTag(), TAG_MODULES))
			{
			for (j = 0; j < pItem->GetContentElementCount(); j++)
				{
				CXMLElement *pDesc = pItem->GetContentElement(j);

				CString sFilename = pDesc->GetAttribute(ATTRIB_FILENAME);
				if (WriteModule(Ctx, sFilename, sFolder, Out) != NOERROR)
					continue;
				}
			}
		else if (strEquals(pItem->GetTag(), TAG_MODULE))
			{
			CString sFilename = pItem->GetAttribute(ATTRIB_FILENAME);
			if (WriteModule(Ctx, sFilename, sFolder, Out) != NOERROR)
				continue;
			}
		}

	return NOERROR;
	}
示例#2
0
ALERROR WriteModuleSounds (CTDBCompiler &Ctx, CXMLElement *pModule, const CString &sFolder, CDataFile &Out)
	{
	ALERROR error;
	int i;

	for (i = 0; i < pModule->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pModule->GetContentElement(i);
		if (strEquals(pItem->GetTag(), TAG_SOUNDS))
			{
			CString sSubFolder = pathAddComponent(sFolder, pItem->GetAttribute(ATTRIB_FOLDER));

			if (error = WriteModuleSounds(Ctx, pItem, sSubFolder, Out))
				return error;
			}
		else if (strEquals(pItem->GetTag(), TAG_SOUND))
			{
			CString sFilename = pItem->GetAttribute(ATTRIB_FILENAME);
			if (error = WriteResource(Ctx, sFilename, sFolder, false, Out))
				continue;
			}
		}

	return NOERROR;
	}
示例#3
0
ALERROR WriteModuleImages (CXMLElement *pModule, const CString &sFolder, CSymbolTable &Resources, CDataFile &Out)
	{
	ALERROR error;
	int i;

	for (i = 0; i < pModule->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pModule->GetContentElement(i);
		if (strEquals(pItem->GetTag(), TAG_IMAGES))
			{
			CString sSubFolder = pathAddComponent(sFolder, pItem->GetAttribute(ATTRIB_FOLDER));

			if (error = WriteModuleImages(pItem, sSubFolder, Resources, Out))
				return error;
			}
		else if (strEquals(pItem->GetTag(), TAG_IMAGE))
			{
			CString sFilename = pItem->GetAttribute(ATTRIB_BITMAP);
			if (!sFilename.IsBlank())
				{
				if (error = WriteResource(sFilename, sFolder, Resources, Out))
					continue;
				}

			sFilename = pItem->GetAttribute(ATTRIB_BITMASK);
			if (!sFilename.IsBlank())
				{
				if (error = WriteResource(sFilename, sFolder, Resources, Out))
					continue;
				}
			}
		}

	return NOERROR;
	}
示例#4
0
bool AddTrait (CNPWorld *pWorld, 
			   CXMLElement *pTraitTable, 
			   CXMLElement *pTrait, 
			   CSymbolTable &Symbols)
	{
	int i;

	//	First check to see if the world has any of the traits
	//	listed in the "unless" sections

	for (i = 0; i < pTrait->GetContentElementCount(); i++)
		{
		CXMLElement *pUnless = pTrait->GetContentElement(i);
		if (strCompare(pUnless->GetTag(), CONSTLIT("Unless")) != 0)
			continue;

		//	If the world has the prohibited trait then we cannot
		//	add the desired trait.

		if (pWorld->HasTrait(GetSymbolicAttribute(Symbols, pUnless, CONSTLIT("Trait"))))
			return false;
		}

	//	Add the trait

	pWorld->SetTrait(GetSymbolicAttribute(Symbols, pTrait, CONSTLIT("Trait")));

	//	Add any traits that are implied by this trait

	for (i = 0; i < pTrait->GetContentElementCount(); i++)
		{
		CXMLElement *pImply = pTrait->GetContentElement(i);
		if (strCompare(pImply->GetTag(), CONSTLIT("Imply")) != 0)
			continue;

		//	Random chance of actually having this trait

		if (mathRandom(1, 100) > pImply->GetAttributeInteger(CONSTLIT("Prob")))
			continue;

		//	If we already have this trait the don't bother

		if (pWorld->HasTrait(GetSymbolicAttribute(Symbols, pImply, CONSTLIT("Trait"))))
			continue;

		//	Look for the implied trait in the table

		CXMLElement *pNewTrait = FindTraitInTable(pTraitTable, pImply->GetAttribute(CONSTLIT("Trait")));

		//	Add it. Note that we don't care if we cannot

		if (pNewTrait)
			AddTrait(pWorld, pTraitTable, pNewTrait, Symbols);
		}

	return true;
	}
示例#5
0
ALERROR WriteModuleImages (CTDBCompiler &Ctx, CXMLElement *pModule, const CString &sFolder, CDataFile &Out)
	{
	ALERROR error;
	int i;

	for (i = 0; i < pModule->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pModule->GetContentElement(i);
		if (strEquals(pItem->GetTag(), TAG_IMAGES))
			{
			CString sSubFolder = pathAddComponent(sFolder, pItem->GetAttribute(ATTRIB_FOLDER));

			if (error = WriteModuleImages(Ctx, pItem, sSubFolder, Out))
				return error;
			}
		else if (strEquals(pItem->GetTag(), TAG_IMAGE))
			{
			CString sFilename = pItem->GetAttribute(ATTRIB_BITMAP);
			if (!sFilename.IsBlank())
				{
				bool bCompress = strEquals(strToLower(pathGetExtension(sFilename)), CONSTLIT("bmp"));
				if (error = WriteResource(Ctx, sFilename, sFolder, bCompress, Out))
					continue;
				}

			sFilename = pItem->GetAttribute(ATTRIB_BITMASK);
			if (!sFilename.IsBlank())
				{
				bool bCompress = strEquals(strToLower(pathGetExtension(sFilename)), CONSTLIT("bmp"));
				if (error = WriteResource(Ctx, sFilename, sFolder, bCompress, Out))
					continue;
				}

			sFilename = pItem->GetAttribute(ATTRIB_SHADOW_MASK);
			if (!sFilename.IsBlank())
				{
				bool bCompress = strEquals(strToLower(pathGetExtension(sFilename)), CONSTLIT("bmp"));
				if (error = WriteResource(Ctx, sFilename, sFolder, bCompress, Out))
					continue;
				}

			sFilename = pItem->GetAttribute(ATTRIB_HIT_MASK);
			if (!sFilename.IsBlank())
				{
				bool bCompress = strEquals(strToLower(pathGetExtension(sFilename)), CONSTLIT("bmp"));
				if (error = WriteResource(Ctx, sFilename, sFolder, bCompress, Out))
					continue;
				}
			}
		}

	return NOERROR;
	}
示例#6
0
ALERROR CSystemMap::ExecuteCreator (STopologyCreateCtx &Ctx, CTopology &Topology, CXMLElement *pCreator)

//	ExecuteCreator
//
//	Runs a specific creator

	{
	ALERROR error;
	int i;

	//	If this is a root node tag then we add it and all its connections.

	if (strEquals(pCreator->GetTag(), ROOT_NODE_TAG))
		{
		if (error = Topology.AddTopologyNode(Ctx, pCreator->GetAttribute(ID_ATTRIB)))
			return error;
		}

	//	Otherwise we process the creator element

	else
		{
		for (i = 0; i < pCreator->GetContentElementCount(); i++)
			{
			CXMLElement *pDirective = pCreator->GetContentElement(i);

			if (strEquals(pDirective->GetTag(), NODE_TAG))
				{
				if (error = Topology.AddTopologyNode(Ctx, pDirective->GetAttribute(ID_ATTRIB)))
					return error;
				}
			else if (strEquals(pDirective->GetTag(), STARGATE_TAG) || strEquals(pDirective->GetTag(), STARGATES_TAG))
				{
				if (error = Topology.AddStargateFromXML(Ctx, pDirective))
					return error;
				}
			else
				{
				Ctx.sError = strPatternSubst(CONSTLIT("Unknown TopologyCreator directive: %s."), pDirective->GetTag());
				return ERR_FAIL;
				}
			}
		}

	return NOERROR;
	}
示例#7
0
ALERROR CShapeEffectCreator::OnEffectCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc, const CString &sUNID)

//	OnEffectCreateFromXML
//
//	Load from XML

	{
	int i;
	CString sAttrib;

	m_iWidth = pDesc->GetAttributeInteger(SCALE_WIDTH_ATTRIB);
	m_iLength = pDesc->GetAttributeInteger(SCALE_LENGTH_ATTRIB);
	m_bDirectional = pDesc->GetAttributeBool(DIRECTIONAL_ATTRIB);
	m_iWidthInc = pDesc->GetAttributeInteger(SCALE_WIDTH_INC_ATTRIB);
	m_iLengthInc = pDesc->GetAttributeInteger(SCALE_LENGTH_INC_ATTRIB);
	m_wColor = ::LoadRGBColor(pDesc->GetAttribute(COLOR_ATTRIB));

	if (pDesc->FindAttribute(OPACITY_ATTRIB, &sAttrib))
		m_byOpacity = strToInt(sAttrib, 255);
	else
		m_byOpacity = 255;

	//	Initialize the points structure

	m_iPointCount = pDesc->GetContentElementCount();
	if (m_iPointCount > 0)
		{
		m_Points = new SPoint [m_iPointCount];
		m_TransBuffer = new SPoint [m_iPointCount];

		for (i = 0; i < m_iPointCount; i++)
			{
			CXMLElement *pPointDesc = pDesc->GetContentElement(i);
			if (!strEquals(pPointDesc->GetTag(), POINT_TAG))
				{
				Ctx.sError = CONSTLIT("<Point> element expected");
				return ERR_FAIL;
				}

			m_Points[i].x = pPointDesc->GetAttributeInteger(X_ATTRIB);
			m_Points[i].y = pPointDesc->GetAttributeInteger(Y_ATTRIB);
			}

		//	Convex polygons (which remain convex no matter the rotation) can be
		//	computed faster with an optimized algorithm, so we keep track here.

		m_bConvexPolygon = IsConvexPolygon(m_iPointCount, m_Points);
		}
	else
		{
		m_Points = NULL;
		m_TransBuffer = NULL;
		m_bConvexPolygon = true;
		}

	return NOERROR;
	}
示例#8
0
ALERROR CEventHandler::InitFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	InitFromXML
//
//	Load all handlers

	{
	int i;

	for (i = 0; i < pDesc->GetContentElementCount(); i++)
		{
		CXMLElement *pHandler = pDesc->GetContentElement(i);
		ICCItem *pCode = g_pUniverse->GetCC().Link(pHandler->GetContentText(0), 0, NULL);
		if (pCode->IsError())
			{
			Ctx.sError = strPatternSubst("<%s> event: %s", pHandler->GetTag(), pCode->GetStringValue());
			return ERR_FAIL;
			}

		//	If this is an old extension, then make sure the code is not using the
		//	gStation variable, because we no longer support it

		if (Ctx.pExtension && Ctx.pExtension->dwVersion < 2)
			{
			if (g_pUniverse->GetCC().HasIdentifier(pCode, CONSTLIT("gStation")))
				{
				Ctx.sError = CONSTLIT("gStation variable has been deprecated--use gSource instead.");
				return ERR_FAIL;
				}
			}

		//	Done

		m_Handlers.Insert(pHandler->GetTag(), pCode);
		}

	return NOERROR;
	}
ALERROR CGroupOfDeviceGenerators::LoadFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	LoadFromXML
//
//	Load from XML

	{
	int i;
	ALERROR error;

	m_Count.LoadFromXML(pDesc->GetAttribute(COUNT_ATTRIB));
	if (m_Count.IsEmpty())
		m_Count.SetConstant(1);

	//	Load either a <DeviceSlot> element or another device generator.

	for (i = 0; i < pDesc->GetContentElementCount(); i++)
		{
		CXMLElement *pEntry = pDesc->GetContentElement(i);

		if (strEquals(pEntry->GetTag(), DEVICE_SLOT_TAG))
			{
			SSlotDesc *pSlotDesc = m_SlotDesc.Insert();

			CItem::ParseCriteria(pEntry->GetAttribute(CRITERIA_ATTRIB), &pSlotDesc->Criteria);

			if (error = IDeviceGenerator::InitDeviceDescFromXML(Ctx, pEntry, &pSlotDesc->DefaultDesc))
				return error;

			pSlotDesc->iMaxCount = pEntry->GetAttributeIntegerBounded(MAX_COUNT_ATTRIB, 0, -1, -1);
			}
		else
			{
			SEntry *pTableEntry = m_Table.Insert();

			pTableEntry->iChance = pEntry->GetAttributeIntegerBounded(CHANCE_ATTRIB, 0, -1, 100);
			if (error = IDeviceGenerator::CreateFromXML(Ctx, pEntry, &pTableEntry->pDevice))
				{
				pTableEntry->pDevice = NULL;
				return error;
				}
			}
		}

	return NOERROR;
	}
示例#10
0
ALERROR CExtension::LoadSystemTypesElement (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	LoadSystemTypesElement
//
//	Loads <SystemTypes> element
//	(For backwards compatibility)

	{
	ALERROR error;
	int i;

	for (i = 0; i < pDesc->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pDesc->GetContentElement(i);

		if (strEquals(pItem->GetTag(), TABLES_TAG))
			{
			CSystemTable *pTable = new CSystemTable;
			pTable->InitFromXML(Ctx, pItem);
			if (pTable->GetUNID() == 0)
				pTable->SetUNID(DEFAULT_SYSTEM_TABLE_UNID);

			if (error = m_DesignTypes.AddEntry(pTable))
				{
				Ctx.sError = strPatternSubst(CONSTLIT("Error adding system table: %x"), pTable->GetUNID());
				return error;
				}
			}
		else
			{
			if (error = LoadDesignType(Ctx, pItem))
				return error;
			}
		}

	return NOERROR;
	}
示例#11
0
ALERROR CUniverse::InitStarSystemTypes (SDesignLoadCtx &Ctx, CXMLElement *pElement)

//	InitStarSystemTypes
//
//	Load <StarSystemTypes> tag

	{
	ALERROR error;
	int i;

	for (i = 0; i < pElement->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pElement->GetContentElement(i);

		if (strEquals(pItem->GetTag(), TABLES_TAG))
			{
			if (m_pSystemTables)
				{
				Ctx.sError = CONSTLIT("Multiple global tables found in <StarSystemDescriptions>");
				return ERR_FAIL;
				}

			m_pSystemTables = pItem->OrphanCopy();
			}
		else
			{
			if (error = m_Design.LoadEntryFromXML(Ctx, pItem))
				return error;

#ifdef DEBUG_SOURCE_LOAD_TRACE
			kernelDebugLogMessage("Loaded system type: %x", dwUNID);
#endif
			}
		}

	return NOERROR;
	}
示例#12
0
ALERROR CNPUniverse::CreateSovereign (CString sName, CNPWorld *pCapital, CXMLElement *pSovTemplate, CNPSovereign **retpSovereign)

//	CreateSovereign
//
//	Creates a new sovereign

	{
	ALERROR error;
	CNPSovereign *pSovereign;
	int i;

	if (error = CNPSovereign::Create(m_Sovereigns.RegisterEntry(), sName, &pSovereign))
		return error;

	m_Sovereigns.SetEntry(pSovereign->GetUNID(), pSovereign);

	//	Obviously we know about ourselves

	pSovereign->SetKnowledge(pSovereign->GetUNID());

	//	Set a capital

	if (pCapital)
		{
		pSovereign->SetCapital(pCapital->GetUNID());

		pCapital->RemoveTrait(traitReservedCapital);
		pCapital->SetTrait(traitCapital);
		pCapital->SetSovereign(pSovereign);

		//	Scan the capital

		CNPNullPoint *pNP = GetNullPoint(pCapital->GetLocation());
		ScanNullPoint(pSovereign, pNP, 1);

		//	Scan the area around the capital

		for (i = 0; i < pNP->GetLinkCount(); i++)
			{
			CNPNullPoint *pDest = pNP->GetLinkDest(i);
			ScanNullPoint(pSovereign, pDest, 1);
			}

		//	Create ships

		if (pSovTemplate)
			{
			CNPFleet *pFleet = NULL;
			for (i = 0; i < pSovTemplate->GetContentElementCount(); i++)
				{
				CXMLElement *pShip = pSovTemplate->GetContentElement(i);
				if (strCompare(pShip->GetTag(), CONSTLIT("Unit")) == 0)
					{
					//	Create the fleet, if needed

					if (pFleet == NULL)
						if (error = CreateFleet(pNP, pSovereign, &pFleet))
							return error;

					//	Add the ship to the fleet

					CNPUnit Unit(pShip->GetAttributeInteger(CONSTLIT("Class")), 0, 0);
					pFleet->GetAssetList().AddUnit(Unit);
					}
				}
			}
		}

	//	Done

	if (retpSovereign)
		*retpSovereign = pSovereign;

	return NOERROR;
	}
示例#13
0
ALERROR CExtension::CreateBaseFile (SDesignLoadCtx &Ctx, EGameTypes iGame, CXMLElement *pDesc, CExternalEntityTable *pEntities, CExtension **retpBase, TArray<CXMLElement *> *retEmbedded)

//	CreateBaseFile
//
//	Loads a new extension from the base file.

	{
	ALERROR error;
	int i;

	//	Create an extension object

	CExtension *pExtension = new CExtension;
	pExtension->m_sFilespec = Ctx.sResDb;
	pExtension->m_dwUNID = 0;	//	Base is the only extension with 0 UNID.
	pExtension->m_iGame = iGame;
	pExtension->m_iType = extBase;
	pExtension->m_iLoadState = loadEntities;
	pExtension->m_iFolderType = folderBase;
	pExtension->m_pEntities = pEntities;
	pExtension->m_ModifiedTime = fileGetModifiedTime(Ctx.sResDb);
	pExtension->m_bRegistered = true;
	pExtension->m_bPrivate = true;
	pExtension->m_bAutoInclude = true;
	pExtension->m_bUsesXML = false;
	pExtension->m_bUsesCompatibilityLibrary = false;

	//	Load the apiVersion

	CString sAPIVersion;
	if (pDesc->FindAttribute(API_VERSION_ATTRIB, &sAPIVersion))
		{
		pExtension->m_dwAPIVersion = (DWORD)strToInt(sAPIVersion, 0);
		if (pExtension->m_dwAPIVersion < 12)
			pExtension->m_dwAPIVersion = 0;
		}

	//	If this version is later than what we expect, then we fail.

	if (pExtension->m_dwAPIVersion > API_VERSION)
		{
		pExtension->m_pEntities = NULL;	//	Let our parent clean up
		delete pExtension;
		Ctx.sError = CONSTLIT("Newer version of the Transcendence engine is required.");
		return ERR_FAIL;
		}

	//	We return the base extension

	*retpBase = pExtension;

	//	Set up context

	Ctx.pExtension = pExtension;

	//	Load the Main XML file

	for (i = 0; i < pDesc->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pDesc->GetContentElement(i);

		//	<Images>

		if (strEquals(pItem->GetTag(), IMAGES_TAG))
			error = pExtension->LoadImagesElement(Ctx, pItem);

		//	<Sounds>

		else if (strEquals(pItem->GetTag(), SOUNDS_TAG))
			error = pExtension->LoadSoundsElement(Ctx, pItem);

		//	<SystemTypes>

		else if (strEquals(pItem->GetTag(), SYSTEM_TYPES_TAG))
			error = pExtension->LoadSystemTypesElement(Ctx, pItem);

		//	<TranscendenceAdventure>

		else if (strEquals(pItem->GetTag(), TRANSCENDENCE_ADVENTURE_TAG)
				|| strEquals(pItem->GetTag(), TRANSCENDENCE_LIBRARY_TAG)
				|| strEquals(pItem->GetTag(), CORE_LIBRARY_TAG))
			{
			//	Return this as an embedded extension

			retEmbedded->Insert(pItem);
			error = NOERROR;
			}

		//	Other types

		else
			error = pExtension->LoadDesignElement(Ctx, pItem);

		//	Check for error

		if (error)
			{
			pExtension->m_pEntities = NULL;	//	Let our parent clean up
			delete pExtension;
			return error;
			}
		}

	//	Restore

	Ctx.pExtension = NULL;

	//	Done

	pExtension->m_iLoadState = loadComplete;

	return NOERROR;
	}
示例#14
0
ALERROR CWeaponFireDesc::InitFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc, const CString &sUNID, bool bDamageOnly)

//	InitFromXML
//
//	Loads shot data from an element

	{
	ALERROR error;
	int i;

	m_pExtension = Ctx.pExtension;
	m_fVariableInitialSpeed = false;
	m_bFragment = false;

	//	Load basic attributes

	m_sUNID = sUNID;
	m_Lifetime.LoadFromXML(pDesc->GetAttribute(LIFETIME_ATTRIB));
	int iMaxLifetime = m_Lifetime.GetMaxValue();
	m_bCanDamageSource = pDesc->GetAttributeBool(CAN_HIT_SOURCE_ATTRIB);
	m_bAutoTarget = pDesc->GetAttributeBool(AUTO_TARGET_ATTRIB);
	m_bNoFriendlyFire = pDesc->GetAttributeBool(NO_FRIENDLY_FIRE_ATTRIB);
	m_InitialDelay.LoadFromXML(pDesc->GetAttribute(INITIAL_DELAY_ATTRIB));

	//	Load missile speed

	CString sData;
	if (pDesc->FindAttribute(MISSILE_SPEED_ATTRIB, &sData))
		{
		if (error = m_MissileSpeed.LoadFromXML(sData))
			{
			Ctx.sError = CONSTLIT("Invalid missile speed attribute");
			return ERR_FAIL;
			}

		m_fVariableInitialSpeed = !m_MissileSpeed.IsConstant();
		m_rMissileSpeed = (double)m_MissileSpeed.GetAveValue() * LIGHT_SPEED / 100;
		}
	else
		{
		m_fVariableInitialSpeed = false;
		m_rMissileSpeed = LIGHT_SPEED;
		}

	//	Load the effect to use

	if (error = m_pEffect.LoadEffect(Ctx, 
			strPatternSubst("%s:e", sUNID),
			pDesc->GetContentElementByTag(EFFECT_TAG),
			pDesc->GetAttribute(EFFECT_ATTRIB)))
		return error;

	//	Load stealth

	m_iStealth = pDesc->GetAttributeInteger(STEALTH_ATTRIB);
	if (m_iStealth == 0)
		m_iStealth = CSpaceObject::stealthNormal;

	//	Other properties

	m_iSplashChance = pDesc->GetAttributeIntegerBounded(PARTICLE_SPLASH_CHANCE_ATTRIB, 0, 100, 0);
	m_iMissChance = pDesc->GetAttributeIntegerBounded(PARTICLE_MISS_CHANCE_ATTRIB, 0, 100, 0);

	//	Load specific properties

	CString sValue = pDesc->GetAttribute(FIRE_TYPE_ATTRIB);
	if (strEquals(sValue, FIRE_TYPE_MISSILE) || strEquals(sValue, FIRE_TYPE_BEAM))
		{
		m_iFireType = (strEquals(sValue, FIRE_TYPE_BEAM) ? ftBeam : ftMissile);

		//	For backwards compatibility, if we don't have an effect, assume
		//	a beam effect.

		if (m_iFireType == ftBeam && m_pEffect == NULL)
			{
			if (error = m_pEffect.CreateBeamEffect(Ctx, pDesc, strPatternSubst("%s:e", sUNID)))
				return error;

			//	Backwards compatibility in case a CBeam object is loaded from
			//	an old save file.

			m_iBeamType = beamLaser;
			m_wPrimaryColor = CG16bitImage::RGBValue(0xf1, 0x5f, 0x2a);
			m_wSecondaryColor = CG16bitImage::RGBValue(0xff, 0x00, 0x00);
			m_iIntensity = 1;
			}

		//	Load the image for the missile

		CXMLElement *pImage = pDesc->GetContentElementByTag(IMAGE_TAG);
		if (pImage)
			if (error = m_Image.InitFromXML(Ctx, pImage))
				return error;

		m_bDirectional = pDesc->GetAttributeBool(DIRECTIONAL_ATTRIB);
		if (m_bDirectional && m_pEffect)
			m_pEffect->SetVariants(g_RotationRange);

		m_iAccelerationFactor = pDesc->GetAttributeInteger(ACCELERATION_FACTOR_ATTRIB);
		int iMaxSpeed = pDesc->GetAttributeInteger(MAX_MISSILE_SPEED_ATTRIB);
		if (iMaxSpeed == 0)
			m_rMaxMissileSpeed = m_rMissileSpeed;
		else
			m_rMaxMissileSpeed = (Metric)iMaxSpeed * LIGHT_SPEED / 100.0;

		//	Hit points and interaction

		m_iHitPoints = pDesc->GetAttributeInteger(HIT_POINTS_ATTRIB);
		CString sInteraction;
		if (pDesc->FindAttribute(INTERACTION_ATTRIB, &sInteraction))
			m_iInteraction = strToInt(sInteraction, 100);
		else
			m_iInteraction = (m_iFireType == ftBeam ? 0 : 100);

		//	Load exhaust data

		CXMLElement *pExhaust = pDesc->GetContentElementByTag(MISSILE_EXHAUST_TAG);
		if (pExhaust)
			{
			m_iExhaustRate = pExhaust->GetAttributeInteger(EXHAUST_RATE_ATTRIB);
			m_iExhaustLifetime = pExhaust->GetAttributeInteger(EXHAUST_LIFETIME_ATTRIB);
			m_rExhaustDrag = pExhaust->GetAttributeInteger(EXHAUST_DRAG_ATTRIB) / 100.0;

			CXMLElement *pImage = pExhaust->GetContentElementByTag(IMAGE_TAG);
			if (error = m_ExhaustImage.InitFromXML(Ctx, pImage))
				return error;
			}
		else
			{
			m_iExhaustRate = 0;
			m_iExhaustLifetime = 0;
			m_rExhaustDrag = 0.0;
			}
		}
	else if (strEquals(sValue, FIRE_TYPE_AREA))
		{
		m_iFireType = ftArea;

		m_rMaxMissileSpeed = m_rMissileSpeed;

		//	Load expansion speed

		if (pDesc->FindAttribute(EXPANSION_SPEED_ATTRIB, &sData))
			{
			if (error = m_ExpansionSpeed.LoadFromXML(sData))
				{
				Ctx.sError = CONSTLIT("Invalid expansionSpeed attribute");
				return ERR_FAIL;
				}
			}
		else
			m_ExpansionSpeed.SetConstant(20);

		//	Area damage density

		if (pDesc->FindAttribute(AREA_DAMAGE_DENSITY_ATTRIB, &sData))
			{
			if (error = m_AreaDamageDensity.LoadFromXML(sData))
				{
				Ctx.sError = CONSTLIT("Invalid areaDamageDensity attribute");
				return ERR_FAIL;
				}
			}
		else
			m_AreaDamageDensity.SetConstant(32);

		//	Must have effect

		if (m_pEffect == NULL)
			{
			Ctx.sError = CONSTLIT("Must have <Effect> for area damage.");
			return ERR_FAIL;
			}
		}
	else if (strEquals(sValue, FIRE_TYPE_PARTICLES))
		{
		m_iFireType = ftParticles;

		m_rMaxMissileSpeed = m_rMissileSpeed;

		if (error = m_ParticleCount.LoadFromXML(pDesc->GetAttribute(PARTICLE_COUNT_ATTRIB)))
			{
			Ctx.sError = CONSTLIT("Invalid particle count.");
			return error;
			}

		if (error = m_ParticleEmitTime.LoadFromXML(pDesc->GetAttribute(PARTICLE_EMIT_TIME_ATTRIB)))
			{
			Ctx.sError = CONSTLIT("Invalid particle emit time.");
			return error;
			}

		m_iParticleSpread = pDesc->GetAttributeInteger(PARTICLE_SPREAD_ANGLE_ATTRIB);
		m_iParticleSpreadWidth = pDesc->GetAttributeInteger(PARTICLE_SPREAD_WIDTH_ATTRIB);
		}
	else if (strEquals(sValue, FIRE_TYPE_RADIUS))
		{
		m_iFireType = ftRadius;

		m_rMaxMissileSpeed = m_rMissileSpeed;

		m_rMinRadius = LIGHT_SECOND * (Metric)pDesc->GetAttributeInteger(MIN_RADIUS_ATTRIB);
		m_rMaxRadius = LIGHT_SECOND * (Metric)pDesc->GetAttributeInteger(MAX_RADIUS_ATTRIB);

		//	For radius, lifetime attribute is not required. We always set the lifetime
		//	to the effect lifetime.

		if (m_pEffect && iMaxLifetime == 0)
			{
			int iEffectLifetime = m_pEffect->GetLifetime();

			//	If the effect lifetime is infinite then change it
			//	to something more finite (this is technically an error condition)

			if (iEffectLifetime == -1)
				iEffectLifetime = 666;

			m_Lifetime.SetConstant(iEffectLifetime);
			iMaxLifetime = iEffectLifetime;
			}
		}
	else if (!bDamageOnly)
		{
		Ctx.sError = CONSTLIT("Invalid weapon fire type");
		return ERR_FAIL;
		}

	//	The effect should have the same lifetime as the shot
	//	Note: For radius damage it is the other way around (we set iMaxLifetime based on
	//	the effect--see above)

	if (m_pEffect)
		m_pEffect->SetLifetime(iMaxLifetime);

	//	We initialize this with the UNID, and later resolve the reference
	//	during OnDesignLoadComplete

	m_pAmmoType.LoadUNID(Ctx, pDesc->GetAttribute(AMMO_ID_ATTRIB));

	//	Maneuverability

	m_iManeuverability = pDesc->GetAttributeInteger(MANEUVERABILITY_ATTRIB);
	m_iManeuverRate = pDesc->GetAttributeIntegerBounded(MANEUVER_RATE_ATTRIB, 1, 180, -1);
	if (m_iManeuverRate == -1 && m_iManeuverability > 0)
		m_iManeuverRate = g_RotationAngle;
	else if (m_iManeuverability == 0 && m_iManeuverRate > 0)
		m_iManeuverability = 1;

	//	Load continuous and passthrough

	m_iContinuous = pDesc->GetAttributeInteger(BEAM_CONTINUOUS_ATTRIB);
	if (pDesc->FindAttributeInteger(PASSTHROUGH_ATTRIB, &m_iPassthrough))
		{
		//	In previous versions passthrough was a boolean value, so for backwards
		//	compatibility we treat 0 as 50%.
		//
		//	Note: We don't do this for ftArea because we need a way to specify
		//	passthrough=0 (since ftArea defaults to non-zero passthrough). Also,
		//	ftArea has no backwards compatibility issues (passthrough is only
		//	supported for 1.1 and above).

		if (m_iPassthrough == 0 && m_iFireType != ftArea)
			m_iPassthrough = 50;
		}
	else
		{
		//	If this is an area weapon, we set passthrough to a default value
		//	(for backwards compatibility)

		if (m_iFireType == ftArea)
			m_iPassthrough = 80;
		else
			m_iPassthrough = 0;
		}

	//	Load damage

	if (error = m_Damage.LoadFromXML(Ctx, pDesc->GetAttribute(DAMAGE_ATTRIB)))
		{
		Ctx.sError = strPatternSubst(CONSTLIT("Invalid damage specification: %s"), pDesc->GetAttribute(DAMAGE_ATTRIB));
		return error;
		}

	//	Fragments

	m_pFirstFragment = NULL;
	SFragmentDesc *pLastFragment = NULL;
	int iFragCount = 0;
	for (i = 0; i < pDesc->GetContentElementCount(); i++)
		{
		CXMLElement *pFragDesc = pDesc->GetContentElement(i);
		if (!strEquals(FRAGMENT_TAG, pFragDesc->GetTag()))
			continue;

		//	Create a new fragmentation descriptor

		SFragmentDesc *pNewDesc = new SFragmentDesc;
		pNewDesc->pNext = NULL;
		if (pLastFragment)
			pLastFragment->pNext = pNewDesc;
		else
			m_pFirstFragment = pNewDesc;

		pLastFragment = pNewDesc;

		//	Load fragment data

		pNewDesc->pDesc = new CWeaponFireDesc;
		CString sFragUNID = strPatternSubst("%s/f%d", sUNID, iFragCount++);
		if (error = pNewDesc->pDesc->InitFromXML(Ctx, pFragDesc, sFragUNID))
			return error;

		pNewDesc->pDesc->m_bFragment = true;

		//	Set the fragment count

		CString sCount = pFragDesc->GetAttribute(COUNT_ATTRIB);
		if (sCount.IsBlank())
			sCount = pDesc->GetAttribute(FRAGMENT_COUNT_ATTRIB);
		pNewDesc->Count.LoadFromXML(sCount);

		//	Set MIRV flag

		pNewDesc->bMIRV = (pFragDesc->GetAttributeBool(MULTI_TARGET_ATTRIB) 
				|| pDesc->GetAttributeBool(FRAGMENT_TARGET_ATTRIB));
		}

	//	If we have fragments, then set proximity appropriately
	//	NOTE: We set the fail safe value even if we don't set the proximity
	//	blast because we might set m_bProximityBlast later if there
	//	is an OnFragment event.

	m_bProximityBlast = (iFragCount != 0);
	m_iProximityFailsafe = pDesc->GetAttributeInteger(FAILSAFE_ATTRIB);

	//	Compute max effective range

	if (m_iFireType == ftArea)
		m_rMaxEffectiveRange = (m_ExpansionSpeed.GetAveValue() * LIGHT_SECOND / 100.0) * Ticks2Seconds(iMaxLifetime) * 0.75;
	else
		{
		Metric rEffectiveLifetime;
		if (m_iManeuverability > 0)
			rEffectiveLifetime = Ticks2Seconds(iMaxLifetime) * 0.75;
		else
			rEffectiveLifetime = Min(Ticks2Seconds(iMaxLifetime), 100.0);

		Metric rSpeed = (m_rMissileSpeed + m_rMaxMissileSpeed) / 2;
		m_rMaxEffectiveRange = rSpeed * rEffectiveLifetime;

		//	If we have fragments, add to the effective range

		if (m_pFirstFragment)
			m_rMaxEffectiveRange += m_pFirstFragment->pDesc->m_rMaxEffectiveRange;
		}

	//	Effects

	if (error = m_pHitEffect.LoadEffect(Ctx,
			strPatternSubst("%s:h", sUNID),
			pDesc->GetContentElementByTag(HIT_EFFECT_TAG),
			pDesc->GetAttribute(HIT_EFFECT_ATTRIB)))
		return error;

	if (error = m_pFireEffect.LoadEffect(Ctx,
			strPatternSubst("%s:f", sUNID),
			pDesc->GetContentElementByTag(FIRE_EFFECT_TAG),
			pDesc->GetAttribute(FIRE_EFFECT_ATTRIB)))
		return error;

	//	Vapor trail

	if (!pDesc->FindAttributeInteger(VAPOR_TRAIL_WIDTH_ATTRIB, &m_iVaporTrailWidth))
		m_iVaporTrailWidth = 100 * pDesc->GetAttributeInteger(VAPOR_TRAIL_ATTRIB);

	if (m_iVaporTrailWidth)
		{
		m_wVaporTrailColor = LoadRGBColor(pDesc->GetAttribute(VAPOR_TRAIL_COLOR_ATTRIB));
		m_iVaporTrailLength = pDesc->GetAttributeInteger(VAPOR_TRAIL_LENGTH_ATTRIB);
		if (m_iVaporTrailLength <= 0)
			m_iVaporTrailLength = 64;

		if (!pDesc->FindAttributeInteger(VAPOR_TRAIL_WIDTH_INC_ATTRIB, &m_iVaporTrailWidthInc))
			m_iVaporTrailWidthInc = 25;
		}
	else
		m_iVaporTrailLength = 0;

	//	Sound

	DWORD dwSoundID = LoadUNID(Ctx, pDesc->GetAttribute(SOUND_ATTRIB));
	if (dwSoundID)
		m_iFireSound = g_pUniverse->FindSound(dwSoundID);
	else
		m_iFireSound = -1;

	//	Events

	CXMLElement *pEventsDesc = pDesc->GetContentElementByTag(EVENTS_TAG);
	if (pEventsDesc)
		{
		if (error = m_Events.InitFromXML(Ctx, pEventsDesc))
			return error;
		}

	//	Check to see if this element has an enhanced sub-element. If so, then we
	//	recurse.

	CXMLElement *pEnhanced = pDesc->GetContentElementByTag(ENHANCED_TAG);
	if (pEnhanced)
		{
		m_pEnhanced = new CWeaponFireDesc(*this);
		if (error = m_pEnhanced->OverrideDesc(Ctx, pEnhanced))
			return error;
		}
	else
		m_pEnhanced = NULL;

	return NOERROR;
	}
示例#15
0
bool ParseElement (ParserCtx *pCtx, CXMLElement **retpElement)

//	ParseElement
//
//	Parses an element and returns it. We assume that we've already
//	parsed an open tag

	{
	CXMLElement *pElement;

	ASSERT(pCtx->iToken == tkTagOpen);

	//	Parse the tag name

	if (ParseToken(pCtx) != tkText)
		{
		pCtx->sError = ERR_ELEMENT_TAG_EXPECTED;
		return false;
		}

	//	Create a new element with the tag

	pElement = new CXMLElement(pCtx->sToken, pCtx->pElement);
	if (pElement == NULL)
		throw CException(errOutOfMemory);

	//	Keep parsing until the tag is done

	ParseToken(pCtx);
	while (pCtx->iToken != tkTagClose && pCtx->iToken != tkSimpleTagClose)
		{
		//	If we've got an identifier then this must be an attribute

		if (pCtx->iToken == tkText)
			{
			CString sAttribute = pCtx->sToken;
			CString sValue;

			//	Expect an equals sign

			if (ParseToken(pCtx) != tkEquals)
				{
				pCtx->sError = ERR_EQUAL_EXPECTED;
				delete pElement;
				return false;
				}

			//	Expect a quote

			ParseToken(pCtx);
			if (pCtx->iToken != tkQuote && pCtx->iToken != tkSingleQuote)
				{
				pCtx->sError = ERR_ATTRIB_NEEDS_QUOTES;
				delete pElement;
				return false;
				}

			//	Remember what kind of qoute we used so that we can match it
			//	(and so we ignore the other kind inside it).

			pCtx->iAttribQuote = pCtx->iToken;

			//	Expect the value 

			ParseToken(pCtx, AttributeState);
			if (pCtx->iToken == tkText)
				{
				sValue = pCtx->sToken;
				ParseToken(pCtx);
				}
			else
				sValue = NULL_STR;

			//	Now expect an end-quote

			if (pCtx->iToken != pCtx->iAttribQuote)
				{
				if (pCtx->iToken != tkError || pCtx->sError.IsEmpty())
					pCtx->sError = ERR_MISMATCHED_ATTRIB_QUOTE;
				delete pElement;
				return false;
				}

			//	Add the attribute to the element

			pElement->AddAttribute(sAttribute, sValue);

			//	Parse the next token

			ParseToken(pCtx);
			}

		//	Otherwise this is an error

		else
			{
			if (pCtx->iToken != tkError || pCtx->sError.IsEmpty())
				pCtx->sError = ERR_ATTRIB_EXPECTED;
			delete pElement;
			return false;
			}
		}

	//	Give our controller a chance to deal with an element
	//	(We use this in Transcendence to parse the <Library> element, which
	//	contains external entities).
	//
	//	NOTE: We only worry about top-level elements (i.e., elements immediately
	//	under the root).

	if (pCtx->m_pController && pCtx->pElement && pCtx->pElement->GetParentElement() == NULL)
		{
		if (!pCtx->m_pController->OnOpenTag(pElement, &pCtx->sError))
			{
			delete pElement;
			return false;
			}
		}

	//	If we don't have an empty element then keep parsing until
	//	we find a close tag

	if (!pCtx->m_bParseRootElement && pCtx->iToken == tkTagClose)
		{
		CXMLElement *pParentElement;

		//	We are recursing

		pParentElement = pCtx->pElement;
		pCtx->pElement = pElement;

		//	Parse until we've got the begin close tag

		while (ParseToken(pCtx, ContentState) != tkEndTagOpen)
			{
			//	If this is text then append it as content

			if (pCtx->iToken == tkText)
				pElement->AppendContent(pCtx->sToken);

			//	Otherwise, append an element

			else if (pCtx->iToken == tkTagOpen)
				{
				CXMLElement *pSubElement;

				if (!ParseElement(pCtx, &pSubElement))
					{
					pCtx->pElement = pParentElement;
					delete pElement;
					return false;
					}

				pElement->AppendSubElement(pSubElement);
				}

			//	Otherwise we're in trouble

			else
				{
				pCtx->pElement = pParentElement;
				if (pCtx->iToken != tkError || pCtx->sError.IsEmpty())
					pCtx->sError = ERR_CONTENT_EXPECTED;
				delete pElement;
				return false;
				}
			}

		//	Done

		pCtx->pElement = pParentElement;

		//	The element tag should match ours

		if (ParseToken(pCtx) != tkText
				|| strEqualsNoCase(pCtx->sToken, pElement->GetTag()))
			{
			pCtx->sError = ERR_UNMATCHED_CLOSE_TAG;
			delete pElement;
			return false;
			}

		//	Parse the end tag

		if (ParseToken(pCtx) != tkTagClose)
			{
			pCtx->sError = ERR_CLOSE_TAG_EXPECTED;
			delete pElement;
			return false;
			}
		}

	//	Done

	*retpElement = pElement;

	return true;
	}
ALERROR CPlayerSettings::InitFromXML (SDesignLoadCtx &Ctx, CShipClass *pClass, CXMLElement *pDesc)

//	InitFromXML
//
//	Initialize from an XML element

	{
	ALERROR error;
	int i;

	m_sDesc = pDesc->GetAttribute(DESC_ATTRIB);
	if (error = LoadUNID(Ctx, pDesc->GetAttribute(LARGE_IMAGE_ATTRIB), &m_dwLargeImage))
		return error;

	m_fDebug = pDesc->GetAttributeBool(DEBUG_ONLY_ATTRIB);
	CString sInitialClass = pDesc->GetAttribute(INITIAL_CLASS_ATTRIB);
	if (strEquals(sInitialClass, CONSTLIT("always")))
		{
		m_fInitialClass = true;
		m_fIncludeInAllAdventures = true;
		}
	else
		{
		m_fInitialClass = CXMLElement::IsBoolTrueValue(sInitialClass);
		m_fIncludeInAllAdventures = false;
		}

	m_fHasArmorDesc = false;
	m_fHasReactorDesc = false;
	m_fHasShieldDesc = false;

	//	Some ship capabilities

	bool bValue;
	if (pDesc->FindAttributeBool(AUTOPILOT_ATTRIB, &bValue))
		m_fAutopilot = bValue;
	else
		m_fAutopilot = true;

	//	Load some miscellaneous data

	CString sAttrib;
	if (!pDesc->FindAttribute(STARTING_CREDITS_ATTRIB, &sAttrib))
		sAttrib = CONSTLIT("5d20+200");

	if (error = m_StartingCredits.InitFromXML(Ctx, sAttrib))
		return error;

	m_sStartNode = pDesc->GetAttribute(STARTING_SYSTEM_ATTRIB);
	m_sStartPos = pDesc->GetAttribute(STARTING_POS_ATTRIB);
	if (m_sStartPos.IsBlank())
		m_sStartPos = CONSTLIT("Start");

	//	Load the ship screen

	CString sShipScreenUNID = pDesc->GetAttribute(SHIP_SCREEN_ATTRIB);
	if (sShipScreenUNID.IsBlank())
		sShipScreenUNID = strFromInt(DEFAULT_SHIP_SCREEN_UNID, false);
	m_pShipScreen.LoadUNID(Ctx, sShipScreenUNID);

	//	Load the armor display data

	CXMLElement *pArmorDisplay = pDesc->GetContentElementByTag(ARMOR_DISPLAY_TAG);
	if (pArmorDisplay && pArmorDisplay->GetContentElementCount() > 0)
		{
		//	Loop over all sub elements

		for (i = 0; i < pArmorDisplay->GetContentElementCount(); i++)
			{
			CXMLElement *pSub = pArmorDisplay->GetContentElement(i);

			if (strEquals(pSub->GetTag(), ARMOR_SECTION_TAG))
				{
				SArmorSegmentImageDesc &ArmorDesc = *m_ArmorDesc.Segments.Insert();

				if (error = ArmorDesc.Image.InitFromXML(Ctx, pSub))
					return ComposeLoadError(Ctx, ERR_ARMOR_DISPLAY_NEEDED);

				ArmorDesc.sName = pSub->GetAttribute(NAME_ATTRIB);
				ArmorDesc.xDest = pSub->GetAttributeInteger(DEST_X_ATTRIB);
				ArmorDesc.yDest = pSub->GetAttributeInteger(DEST_Y_ATTRIB);
				ArmorDesc.xHP = pSub->GetAttributeInteger(HP_X_ATTRIB);
				ArmorDesc.yHP = pSub->GetAttributeInteger(HP_Y_ATTRIB);
				ArmorDesc.yName = pSub->GetAttributeInteger(NAME_Y_ATTRIB);
				ArmorDesc.cxNameBreak = pSub->GetAttributeInteger(NAME_BREAK_WIDTH);
				ArmorDesc.xNameDestOffset = pSub->GetAttributeInteger(NAME_DEST_X_ATTRIB);
				ArmorDesc.yNameDestOffset = pSub->GetAttributeInteger(NAME_DEST_Y_ATTRIB);
				}
			else if (strEquals(pSub->GetTag(), SHIP_IMAGE_TAG))
				{
				if (error = m_ArmorDesc.ShipImage.InitFromXML(Ctx, pSub))
					return ComposeLoadError(Ctx, ERR_SHIP_IMAGE_NEEDED);
				}
			else
				return ComposeLoadError(Ctx, strPatternSubst(CONSTLIT("Unknown ArmorDisplay element: "), pSub->GetTag()));
			}

		m_fHasArmorDesc = true;
		}
	else
		m_fHasArmorDesc = false;

	//	Load shield display data

	CXMLElement *pShieldDisplay = pDesc->GetContentElementByTag(SHIELD_DISPLAY_TAG);
	if (pShieldDisplay)
		{
		//	Load the new shield effect

		if (error = m_ShieldDesc.pShieldEffect.LoadEffect(Ctx,
				strPatternSubst(CONSTLIT("%d:p:s"), pClass->GetUNID()),
				pShieldDisplay->GetContentElementByTag(SHIELD_EFFECT_TAG),
				pShieldDisplay->GetAttribute(SHIELD_EFFECT_ATTRIB)))
			return error;

		//	If we don't have the new effect, load the backwards compatibility
		//	image.

		if (m_ShieldDesc.pShieldEffect.IsEmpty())
			{
			if (error = m_ShieldDesc.Image.InitFromXML(Ctx, 
					pShieldDisplay->GetContentElementByTag(IMAGE_TAG)))
				return ComposeLoadError(Ctx, ERR_SHIELD_DISPLAY_NEEDED);
			}

		m_fHasShieldDesc = true;
		}

	//	If we have a shield effect then we must have an armor image

	if (!m_ShieldDesc.pShieldEffect.IsEmpty() && m_ArmorDesc.ShipImage.GetBitmapUNID() == 0)
		return ComposeLoadError(Ctx, ERR_MUST_HAVE_SHIP_IMAGE);

	//	Load reactor display data

	CXMLElement *pReactorDisplay = pDesc->GetContentElementByTag(REACTOR_DISPLAY_TAG);
	if (pReactorDisplay)
		{
		if (error = m_ReactorDesc.ReactorImage.InitFromXML(Ctx,
				pReactorDisplay->GetContentElementByTag(IMAGE_TAG)))
			return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED);

		CXMLElement *pImage = pReactorDisplay->GetContentElementByTag(POWER_LEVEL_IMAGE_TAG);
		if (pImage == NULL || (error = m_ReactorDesc.PowerLevelImage.InitFromXML(Ctx, pImage)))
			return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED);

		m_ReactorDesc.xPowerLevelImage = pImage->GetAttributeInteger(DEST_X_ATTRIB);
		m_ReactorDesc.yPowerLevelImage = pImage->GetAttributeInteger(DEST_Y_ATTRIB);

		pImage = pReactorDisplay->GetContentElementByTag(FUEL_LEVEL_IMAGE_TAG);
		if (pImage == NULL || (error = m_ReactorDesc.FuelLevelImage.InitFromXML(Ctx, pImage)))
			return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED);

		m_ReactorDesc.xFuelLevelImage = pImage->GetAttributeInteger(DEST_X_ATTRIB);
		m_ReactorDesc.yFuelLevelImage = pImage->GetAttributeInteger(DEST_Y_ATTRIB);

		pImage = pReactorDisplay->GetContentElementByTag(FUEL_LOW_LEVEL_IMAGE_TAG);
		if (pImage == NULL || (error = m_ReactorDesc.FuelLowLevelImage.InitFromXML(Ctx, pImage)))
			return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED);

		if (error = InitRectFromElement(pReactorDisplay->GetContentElementByTag(REACTOR_TEXT_TAG),
				&m_ReactorDesc.rcReactorText))
			return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED);

		if (error = InitRectFromElement(pReactorDisplay->GetContentElementByTag(POWER_LEVEL_TEXT_TAG),
				&m_ReactorDesc.rcPowerLevelText))
			return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED);

		if (error = InitRectFromElement(pReactorDisplay->GetContentElementByTag(FUEL_LEVEL_TEXT_TAG),
				&m_ReactorDesc.rcFuelLevelText))
			return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED);

		m_fHasReactorDesc = true;
		}

	//	Done

	return NOERROR;
	}
示例#17
0
ALERROR CSystemMap::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	OnCreateFromXML

	{
	ALERROR error;
	int i;

	//	Load some basic info

	m_sName = pDesc->GetAttribute(NAME_ATTRIB);
	m_dwBackgroundImage = pDesc->GetAttributeInteger(BACKGROUND_IMAGE_ATTRIB);
	if (error = m_pPrimaryMap.LoadUNID(Ctx, pDesc->GetAttribute(PRIMARY_MAP_ATTRIB)))
		return error;

	m_bStartingMap = pDesc->GetAttributeBool(STARTING_MAP_ATTRIB);

	//	If we have a primary map, then add it to the Uses list.

	if (m_pPrimaryMap.GetUNID() != 0)
		m_Uses.Insert(m_pPrimaryMap);

	//	Scale information

	m_iInitialScale = pDesc->GetAttributeIntegerBounded(INITIAL_SCALE_ATTRIB, 10, 1000, 100);
	m_iMaxScale = pDesc->GetAttributeIntegerBounded(MAX_SCALE_ATTRIB, 100, 1000, 200);
	m_iMinScale = pDesc->GetAttributeIntegerBounded(MIN_SCALE_ATTRIB, 10, 100, 50);

	//	Generate an UNID

	CString sUNID = strPatternSubst(CONSTLIT("%d"), GetUNID());

	//	Keep track of root nodes

	TArray<CString> RootNodes;

	//	Iterate over all child elements and process them

	for (i = 0; i < pDesc->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pDesc->GetContentElement(i);

		if (strEquals(pItem->GetTag(), TOPOLOGY_CREATOR_TAG)
				|| strEquals(pItem->GetTag(), ROOT_NODE_TAG))
			{
			m_Creators.Insert(pItem->OrphanCopy());

			if (strEquals(pItem->GetTag(), ROOT_NODE_TAG))
				RootNodes.Insert(pItem->GetAttribute(ID_ATTRIB));
			}
		else if (strEquals(pItem->GetTag(), TOPOLOGY_PROCESSOR_TAG))
			{
			ITopologyProcessor *pNewProc;
			CString sProcessorUNID = strPatternSubst(CONSTLIT("%d:p%d"), GetUNID(), m_Processors.GetCount());

			if (error = ITopologyProcessor::CreateFromXMLAsGroup(Ctx, pItem, sProcessorUNID, &pNewProc))
				return error;

			m_Processors.Insert(pNewProc);
			}
		else if (strEquals(pItem->GetTag(), SYSTEM_TOPOLOGY_TAG))
			{
			if (error = m_FixedTopology.LoadFromXML(Ctx, pItem, this, sUNID, true))
				return error;
			}
		else if (strEquals(pItem->GetTag(), USES_TAG))
			{
			CSystemMapRef *pRef = m_Uses.Insert();

			if (error = pRef->LoadUNID(Ctx, pItem->GetAttribute(UNID_ATTRIB)))
				return error;
			}
		else
			{
			//	If it's none of the above, see if it is a node descriptor

			if (error = m_FixedTopology.LoadNodeFromXML(Ctx, pItem, this, sUNID))
				return error;
			}
		}

	//	Mark all the root nodes.
	//
	//	We need to do this for backwards compatibility because the old technique
	//	of having a root node with [Prev] for a stargate requires this. This was
	//	used by Huaramarca.

	for (i = 0; i < RootNodes.GetCount(); i++)
		if (error = m_FixedTopology.AddRootNode(Ctx, RootNodes[i]))
			return error;

	//	Init

	m_bAdded = false;

	//	Debug info

	m_bDebugShowAttributes = pDesc->GetAttributeBool(DEBUG_SHOW_ATTRIBUTES_ATTRIB);

	return NOERROR;
	}
示例#18
0
ALERROR CConquerNodesProc::OnInitFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc, const CString &sUNID)

//	OnInitFromXML
//
//	Initialize from XML element

	{
	ALERROR error;
	int i;

	//	Initialize criteria

	CTopologyNode::ParseCriteria(NULL, &m_Criteria);

	//	Loop over all elements

	for (i = 0; i < pDesc->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pDesc->GetContentElement(i);

		//	If we have a criteria, parse it and remember it
		//	(Note: If multiple criteria are found, we take the latest one).

		if (strEquals(pItem->GetTag(), CRITERIA_TAG))
			{
			//	Parse the filter

			if (error = CTopologyNode::ParseCriteria(pItem, &m_Criteria, &Ctx.sError))
				return error;
			}

		//	Otherwise, treat it as a conqueror definition and insert it in the list

		else
			{
			CString sNewUNID = strPatternSubst(CONSTLIT("%s/%d"), sUNID, m_Conquerors.GetCount());
			SConqueror *pConqueror = m_Conquerors.Insert();

			//	Get some properties

			pConqueror->iSeedChance = pItem->GetAttributeIntegerBounded(SEED_CHANCE_ATTRIB, 1, 100, 1);
			pConqueror->iMaxSeeds = pItem->GetAttributeIntegerBounded(MAX_SEEDS_ATTRIB, 1, -1, 1);
			pConqueror->iExpandChance = pItem->GetAttributeIntegerBounded(EXPAND_CHANCE_ATTRIB, 1, 100, 1);
			pConqueror->iMaxNodes = pItem->GetAttributeIntegerBounded(MAX_NODES_ATTRIB, 1, -1, 1);

			//	Get the seed and expand probabilities

			if (error = LoadNodeWeightTable(Ctx, pItem->GetContentElementByTag(SEED_CHANCE_TAG), &pConqueror->Seed))
				return error;

			if (error = LoadNodeWeightTable(Ctx, pItem->GetContentElementByTag(EXPAND_CHANCE_TAG), &pConqueror->Expand))
				return error;

			//	Get the processor itself

			CXMLElement *pProcXML = pItem->GetContentElementByTag(PROCESSOR_TAG);
			if (pProcXML)
				{

				if (error = ITopologyProcessor::CreateFromXMLAsGroup(Ctx, pProcXML, sNewUNID, &pConqueror->pProc))
					return error;
				}
			else
				{
				Ctx.sError = CONSTLIT("<Processor> element not found in <ConquerNodes>");
				return ERR_FAIL;
				}
			}
		}

	return NOERROR;
	}
示例#19
0
ALERROR WriteModule (CTDBCompiler &Ctx, 
					 const CString &sFilename, 
					 const CString &sFolder, 
					 CDataFile &Out, 
					 int *retiModuleEntry,
					 bool bCore)
	{
	ALERROR error;
	int i;

	//	Parse the file

	CXMLElement *pModule;
	CExternalEntityTable *pEntityTable = new CExternalEntityTable;
	CFileReadBlock DataFile(pathAddComponent(Ctx.GetRootPath(), sFilename));
	CString sError;

	printf("Parsing %s...", sFilename.GetASCIIZPointer());
	if (error = CXMLElement::ParseXML(&DataFile, Ctx.GetCoreEntities(), &pModule, &sError, pEntityTable))
		{
		printf("\n");
		Ctx.ReportError(sError);
		return error;
		}

	//	If this is a core module (embedded in the root XML) then we add these
	//	entities to the core. [Ctx takes ownership.]

	if (bCore)
		Ctx.AddEntityTable(pEntityTable);

	//	Chain entity tables (so that any modules that we load get the benefit).
	//	This will chain Ctx.pCoreEntities (and restore it in the destructor).
	//
	//	NOTE: If this is a core module, then we don't do this, since we've
	//	already added the entities to the context block.

	CSaveEntitiesTable SavedEntities(Ctx, (!bCore ? pEntityTable : NULL));

	printf("done.\n");

	//	Compress if this is NOT the main file. We can't compress the
	//	main file because we sometimes need to read it partially.

	bool bCompress = (retiModuleEntry == NULL);

	//	Write the module itself

	int iEntry;
	if (error = WriteGameFile(Ctx, sFilename, bCompress, Out, &iEntry))
		return error;

	//	If the caller doesn't want the module entry, then it means that this is
	//	a module (instead of the main file). If so, add it to the resources table

	if (retiModuleEntry == NULL)
		Ctx.AddResource(sFilename, iEntry, bCompress);

	//	Store all the image resources

	if (error = WriteModuleImages(Ctx, pModule, sFolder, Out))
		return error;

	//	Store all the sound resources

	if (error = WriteModuleSounds(Ctx, pModule, sFolder, Out))
		return error;

	//	Store all modules

	if (error = WriteSubModules(Ctx, pModule, sFolder, Out))
		return error;

	//	The root module may have a TranscendenceAdventure tag with modules in it

	for (i = 0; i < pModule->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pModule->GetContentElement(i);

		if (strEquals(pItem->GetTag(), TAG_CORE_LIBRARY)
				|| strEquals(pItem->GetTag(), TAG_TRANSCENDENCE_ADVENTURE) 
				|| strEquals(pItem->GetTag(), TAG_TRANSCENDENCE_LIBRARY))
			{
			//	If we have a filename, then we need to save the target as a
			//	module.

			CString sFilename;
			if (pItem->FindAttribute(ATTRIB_FILENAME, &sFilename))
				{
				//	Write out the module, making sure to set the core flag.

				if (error = WriteModule(Ctx, sFilename, sFolder, Out, NULL, true))
					return error;

				//	We ignore any other elements.

				continue;
				}

			//	Store all the image resources

			if (error = WriteModuleImages(Ctx, pItem, sFolder, Out))
				return error;

			//	Store all the sound resources

			if (error = WriteModuleSounds(Ctx, pItem, sFolder, Out))
				return error;

			//	Modules

			if (error = WriteSubModules(Ctx, pItem, sFolder, Out))
				return error;
			}
		}

	//	Done

	if (retiModuleEntry)
		*retiModuleEntry = iEntry;

	return NOERROR;
	}
示例#20
0
ALERROR CDockPane::CreateControls (CString *retsError)

//	CreateControls
//
//	Creates controls based on the pane descriptor. We assume that m_pContainer has
//	already been created and is empty.

	{
	int i;

	//	If there is a <Controls> element then use that to figure out what to
	//	create.

	CXMLElement *pControls = m_pPaneDesc->GetContentElementByTag(CONTROLS_TAG);
	if (pControls)
		{
		for (i = 0; i < pControls->GetContentElementCount(); i++)
			{
			CXMLElement *pControlDef = pControls->GetContentElement(i);

			//	Figure out the type

			EControlTypes iType;
			if (strEquals(pControlDef->GetTag(), COUNTER_TAG))
				iType = controlCounter;
			else if (strEquals(pControlDef->GetTag(), ITEM_DISPLAY_TAG))
				iType = controlItemDisplay;
			else if (strEquals(pControlDef->GetTag(), TEXT_TAG))
				iType = controlDesc;
			else if (strEquals(pControlDef->GetTag(), TEXT_INPUT_TAG))
				iType = controlTextInput;
			else
				{
				*retsError = strPatternSubst(CONSTLIT("Unknown control element: <%s>."), pControlDef->GetTag());
				return ERR_FAIL;
				}

			//	Get the ID

			CString sID;
			if (!pControlDef->FindAttribute(ID_ATTRIB, &sID))
				{
				*retsError = strPatternSubst(CONSTLIT("Missing ID attrib for control element: <%s>."), pControlDef->GetTag());
				return ERR_FAIL;
				}

			//	Create the control

			CreateControl(iType, sID);
			}
		}

	//	Otherwise we create default controls

	else
		{
		//	Create the text description control

		CreateControl(controlDesc, DEFAULT_DESC_ID);

		//	Create counter or input fields

		if (m_pPaneDesc->GetAttributeBool(SHOW_COUNTER_ATTRIB))
			CreateControl(controlCounter, DEFAULT_COUNTER_ID);
		else if (m_pPaneDesc->GetAttributeBool(SHOW_TEXT_INPUT_ATTRIB))
			CreateControl(controlTextInput, DEFAULT_TEXT_INPUT_ID);
		}

	return NOERROR;
	}
示例#21
0
ALERROR CTopologyNode::ParseCriteria (CXMLElement *pCrit, SCriteria *retCrit, CString *retsError)

//	ParseCriteria
//
//	Parses an XML element into a criteria desc

	{
	int i;

	retCrit->iChance = 100;
	retCrit->iMaxInterNodeDist = -1;
	retCrit->iMinInterNodeDist = 0;
	retCrit->iMaxStargates = -1;
	retCrit->iMinStargates = 0;

	if (pCrit)
		{
		for (i = 0; i < pCrit->GetContentElementCount(); i++)
			{
			CXMLElement *pItem = pCrit->GetContentElement(i);

			if (strEquals(pItem->GetTag(), ATTRIBUTES_TAG))
				{
				CString sCriteria = pItem->GetAttribute(CRITERIA_ATTRIB);
				ParseCriteriaInt(sCriteria, retCrit);
				}
			else if (strEquals(pItem->GetTag(), CHANCE_TAG))
				{
				retCrit->iChance = pItem->GetAttributeIntegerBounded(CHANCE_ATTRIB, 0, 100, 100);
				}
			else if (strEquals(pItem->GetTag(), DISTANCE_BETWEEN_NODES_TAG))
				{
				retCrit->iMinInterNodeDist = pItem->GetAttributeIntegerBounded(MIN_ATTRIB, 0, -1, 0);
				retCrit->iMaxInterNodeDist = pItem->GetAttributeIntegerBounded(MAX_ATTRIB, 0, -1, -1);
				}
			else if (strEquals(pItem->GetTag(), DISTANCE_TO_TAG))
				{
				SDistanceTo *pDistTo = retCrit->DistanceTo.Insert();
				pDistTo->iMinDist = pItem->GetAttributeIntegerBounded(MIN_ATTRIB, 0, -1, 0);
				pDistTo->iMaxDist = pItem->GetAttributeIntegerBounded(MAX_ATTRIB, 0, -1, -1);

				CString sCriteria;
				if (pItem->FindAttribute(CRITERIA_ATTRIB, &sCriteria))
					{
					SCriteria Criteria;
					if (ParseCriteriaInt(sCriteria, &Criteria) != NOERROR)
						{
						*retsError = strPatternSubst(CONSTLIT("Unable to parse criteria: %s"), sCriteria);
						return ERR_FAIL;
						}

					pDistTo->AttribsRequired = Criteria.AttribsRequired;
					pDistTo->AttribsNotAllowed = Criteria.AttribsNotAllowed;
					}
				else
					pDistTo->sNodeID = pItem->GetAttribute(NODE_ID_ATTRIB);
				}
			else if (strEquals(pItem->GetTag(), STARGATE_COUNT_TAG))
				{
				retCrit->iMinStargates = pItem->GetAttributeIntegerBounded(MIN_ATTRIB, 0, -1, 0);
				retCrit->iMaxStargates = pItem->GetAttributeIntegerBounded(MAX_ATTRIB, 0, -1, -1);
				}
			else
				{
				*retsError = strPatternSubst(CONSTLIT("Unknown criteria element: %s"), pItem->GetTag());
				return ERR_FAIL;
				}
			}
		}

	return NOERROR;
	}
示例#22
0
ALERROR CGameSettings::Load (const CString &sFilespec, CString *retsError)

//	Load
//
//	Load game settings from a file. If the file does not exist, then we 
//	set settings to default values

	{
	ALERROR error;
	int i;

	//	Initialize from defaults

	for (i = 0; i < OPTIONS_COUNT; i++)
		SetValue(i, CString(g_OptionData[i].pszDefaultValue, -1, true), true);

	//	Load XML

	CFileReadBlock DataFile(sFilespec);
	CXMLElement *pData;
	CString sError;
	if (error = CXMLElement::ParseXML(&DataFile, &pData, retsError))
		{
		//	ERR_NOTFOUND means that we couldn't find the Settings.xml
		//	file. In that case, initialize from defaults

		if (error == ERR_NOTFOUND)
			{
			LoadFromRegistry();
			m_bModified = true;
			return NOERROR;
			}

		//	Otherwise, it means that we got an error parsing the file.
		//	Return the error, but leave the settings initialized to defaults
		//	(We should be OK to continue, even with an error).

		else
			{
			m_bModified = false;
			return error;
			}
		}

	//	Initialize to unmodified (as we load settings we might change this)

	m_bModified = false;

	//	Loop over all elements

	for (i = 0; i < pData->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pData->GetContentElement(i);

		if (strEquals(pItem->GetTag(), OPTION_TAG))
			{
			int iOption = FindOptionData(pItem->GetAttribute(NAME_ATTRIB));
			if (iOption == -1)
				{
				kernelDebugLogMessage("Unknown option: %s", pItem->GetAttribute(NAME_ATTRIB).GetASCIIZPointer());
				continue;
				}

			SetValue(iOption, pItem->GetAttribute(VALUE_ATTRIB), true);
			}
		else if (strEquals(pItem->GetTag(), KEY_MAP_TAG))
			{
			if (error = m_KeyMap.ReadFromXML(pItem))
				return error;
			}
		else if (m_pExtra)
			{
			bool bModified;
			if (error = m_pExtra->OnLoadSettings(pItem, &bModified))
				return error;

			if (bModified)
				m_bModified = true;
			}
		}

	//	Done

	delete pData;

	return NOERROR;
	}
ALERROR CAdventureDesc::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	OnCreateFromXML
//
//	Load from XML

{
    ALERROR error;
    int i;

    //	If we are part of the default resource, then get the adventure UNID

    if (Ctx.pExtension == NULL)
    {
        m_dwExtensionUNID = pDesc->GetAttributeInteger(ADVENTURE_UNID_ATTRIB);
        m_fInDefaultResource = true;
    }

    //	Otherwise, we remember the extension that we were loaded from

    else
    {
        m_dwExtensionUNID = Ctx.pExtension->GetUNID();
        m_fInDefaultResource = false;
    }

    //	Load the name, etc

    m_sName = pDesc->GetAttribute(NAME_ATTRIB);
    if (error = ::LoadUNID(Ctx, pDesc->GetAttribute(BACKGROUND_ID_ATTRIB), &m_dwBackgroundUNID))
        return error;

    //	Starting ship criteria

    CString sCriteria;
    if (!pDesc->FindAttribute(STARTING_SHIP_CRITERIA_ATTRIB, &sCriteria))
        sCriteria = CONSTLIT("*");

    if (error = CDesignTypeCriteria::ParseCriteria(sCriteria, &m_StartingShips))
        return ComposeLoadError(Ctx, ERR_STARTING_SHIP_CRITERIA);

    m_fIncludeOldShipClasses = pDesc->GetAttributeBool(INCLUDE_10_STARTING_CLASSES_ATTRIB);

    //	Starting position

    m_sStartingNodeID = pDesc->GetAttribute(STARTING_SYSTEM_ATTRIB);
    m_sStartingPos = pDesc->GetAttribute(STARTING_POS_ATTRIB);

    //	Welcome message

    if (!pDesc->FindAttribute(WELCOME_MESSAGE_ATTRIB, &m_sWelcomeMessage))
        m_sWelcomeMessage = CONSTLIT("Welcome to Transcendence!");

    //	Init some flags

    m_fIsCurrentAdventure = false;

    //	If we don't have a name, then get it from the extension

    if (m_sName.IsBlank())
    {
        if (Ctx.pExtension)
            m_sName = Ctx.pExtension->GetName();
    }

    //	Otherwise, if the extension doesn't have a name, then we can set it

    else if (Ctx.pExtension && strFind(Ctx.pExtension->GetName(), CONSTLIT("Extension")) == 0)
        Ctx.pExtension->SetName(m_sName);

    //	Initialize armor and shield damage adjustment tables

    InitDefaultDamageAdj();
    for (i = 1; i <= MAX_ITEM_LEVEL; i++)
    {
        m_ArmorDamageAdj[i - 1] = g_ArmorDamageAdj[i - 1];
        m_ShieldDamageAdj[i - 1] = g_ShieldDamageAdj[i - 1];
    }

    //	Load constants

    CXMLElement *pConstants = pDesc->GetContentElementByTag(CONSTANTS_TAG);
    if (pConstants)
    {
        for (i = 0; i < pConstants->GetContentElementCount(); i++)
        {
            CXMLElement *pItem = pConstants->GetContentElement(i);

            if (strEquals(pItem->GetTag(), ARMOR_DAMAGE_ADJ_TAG))
            {
                int iLevel = pItem->GetAttributeInteger(LEVEL_ATTRIB);
                if (iLevel < 1 || iLevel > MAX_ITEM_LEVEL)
                {
                    Ctx.sError = strPatternSubst(CONSTLIT("Invalid level: %d."), iLevel);
                    return ERR_FAIL;
                }

                if (error = m_ArmorDamageAdj[iLevel - 1].InitFromXML(Ctx, pItem, true))
                    return error;
            }
            else if (strEquals(pItem->GetTag(), SHIELD_DAMAGE_ADJ_TAG))
            {
                int iLevel = pItem->GetAttributeInteger(LEVEL_ATTRIB);
                if (iLevel < 1 || iLevel > MAX_ITEM_LEVEL)
                {
                    Ctx.sError = strPatternSubst(CONSTLIT("Invalid level: %d."), iLevel);
                    return ERR_FAIL;
                }

                if (error = m_ShieldDamageAdj[iLevel - 1].InitFromXML(Ctx, pItem, true))
                    return error;
            }
            else
            {
                Ctx.sError = strPatternSubst(CONSTLIT("Invalid constant definition element: %s."), pItem->GetTag());
                return ERR_FAIL;
            }
        }
    }

    return NOERROR;
}
示例#24
0
ALERROR CUniverse::InitFromXML (SDesignLoadCtx &Ctx,
								CXMLElement *pElement, 
								CResourceDb &Resources)

//	InitFromXML
//
//	Initializes the universe from an XML database

	{
	ALERROR error;
	int i;
	CIDTable UNIDMap(FALSE, FALSE);

	m_bNoImages = Ctx.bNoResources;

	//	Initialize code chain

	if (error = m_CC.Boot())
		return error;

	if (error = InitCodeChainPrimitives())
		return error;

	//	Create some fonts

	m_MapLabelFont.Create(MAP_LABEL_TYPEFACE, 12);
	m_SignFont.Create(SIGN_TYPEFACE, 11, true);

	//	Make sure we have the right version

	if (!Ctx.bNoVersionCheck)
		{
		DWORD dwVersion;

		//	Make sure we have the latest version of the .XML

		dwVersion = (DWORD)pElement->GetAttributeInteger(VERSION_ATTRIB);
		if (fileGetProductVersion() > dwVersion)
			{
			if (Resources.IsUsingExternalGameFile())
				Ctx.sError = CONSTLIT("External definitions file (Transcendence.xml) is obsolete.\nPlease remove 'Transcendence.xml' file from game folder.");
			else
				Ctx.sError = CONSTLIT("Source definitions file (Transcendence.xml) is obsolete.\nPlease download the latest version at http://www.neurohack.com/transcendence/Downloads.html.");
			return ERR_FAIL;
			}

		//	Make sure we have the latest version of the .EXE

		dwVersion = (DWORD)pElement->GetAttributeInteger(MIN_VERSION_ATTRIB);
		if (fileGetProductVersion() < dwVersion)
			{
			Ctx.sError = CONSTLIT("Source definitions file (Transcendence.xml) requires a newer version of Transcendence.exe.\nPlease download the latest version at http://www.neurohack.com/transcendence/Downloads.html.");
			return ERR_FAIL;
			}
		}

	//	Load the Main XML file

	for (i = 0; i < pElement->GetContentElementCount(); i++)
		{
		CXMLElement *pDesc = pElement->GetContentElement(i);

		if (strEquals(pDesc->GetTag(), IMAGES_TAG))
			error = InitImages(Ctx, pDesc, Resources);
		else if (strEquals(pDesc->GetTag(), SOUNDS_TAG))
			error = InitSounds(Ctx, pDesc, Resources);
		else if (strEquals(pDesc->GetTag(), STATION_TYPE_RESOURCES_TAG))
			error = InitStationTypeResources(Ctx, pDesc);
		else if (strEquals(pDesc->GetTag(), STAR_SYSTEM_TYPES_TAG))
			error = InitStarSystemTypes(Ctx, pDesc);
		else if (strEquals(pDesc->GetTag(), MODULES_TAG))
			error = LoadModules(Ctx, pDesc);
		else
			error = LoadDesignElement(Ctx, pDesc);

		//	Check for error

		if (error)
			return error;
		}

	return NOERROR;
	}
示例#25
0
void InitStationTypeImage (SEntryDesc &Entry, CStationType *pStationType)
	{
	struct SSatImageDesc
		{
		const CObjectImageArray *pImage;
		CCompositeImageSelector Selector;
		int xOffset;
		int yOffset;
		};

	int i;

	SSelectorInitCtx InitCtx;
	pStationType->SetImageSelector(InitCtx, &Entry.Selector);
	const CObjectImageArray *pMainImage = &pStationType->GetImage(Entry.Selector, CCompositeImageModifiers());

	//	If we have no satellites, then we can just return the single station 
	//	image.

	CXMLElement *pSatellites = pStationType->GetSatellitesDesc();
	if (pSatellites == NULL)
		{
		Entry.pImage = pMainImage;
		return;
		}

	//	Figure out the extents of the image

	RECT rcMainImage = pMainImage->GetImageRect();
	RECT rcBounds;
	rcBounds.left = -(RectWidth(rcMainImage) / 2);
	rcBounds.top = -(RectHeight(rcMainImage) / 2);
	rcBounds.right = rcBounds.left + RectWidth(rcMainImage);
	rcBounds.bottom = rcBounds.top + RectHeight(rcMainImage);

	//	Loop over all satellites and get metrics

	TArray<SSatImageDesc> SatImages;
	for (i = 0; i < pSatellites->GetContentElementCount(); i++)
		{
		CXMLElement *pSatDesc = pSatellites->GetContentElement(i);
		if (!pSatDesc->FindAttribute(SEGMENT_ATTRIB)
				|| !strEquals(STATION_TAG, pSatDesc->GetTag()))
			continue;

		//	Get the type of the satellite

		CStationType *pSatType = g_pUniverse->FindStationType(pSatDesc->GetAttributeInteger(TYPE_ATTRIB));
		if (pSatType == NULL)
			continue;

		//	Prepare the image for the satellite

		SSatImageDesc *pSatImage = SatImages.Insert();
		pSatType->SetImageSelector(InitCtx, &pSatImage->Selector);

		//	If we have an image variant, then set it

		int iVariant;
		if (pSatDesc->FindAttributeInteger(IMAGE_VARIANT_ATTRIB, &iVariant))
			{
			IImageEntry *pRoot = pSatType->GetImage().GetRoot();
			DWORD dwID = (pRoot ? pRoot->GetID() : DEFAULT_SELECTOR_ID);

			pSatImage->Selector.DeleteAll();
			pSatImage->Selector.AddVariant(dwID, iVariant);
			}

		pSatImage->pImage = &pSatType->GetImage(pSatImage->Selector, CCompositeImageModifiers());

		//	Now get the offset

		pSatImage->xOffset = pSatDesc->GetAttributeInteger(X_OFFSET_ATTRIB);
		pSatImage->yOffset = pSatDesc->GetAttributeInteger(Y_OFFSET_ATTRIB);

		//	Compute the satellite rect

		RECT rcSatImage = pSatImage->pImage->GetImageRect();
		RECT rcSatBounds;
		rcSatBounds.left = pSatImage->xOffset - (RectWidth(rcSatImage) / 2);
		rcSatBounds.top = -pSatImage->yOffset - (RectHeight(rcSatImage) / 2);
		rcSatBounds.right = rcSatBounds.left + RectWidth(rcSatImage);
		rcSatBounds.bottom = rcSatBounds.top + RectHeight(rcSatImage);

		//	Increase the size of the bounds

		rcBounds.left = Min(rcBounds.left, rcSatBounds.left);
		rcBounds.right = Max(rcBounds.right, rcSatBounds.right);
		rcBounds.top = Min(rcBounds.top, rcSatBounds.top);
		rcBounds.bottom = Max(rcBounds.bottom, rcSatBounds.bottom);
		}

	//	If no segments, then we just return the basic image

	if (SatImages.GetCount() == 0)
		{
		Entry.pImage = pMainImage;
		return;
		}

	//	Create an image that will hold the composite

	CG32bitImage *pCompositeImage = new CG32bitImage;
	pCompositeImage->Create(RectWidth(rcBounds), RectHeight(rcBounds), CG32bitImage::alpha8, CG32bitPixel::Null());
	int xCenter = -rcBounds.left;
	int yCenter = -rcBounds.top;

	//	Paint the main image

	pMainImage->PaintImage(*pCompositeImage, xCenter, yCenter, 0, Entry.iRotation, true);

	//	Paint all the satellites

	for (i = 0; i < SatImages.GetCount(); i++)
		SatImages[i].pImage->PaintImage(*pCompositeImage, xCenter + SatImages[i].xOffset, yCenter - SatImages[i].yOffset, 0, 0, true);

	//	Now create the proper image array

	RECT rcResult;
	rcResult.left = 0;
	rcResult.top = 0;
	rcResult.right = RectWidth(rcBounds);
	rcResult.bottom = RectHeight(rcBounds);

    int xOffset = (RectWidth(rcBounds) / 2) - xCenter;
    int yOffset = (RectHeight(rcBounds) / 2) - yCenter;

	Entry.pCompositeImageArray = new CObjectImageArray;
	Entry.pCompositeImageArray->Init(pCompositeImage, rcResult, 0, 0, true, xOffset, yOffset);

	//	Done

	Entry.pImage = Entry.pCompositeImageArray;
	}
示例#26
0
ALERROR CGameSettings::Load (const CString &sFilespec, CString *retsError)

//	Load
//
//	Load game settings from a file. If the file does not exist, then we 
//	set settings to default values

	{
	ALERROR error;
	int i;

	//	Initialize from defaults

	for (i = 0; i < OPTIONS_COUNT; i++)
		SetValue(i, CString(g_OptionData[i].pszDefaultValue, -1, true), true);

	//	Look for a file in the current directory and see if it is writable. If
	//	not, then look in AppData. We remember the place where we found a valid
	//	file as our AppData root (and we base other directories off that).

	if (pathIsWritable(sFilespec))
		{
		//	AppData is current directory
		m_sAppData = NULL_STR;
		}
	else
		{
		m_sAppData = pathAddComponent(pathGetSpecialFolder(folderAppData), TRANSCENDENCE_APP_DATA);
		if (!pathCreate(m_sAppData)
				|| !pathIsWritable(m_sAppData))
			{
			*retsError = strPatternSubst(CONSTLIT("Unable to write to AppData folder: %s"), m_sAppData);
			return ERR_FAIL;
			}
		}

	//	Settings file

	CString sSettingsFilespec = pathAddComponent(m_sAppData, sFilespec);

	//	Load XML

	CFileReadBlock DataFile(sSettingsFilespec);
	CXMLElement *pData;
	CString sError;
	if (error = CXMLElement::ParseXML(&DataFile, &pData, retsError))
		{
		//	ERR_NOTFOUND means that we couldn't find the Settings.xml
		//	file. In that case, initialize from defaults

		if (error == ERR_NOTFOUND)
			{
			LoadFromRegistry();
			m_bModified = true;
			return NOERROR;
			}

		//	Otherwise, it means that we got an error parsing the file.
		//	Return the error, but leave the settings initialized to defaults
		//	(We should be OK to continue, even with an error).

		else
			{
			m_bModified = false;
			return error;
			}
		}

	//	Initialize to unmodified (as we load settings we might change this)

	m_bModified = false;

	//	Loop over all elements

	for (i = 0; i < pData->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pData->GetContentElement(i);

		if (strEquals(pItem->GetTag(), OPTION_TAG))
			{
			int iOption = FindOptionData(pItem->GetAttribute(NAME_ATTRIB));
			if (iOption == -1)
				{
				kernelDebugLogMessage("Unknown option: %s", pItem->GetAttribute(NAME_ATTRIB));
				continue;
				}

			SetValue(iOption, pItem->GetAttribute(VALUE_ATTRIB), true);
			}
		else if (strEquals(pItem->GetTag(), KEY_MAP_TAG))
			{
			if (error = m_KeyMap.ReadFromXML(pItem))
				return error;
			}
		else if (strEquals(pItem->GetTag(), EXTENSION_FOLDER_TAG))
			{
			CString sFolder;
			if (pItem->FindAttribute(PATH_ATTRIB, &sFolder))
				m_ExtensionFolders.Insert(sFolder);
			}
		else if (strEquals(pItem->GetTag(), EXTENSIONS_TAG))
			{
			if (error = m_Extensions.ReadFromXML(pItem))
				return error;
			}
		else if (m_pExtra)
			{
			bool bModified;
			if (error = m_pExtra->OnLoadSettings(pItem, &bModified))
				return error;

			if (bModified)
				m_bModified = true;
			}
		}

	//	Done

	delete pData;

	return NOERROR;
	}
ALERROR CLanguageDataBlock::InitFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	InitFromXML
//
//	Initializes from an XML block

	{
	int i;

	for (i = 0; i < pDesc->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pDesc->GetContentElement(i);
		CString sID = pItem->GetAttribute(ID_ATTRIB);
		if (sID.IsBlank())
			{
			Ctx.sError = strPatternSubst(CONSTLIT("Invalid id in <Language> block"));
			return ERR_FAIL;
			}

		if (strEquals(pItem->GetTag(), TEXT_TAG))
			{
			//	Link the code

			CCodeChainCtx CCCtx;
			ICCItem *pCode = CCCtx.Link(pItem->GetContentText(0), 0, NULL);
			if (pCode->IsError())
				{
				Ctx.sError = strPatternSubst(CONSTLIT("Language id: %s : %s"), sID, pCode->GetStringValue());
				return ERR_FAIL;
				}

			//	Add an entry

			bool bIsNew;
			SEntry *pEntry = m_Data.SetAt(sID, &bIsNew);
			if (!bIsNew)
				{
				Ctx.sError = strPatternSubst(CONSTLIT("Duplicate <Language> element: %s"), sID);
				return ERR_FAIL;
				}

			//	If pCode is a string and not an identifier, then we can just
			//	store it directly.

			if (pCode->IsIdentifier() && pCode->IsQuoted())
				{
				pEntry->pCode = NULL;
				pEntry->sText = pCode->GetStringValue();
				}

			//	Otherwise we store the code

			else
				pEntry->pCode = pCode->Reference();

			//	Done

			CCCtx.Discard(pCode);
			}
		else if (strEquals(pItem->GetTag(), MESSAGE_TAG))
			{
			//	Add an entry

			bool bIsNew;
			SEntry *pEntry = m_Data.SetAt(sID, &bIsNew);
			if (!bIsNew)
				{
				Ctx.sError = strPatternSubst(CONSTLIT("Duplicate <Language> element: %s"), sID);
				return ERR_FAIL;
				}

			//	Set the text

			pEntry->pCode = NULL;
			pEntry->sText = pItem->GetAttribute(TEXT_ATTRIB);
			}
		else
			{
			Ctx.sError = strPatternSubst(CONSTLIT("Invalid element in <Language> block: <%s>"), pItem->GetTag());
			return ERR_FAIL;
			}
		}

	return NOERROR;
	}
示例#28
0
ALERROR CExtension::LoadModuleElement (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	LoadModuleElement
//
//	Loads <Module>

	{
	ALERROR error;

	CString sFilename = pDesc->GetAttribute(FILENAME_ATTRIB);

	//	Load the module XML

	CXMLElement *pModuleXML;
	if (error = Ctx.pResDb->LoadModule(Ctx.sFolder, sFilename, &pModuleXML, &Ctx.sError))
		{
		if (error == ERR_NOTFOUND)
			Ctx.sError = strPatternSubst(CONSTLIT("%s: %s"), Ctx.pResDb->GetFilespec(), Ctx.sError);
		return error;
		}

	if (!strEquals(pModuleXML->GetTag(), TRANSCENDENCE_MODULE_TAG))
		{
		delete pModuleXML;
		Ctx.sError = strPatternSubst(CONSTLIT("Module must have <TranscendenceModule> root element: %s"), sFilename);
		return ERR_FAIL;
		}

	//	We are loading a module

	bool bOldLoadModule = Ctx.bLoadModule;
	Ctx.bLoadModule = true;

	//	Look for resources relative to the module path

	CString sOldFolder = Ctx.sFolder;
	CString sFolder = pathGetPath(sFilename);
	if (!sFolder.IsBlank() && Ctx.GetAPIVersion() >= 26)
		Ctx.sFolder = pathAddComponent(Ctx.sFolder, sFolder);

	//	Errors credited to this file.

	CString sOldErrorFilespec = Ctx.sErrorFilespec;
	if (strEquals(pathGetExtension(sOldErrorFilespec), FILESPEC_TDB_EXTENSION))
		Ctx.sErrorFilespec = strPatternSubst(CONSTLIT("%s#%s"), sOldErrorFilespec, sFilename);
	else
		Ctx.sErrorFilespec = sFilename;

	//	Process each design element in the module

	if (error = LoadModuleContent(Ctx, pModuleXML))
		return error;

	//	Clean up

	Ctx.sFolder = sOldFolder;
	Ctx.sErrorFilespec = sOldErrorFilespec;
	Ctx.bLoadModule = bOldLoadModule;

	//	If we're keeping the XML, then add it to our table

	if (Ctx.bKeepXML && !m_ModuleXML.Find(sFilename))
		m_ModuleXML.Insert(sFilename, pModuleXML);
	else
		delete pModuleXML;

	return NOERROR;
	}