void CDesignCollection::CleanUp (void)

//	CleanUp
//
//	Free all entries so that we don't hold on to any resources.

	{
	int i;

	//	Some classes need to clean up global data
	//	(But we need to do this before we destroy the types)

	CStationType::Reinit();

	//	Delete the base types

	m_Base.DeleteAll();

	//	Delete all extensions

	for (i = 0; i < GetExtensionCount(); i++)
		{
		SExtensionDesc *pEntry = GetExtension(i);
		pEntry->Table.DeleteAll();
		delete pEntry;
		}

	m_Extensions.DeleteAll();
	}
void CDesignCollection::SelectAdventure (DWORD dwUNID)

//	SelectAdventure
//
//	Enable the given adventure and disable all other adventures

	{
	int i;

	for (i = 0; i < GetExtensionCount(); i++)
		{
		SExtensionDesc *pEntry = GetExtension(i);
		if (pEntry->iType == extAdventure)
			pEntry->bEnabled = (pEntry->dwUNID == dwUNID);
		}
	}
void CDesignCollection::GetEnabledExtensions (TArray<DWORD> *retExtensionList)

//	GetEnabledExtensions
//
//	Returns the list of enabled extensions

	{
	int i;

	retExtensionList->DeleteAll();

	for (i = 0; i < GetExtensionCount(); i++)
		{
		SExtensionDesc *pEntry = GetExtension(i);
		if (pEntry->iType == extExtension && pEntry->bEnabled)
			retExtensionList->Insert(pEntry->dwUNID);
		}
	}
Example #4
0
void CDesignCollection::GetEnabledExtensions (TArray<CExtension *> *retExtensionList)

//	GetEnabledExtensions
//
//	Returns the list of enabled extensions

	{
	int i;

	retExtensionList->DeleteAll();

	for (i = 0; i < GetExtensionCount(); i++)
		{
		CExtension *pEntry = GetExtension(i);
		if (pEntry->GetType() == extExtension)
			retExtensionList->Insert(pEntry);
		}
	}
void CDesignCollection::RemoveAll (void)

//	RemoveAll
//
//	Remove all entries

	{
	int i;

	//	Delete the base types

	m_Base.DeleteAll();

	//	Delete all extensions

	for (i = 0; i < GetExtensionCount(); i++)
		{
		SExtensionDesc *pEntry = GetExtension(i);
		pEntry->Table.DeleteAll();
		delete pEntry;
		}

	m_Extensions.RemoveAll();
	}
ALERROR CDesignCollection::BindDesign (SDesignLoadCtx &Ctx)

//	BindDesign
//
//	Bind the design collection so that design types point the appropriate
//	pointers by UNID

	{
	ALERROR error;
	int i, j;

	//	Unbind everything

	for (i = 0; i < m_AllTypes.GetCount(); i++)
		m_AllTypes.GetEntry(i)->UnbindDesign();
	m_AllTypes.DeleteAll();

	//	Reset the bind tables

	for (i = 0; i < designCount; i++)
		m_ByType[i].DeleteAll();

	//	We start with all the base types

	for (i = 0; i < m_Base.GetCount(); i++)
		m_AllTypes.AddEntry(m_Base.GetEntry(i));

	//	Start with base topology

	m_pTopology = &m_BaseTopology;
	m_pAdventureExtension = NULL;

	//	Now add all enabled extensions

	for (i = 0; i < GetExtensionCount(); i++)
		{
		SExtensionDesc *pExtension = GetExtension(i);

		if (pExtension->bEnabled)
			{
			//	Add design elements in extension

			for (j = 0; j < pExtension->Table.GetCount(); j++)
				{
				CDesignType *pEntry = pExtension->Table.GetEntry(j);
				m_AllTypes.AddOrReplaceEntry(pEntry);
				}

			//	Handle adventure extensions

			if (pExtension->iType == extAdventure)
				{
				//	Keep track of extension

				m_pAdventureExtension = pExtension;

				//	Add topology

				m_pTopology = &pExtension->Topology;
				}
			}
		else
			{
			if (pExtension->iType == extAdventure)
				{
				DWORD dwCoverImage = 0;

				//	Adventure desc elements are added even if not enabled

				for (j = 0; j < pExtension->Table.GetCount(); j++)
					{
					CDesignType *pEntry = pExtension->Table.GetEntry(j);
					if (pEntry->GetType() == designAdventureDesc)
						{
						m_AllTypes.AddOrReplaceEntry(pEntry);

						//	Get the cover image used by the adventure, because
						//	we need to load that too.

						CAdventureDesc *pDesc = CAdventureDesc::AsType(pEntry);
						dwCoverImage = pDesc->GetBackgroundUNID();
						}
					}

				//	Make sure we load the cover image

				if (dwCoverImage)
					{
					for (j = 0; j < pExtension->Table.GetCount(); j++)
						{
						CDesignType *pEntry = pExtension->Table.GetEntry(j);
						if (pEntry->GetUNID() == dwCoverImage)
							m_AllTypes.AddOrReplaceEntry(pEntry);
						}
					}
				}
			}
		}

	//	If this is a new game, then create all the Template types

	if (Ctx.bNewGame)
		{
		m_DynamicUNIDs.DeleteAll();
		m_DynamicTypes.DeleteAll();

		if (error = FireOnGlobalTypesInit(Ctx))
			return error;

		if (error = CreateTemplateTypes(Ctx))
			return error;
		}

	//	Add all the dynamic types. These came either from the saved game file or
	//	from the Template types above.

	for (i = 0; i < m_DynamicTypes.GetCount(); i++)
		m_AllTypes.AddOrReplaceEntry(m_DynamicTypes.GetType(i));

	//	Initialize the byType lists

	for (i = 0; i < m_AllTypes.GetCount(); i++)
		{
		CDesignType *pEntry = m_AllTypes.GetEntry(i);
		m_ByType[pEntry->GetType()].AddEntry(pEntry);
		}

	//	Set our adventure desc as current; since adventure descs are always 
	//	loaded this is the only thing that we can use to tell if we should
	//	call global events.
	//
	//	This must happen after Unbind (because that clears it) and before
	//	PrepareBindDesign.
	//
	//	NOTE: m_pAdventureDesc can be NULL (e.g., in the intro screen).

	if (m_pAdventureDesc)
		m_pAdventureDesc->SetCurrentAdventure();

	//	Cache a map between currency name and economy type
	//	We need to do this before Bind because some types will lookup
	//	a currency name during Bind.

	m_EconomyIndex.DeleteAll();
	for (i = 0; i < GetCount(designEconomyType); i++)
		{
		CEconomyType *pEcon = CEconomyType::AsType(GetEntry(designEconomyType, i));
		const CString &sName = pEcon->GetSID();

		bool bUnique;
		CEconomyType **ppDest = m_EconomyIndex.SetAt(sName, &bUnique);
		if (!bUnique)
			return pEcon->ComposeLoadError(Ctx, CONSTLIT("Currency ID must be unique"));

		*ppDest = pEcon;
		}

	//	Prepare to bind. This is used by design elements
	//	that need two passes to bind.

	for (i = 0; i < m_AllTypes.GetCount(); i++)
		{
		CDesignType *pEntry = m_AllTypes.GetEntry(i);
		if (error = pEntry->PrepareBindDesign(Ctx))
			return error;
		}

	//	Now call Bind on all active design entries

	for (i = 0; i < evtCount; i++)
		m_EventsCache[i]->DeleteAll();

	for (i = 0; i < m_AllTypes.GetCount(); i++)
		{
		CDesignType *pEntry = m_AllTypes.GetEntry(i);
		if (error = pEntry->BindDesign(Ctx))
			return error;

		//	Cache some global events. We keep track of the global events for
		//	all types so that we can access them faster.

		CacheGlobalEvents(pEntry);
		}

	//	Finish binding. This pass is used by design elements
	//	that need to do stuff after all designs are bound.

	for (i = 0; i < m_AllTypes.GetCount(); i++)
		{
		CDesignType *pEntry = m_AllTypes.GetEntry(i);
		if (error = pEntry->FinishBindDesign(Ctx))
			return error;
		}

	return NOERROR;
	}
ALERROR CDesignCollection::SelectExtensions (CAdventureDesc *pAdventure, TArray<DWORD> *pExtensionList, bool *retbBindNeeded, CString *retsError)

//	SelectExtensions
//
//	Enables all extensions in pExtensionList and disables all others
//	(if pExtensionList == NULL then we enable all extensions).
//
//	Returns an error if an extension on the list could not be found.

	{
	int i;
	bool bBindNeeded = false;

	TArray<bool> OldState;
	OldState.InsertEmpty(GetExtensionCount());

	//	Disable all extensions

	for (i = 0; i < GetExtensionCount(); i++)
		{
		SExtensionDesc *pEntry = GetExtension(i);
		if (pEntry->iType == extExtension)
			{
			OldState[i] = pEntry->bEnabled;
			pEntry->bEnabled = false;
			}
		}

	//	Enable all extensions in the list

	if (pExtensionList)
		{
		for (i = 0; i < pExtensionList->GetCount(); i++)
			{
			SExtensionDesc *pEntry = FindExtension(pExtensionList->GetAt(i));
			if (pEntry == NULL || pEntry->iType == extAdventure)
				{
				if (retsError)
					*retsError = strPatternSubst(CONSTLIT("Unable to find extension: %x"), pExtensionList->GetAt(i));
				return ERR_NOTFOUND;
				}

			if (pEntry->iType == extExtension
					&& IsExtensionCompatibleWithAdventure(pEntry, pAdventure))
				pEntry->bEnabled = true;
			}
		}
	else
		{
		//	Enable all extensions

		for (i = 0; i < GetExtensionCount(); i++)
			{
			SExtensionDesc *pEntry = GetExtension(i);
			if (pEntry->iType == extExtension 
					&& IsExtensionCompatibleWithAdventure(pEntry, pAdventure)
					&& (!pEntry->bDebugOnly || g_pUniverse->InDebugMode()))
				pEntry->bEnabled = true;
			}
		}

	//	See if we made any changes

	for (i = 0; i < GetExtensionCount(); i++)
		{
		SExtensionDesc *pEntry = GetExtension(i);
		if (pEntry->iType == extExtension && pEntry->bEnabled != OldState[i])
			{
			bBindNeeded = true;
			break;
			}
		}

	//	Done

	if (retbBindNeeded)
		*retbBindNeeded = bBindNeeded;

	return NOERROR;
	}
ALERROR CDesignCollection::BindDesign (SDesignLoadCtx &Ctx)

//	BindDesign
//
//	Bind the design collection so that design types point the appropriate
//	pointers by UNID

	{
	ALERROR error;
	int i, j;

	//	Reset the bind tables

	m_AllTypes.RemoveAll();
	for (i = 0; i < designCount; i++)
		m_ByType[i].RemoveAll();

	//	We start with all the base types

	for (i = 0; i < m_Base.GetCount(); i++)
		m_AllTypes.AddEntry(m_Base.GetEntry(i));

	//	Start with base topology

	m_pTopology = &m_BaseTopology;
	m_pAdventureExtension = NULL;

	//	Now add all enabled extensions

	for (i = 0; i < GetExtensionCount(); i++)
		{
		SExtensionDesc *pExtension = GetExtension(i);

		if (pExtension->bEnabled)
			{
			//	Add design elements in extension

			for (j = 0; j < pExtension->Table.GetCount(); j++)
				m_AllTypes.AddOrReplaceEntry(pExtension->Table.GetEntry(j));

			//	Handle adventure extensions

			if (pExtension->iType == extAdventure)
				{
				//	Keep track of extension

				m_pAdventureExtension = pExtension;

				//	Add topology

				m_pTopology = &pExtension->Topology;
				}
			}
		else
			{
			if (pExtension->iType == extAdventure)
				{
				//	Adventure desc elements are added even if not enabled

				for (j = 0; j < pExtension->Table.GetCount(); j++)
					{
					CDesignType *pEntry = pExtension->Table.GetEntry(j);
					if (pEntry->GetType() == designAdventureDesc)
						m_AllTypes.AddOrReplaceEntry(pEntry);
					}
				}
			}
		}

	//	Initialize the byType lists

	for (i = 0; i < m_AllTypes.GetCount(); i++)
		{
		CDesignType *pEntry = m_AllTypes.GetEntry(i);
		m_ByType[pEntry->GetType()].AddEntry(pEntry);
		}

	//	Now call Bind on all active design entries

	for (i = 0; i < m_AllTypes.GetCount(); i++)
		{
		CDesignType *pEntry = m_AllTypes.GetEntry(i);
		if (error = pEntry->BindDesign(Ctx))
			return error;
		}

	//	Check to make sure we have at least one topology node

	if (m_pTopology->GetRootNodeCount() == 0)
		{
		Ctx.sError = CONSTLIT("No topology nodes found");
		return ERR_FAIL;
		}

	return NOERROR;
	}