Example #1
0
ALERROR CGroupOfGenerators::LoadFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	LoadFromXML
//
//	Load from XML

	{
	int i;
	ALERROR error;

	//	Load content elements

	m_Table.InsertEmpty(pDesc->GetContentElementCount());
	for (i = 0; i < m_Table.GetCount(); i++)
		{
		CXMLElement *pEntry = pDesc->GetContentElement(i);
			
		m_Table[i].iChance = pEntry->GetAttributeInteger(CHANCE_ATTRIB);
		if (m_Table[i].iChance == 0)
			m_Table[i].iChance = 100;

		CString sCount = pEntry->GetAttribute(COUNT_ATTRIB);
		if (sCount.IsBlank())
			m_Table[i].Count = DiceRange(0, 0, 1);
		else
			m_Table[i].Count.LoadFromXML(sCount);

		if (error = IItemGenerator::CreateFromXML(Ctx, pEntry, &m_Table[i].pItem))
			return error;
		}

	//	See if we force an average value

	CString sAttrib;
	if (pDesc->FindAttribute(LEVEL_VALUE_ATTRIB, &sAttrib))
		{
		TArray<int> Values;
		ParseIntegerList(sAttrib, 0, &Values);

		m_AverageValue.InsertEmpty(MAX_ITEM_LEVEL + 1);
		m_AverageValue[0] = 0;
		for (i = 0; i < Values.GetCount(); i++)
			m_AverageValue[i + 1] = Values[i];

		for (i = Values.GetCount() + 1; i <= MAX_ITEM_LEVEL; i++)
			m_AverageValue[i] = 0;
		}
	else if (pDesc->FindAttribute(VALUE_ATTRIB, &sAttrib))
		{
		int iValue = strToInt(sAttrib, 0);

		m_AverageValue.InsertEmpty(MAX_ITEM_LEVEL + 1);
		m_AverageValue[0] = 0;
		for (i = 1; i <= MAX_ITEM_LEVEL; i++)
			m_AverageValue[i] = iValue;
		}

	return NOERROR;
	}
CTopologyNode *CConquerNodesProc::ChooseRandomNode (CTopologyNodeList &NodeList, TArray<SNodeWeight> &Weights)

//	ChooseRandomNode
//
//	Chooses a random node from the list, using Weights as a descriminator

	{
	int i;

	//	Generate a weight for each node

	TArray<int> Chance;
	TArray<int> Success;
	Chance.InsertEmpty(NodeList.GetCount());
	Success.InsertEmpty(NodeList.GetCount());

	int iTotalChance = 0;
	for (i = 0; i < NodeList.GetCount(); i++)
		if (NodeList[i]->IsMarked())
			{
			Chance[i] = CalcNodeWeight(NodeList[i], Weights, &Success[i]);
			iTotalChance += Chance[i];
			}
		else
			Chance[i] = 0;

	//	If nothing left, return

	if (iTotalChance == 0)
		return NULL;

	//	Pick a random node

	int iRoll = mathRandom(1, iTotalChance);
	for (i = 0; i < Chance.GetCount(); i++)
		{
		if (iRoll <= Chance[i])
			{
			if (mathRandom(1, 100) <= Success[i])
				return NodeList[i];
			else
				return NULL;
			}
		else
			iRoll -= Chance[i];
		}

	ASSERT(false);
	return NULL;
	}
Example #3
0
void CGameSession::PaintSoundtrackTitles (CG32bitImage &Dest)

//	PaintSoundtrackTitles
//
//	Paints the info about the currently playing soundtrack.

	{
	int iPos;
	CMusicResource *pTrack = m_Soundtrack.GetCurrentTrack(&iPos);
	if (pTrack == NULL)
		return;

	int iSegment = pTrack->FindSegment(iPos);

	//	Time

	int iMilliseconds = iPos % 1000;
	int iSeconds = (iPos / 1000) % 60;
	int iMinutes = (iPos / 60000);

	//	Add all the components

	TArray<CString> Desc;
	Desc.InsertEmpty(3);
	Desc[0] = pTrack->GetPerformedBy();
	Desc[1] = pTrack->GetFilename();
	Desc[2] = strPatternSubst(CONSTLIT("Segment %d of %d [%02d:%02d.%03d]"), iSegment + 1, pTrack->GetSegmentCount(), iMinutes, iSeconds, iMilliseconds);

	//	Paint

	PaintInfoText(Dest, pTrack->GetTitle(), Desc, true);
	}
ALERROR CCompositeEntry::InitFromXML (SDesignLoadCtx &Ctx, CIDCounter &IDGen, CXMLElement *pDesc)

//	InitFromXML
//
//	Initialize from XML

	{
	ALERROR error;
	int i;

	m_dwID = IDGen.GetID();

	//	Load each sub-entry in turn

	int iCount = pDesc->GetContentElementCount();
	if (iCount == 0)
		return NOERROR;

	m_Layers.InsertEmpty(iCount);
	for (i = 0; i < iCount; i++)
		{
		if (error = CCompositeImageDesc::InitEntryFromXML(Ctx, pDesc->GetContentElement(i), IDGen, &m_Layers[i]))
			return error;
		}

	//	Done

	return NOERROR;
	}
Example #5
0
TArray<CString> CDatum::AsStringArray (void) const

//	AsStringArray
//
//	Coerces to an array of strings.

	{
	int i;

	TArray<CString> Result;
	Result.InsertEmpty(GetCount());
	for (i = 0; i < GetCount(); i++)
		Result[i] = GetElement(i).AsString();

	return Result;
	}
Example #6
0
ALERROR CLocationCriteriaTableEntry::InitFromXML (SDesignLoadCtx &Ctx, CIDCounter &IDGen, CXMLElement *pDesc)

//	InitFromXML
//
//	Initialize from XML

	{
	ALERROR error;
	int i;

	m_dwID = IDGen.GetID();
	m_iDefault = -1;

	//	Load each sub-entry in turn

	int iCount = pDesc->GetContentElementCount();
	if (iCount == 0)
		return NOERROR;

	m_Table.InsertEmpty(iCount);
	for (i = 0; i < iCount; i++)
		{
		CXMLElement *pItem = pDesc->GetContentElement(i);

		if (error = CCompositeImageDesc::InitEntryFromXML(Ctx, pItem, IDGen, &m_Table[i].pImage))
			return error;

		//	Load the criteria

		CString sCriteria = pItem->GetAttribute(CRITERIA_ATTRIB);
		if (error = m_Table[i].Criteria.Parse(sCriteria, 0, &Ctx.sError))
			return error;

		if (m_iDefault == -1 && m_Table[i].Criteria.MatchesDefault())
			m_iDefault = i;
		}

	//	If we don't have a default, the pick the last item.

	if (m_iDefault == -1 
			&& m_Table.GetCount() > 0)
		m_iDefault = m_Table.GetCount() - 1;

	//	Done

	return NOERROR;
	}
Example #7
0
void CIntGraph::AddGraph (CIntGraph &Source)

//	AddGraph
//
//	Adds the source graph to this graph

	{
	int i;

	//	Keep a map between source ID and dest ID

	TArray<DWORD> SourceToDest;
	SourceToDest.InsertEmpty(Source.m_Nodes.GetCount());
	for (i = 0; i < Source.m_Nodes.GetCount(); i++)
		{
		SNode *pNode = Source.GetNode(i);
		if (!NodeIsFree(pNode))
			{
			//	Add node to destination

			DWORD dwNewID;
			AddNode(pNode->x, pNode->y, &dwNewID);

			//	Add a mapping

			SourceToDest[i] = dwNewID;
			}
		}

	//	Now add the connections between nodes

	for (i = 0; i < Source.m_Nodes.GetCount(); i++)
		{
		SNode *pNode = Source.GetNode(i);
		if (!NodeIsFree(pNode))
			{
			SConnection *pConnection = Source.GetForwardConnection(pNode);
			while (pConnection)
				{
				Connect(SourceToDest[i], SourceToDest[pConnection->iTo]);

				pConnection = Source.GetNextConnection(pConnection);
				}
			}
		}
	}
Example #8
0
ALERROR CTableOfGenerators::LoadFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	LoadFromXML
//
//	Load from XML

	{
	int i;
	ALERROR error;

	m_iTotalChance = 0;
	int iCount = pDesc->GetContentElementCount();
	if (iCount > 0)
		{
		m_Table.InsertEmpty(iCount);

		//	Pre-initialize to NULL in case we exit with an error

		for (i = 0; i < iCount; i++)
			m_Table[i].pItem = NULL;

		//	Load

		for (i = 0; i < iCount; i++)
			{
			CXMLElement *pEntry = pDesc->GetContentElement(i);
			
			m_Table[i].iChance = pEntry->GetAttributeInteger(CHANCE_ATTRIB);
			m_iTotalChance += m_Table[i].iChance;

			CString sCount = pEntry->GetAttribute(COUNT_ATTRIB);
			if (sCount.IsBlank())
				m_Table[i].Count = DiceRange(0, 0, 1);
			else
				m_Table[i].Count.LoadFromXML(sCount);

			if (error = IItemGenerator::CreateFromXML(Ctx, pEntry, &m_Table[i].pItem))
				return error;
			}
		}

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

//	InitFromXML
//
//	Initialize from XML

	{
	ALERROR error;
	int i;

	m_dwID = IDGen.GetID();

	//	Load each sub-entry in turn

	int iCount = pDesc->GetContentElementCount();
	if (iCount == 0)
		return NOERROR;

	m_iTotalChance = 0;
	m_Table.InsertEmpty(iCount);
	for (i = 0; i < iCount; i++)
		{
		CXMLElement *pItem = pDesc->GetContentElement(i);

		if (error = CCompositeImageDesc::InitEntryFromXML(Ctx, pItem, IDGen, &m_Table[i].pImage))
			return error;

		//	Load the chance

		m_Table[i].iChance = pItem->GetAttributeIntegerBounded(CHANCE_ATTRIB, 0, -1, 1);
		m_iTotalChance += m_Table[i].iChance;
		}

	//	Done

	return NOERROR;
	}
ALERROR CTableOfDeviceGenerators::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);

	m_iTotalChance = 0;
	int iCount = pDesc->GetContentElementCount();
	if (iCount > 0)
		{
		m_Table.InsertEmpty(iCount);
		for (i = 0; i < iCount; i++)
			{
			CXMLElement *pEntry = pDesc->GetContentElement(i);
			
			m_Table[i].iChance = pEntry->GetAttributeInteger(CHANCE_ATTRIB);
			m_iTotalChance += m_Table[i].iChance;

			if (error = IDeviceGenerator::CreateFromXML(Ctx, pEntry, &m_Table[i].pDevice))
				{
				m_Table[i].pDevice = NULL;
				return error;
				}
			}
		}

	return NOERROR;
	}
Example #11
0
ALERROR CGroupOfGenerators::OnDesignLoadComplete (SDesignLoadCtx &Ctx)

//	OnDesignLoadComplete
//
//	Resolve references

	{
	int i;
	ALERROR error;

	for (i = 0; i < m_Table.GetCount(); i++)
		{
		if (error = m_Table[i].pItem->OnDesignLoadComplete(Ctx))
			return error;
		}

	//	Initialize count adjustment

	m_CountAdj.InsertEmpty(m_AverageValue.GetCount());
	for (i = 0; i < m_AverageValue.GetCount(); i++)
		m_CountAdj[i] = -1.0;

	return NOERROR;
	}
Example #12
0
void CMnemosynthDb::GenerateDelta (TArray<SMnemosynthUpdate> *retUpdates, CDatum *retdLocalUpdates)

//	GenerateDelta
//
//	Generates a list of changes since the last time we called this

	{
	CSmartLock Lock(m_cs);

	int i, j;

	//	Edge conditions

	if (m_Endpoints.GetCount() == 0)
		{
		*retdLocalUpdates = CDatum();
		return;
		}

	//	If we are not the central module, then we only need to
	//	generate a list of updates made by our own endpoint
	//	(and send it to our central module).

	if (!m_pProcess->IsCentralModule())
		{
		if (GetLocalEndpoint().dwSeqRecv > GetLocalEndpoint().dwSeqSent)
			{
			SMnemosynthUpdate *pUpdate = retUpdates->Insert();
			pUpdate->sDestEndpoint = strPattern("%s/CentralModule", m_pProcess->GetMachineName());

			//	Generate a payload for our updates

			CComplexArray *pEntries = new CComplexArray;
			for (i = 0; i < m_Collections.GetCount(); i++)
				{
				const CString &sCollection = m_Collections.GetKey(i);
				SCollection *pCollection = &m_Collections[i];

				for (j = 0; j < pCollection->Entries.GetCount(); j++)
					{
					SEntry *pEntry = &pCollection->Entries[j];
					if (pEntry->dwOwnerID == 0 && pEntry->dwSequence > GetLocalEndpoint().dwSeqSent)
						{
						CDatum dEntry = GenerateEntry(i, pCollection->Entries.GetKey(j), pEntry);
						pEntries->Insert(dEntry);

						//	If this entry is Nil then we can deleted. (We don't
						//	need it as a deletion stub since we just composed
						//	the update. If this message gets lost we need to
						//	resend everything).

						if (pCollection->Entries.GetValue(j).dValue.IsNil())
							{
							pCollection->Entries.Delete(j);
							j--;
							}
						}
					}
				}

			//	Create the payload

			CComplexStruct *pPayload = new CComplexStruct;
			pPayload->SetElement(STR_COLLECTIONS, GenerateCollectionsArray());
			pPayload->SetElement(STR_ENDPOINT, GetLocalEndpoint().sName);
			pPayload->SetElement(STR_ENTRIES, CDatum(pEntries));
			pPayload->SetElement(FIELD_PROCESS_ID, CDatum(GetLocalEndpoint().dwProcessID));

			//	Add it

			CDatum dLocalUpdates = CDatum(pPayload);
			pUpdate->Payloads.Insert(dLocalUpdates);

			//	Return it

			*retdLocalUpdates = dLocalUpdates;
			}
		else
			*retdLocalUpdates = CDatum();
		}

	//	Otherwise, loop over all endpoints and generate a different
	//	update entry for each one that we need to handle

	else
		{
		bool bFullUpdateNeeded = false;
		for (i = 1; i < m_Endpoints.GetCount(); i++)
			if (m_Endpoints[i].bFullUpdate)
				{
				bFullUpdateNeeded = true;
				break;
				}

		//	Collections

		CDatum dCollections = GenerateCollectionsArray();

		//	We end up creating one or two arrays of deltas. The first
		//	array has all the changes since we last generated a delta
		//	(this is used for endpoints that we updated last time).
		//
		//	The second array has a full set of data (this is for new
		//	endpoints).

		TArray<CComplexArray *> UpdateEntries;
		TArray<CComplexArray *> FullEntries;
		TArray<CDatum> UpdatePayloads;
		TArray<CDatum> FullPayloads;

		UpdateEntries.InsertEmpty(m_Endpoints.GetCount());
		UpdatePayloads.InsertEmpty(m_Endpoints.GetCount());
		if (bFullUpdateNeeded)
			{
			FullEntries.InsertEmpty(m_Endpoints.GetCount());
			FullPayloads.InsertEmpty(m_Endpoints.GetCount());
			}

		for (i = 0; i < m_Endpoints.GetCount(); i++)
			{
			UpdateEntries[i] = new CComplexArray;

			CComplexStruct *pStruct = new CComplexStruct;
			pStruct->SetElement(STR_COLLECTIONS, dCollections);
			pStruct->SetElement(STR_ENDPOINT, m_Endpoints[i].sName);
			pStruct->SetElement(STR_ENTRIES, CDatum(UpdateEntries[i]));
			pStruct->SetElement(FIELD_PROCESS_ID, CDatum(m_Endpoints[i].dwProcessID));
			UpdatePayloads[i] = CDatum(pStruct);

			if (bFullUpdateNeeded)
				{
				FullEntries[i] = new CComplexArray;

				pStruct = new CComplexStruct;
				pStruct->SetElement(STR_COLLECTIONS, dCollections);
				pStruct->SetElement(STR_ENDPOINT, m_Endpoints[i].sName);
				pStruct->SetElement(STR_ENTRIES, CDatum(FullEntries[i]));
				pStruct->SetElement(FIELD_PROCESS_ID, CDatum(m_Endpoints[i].dwProcessID));
				FullPayloads[i] = CDatum(pStruct);
				}
			}

		//	Loop over all entries in the database and add them to the
		//	appropriate payload arrays

		for (i = 0; i < m_Collections.GetCount(); i++)
			{
			const CString &sCollection = m_Collections.GetKey(i);
			SCollection *pCollection = &m_Collections[i];

			for (j = 0; j < pCollection->Entries.GetCount(); j++)
				{
				SEntry *pEntry = &pCollection->Entries[j];

				//	Get the endpoint for the owner of this collection

				int iOwner = FindEndpointIndex(pEntry->dwOwnerID);
				if (iOwner == -1)
					continue;

				//	Add to the update array

				if (pEntry->dwSequence > m_Endpoints[iOwner].dwSeqSent)
					{
					CDatum dEntry = GenerateEntry(i, pCollection->Entries.GetKey(j), pEntry);
					UpdateEntries[iOwner]->Insert(dEntry);

#ifdef DEBUG_MNEMOSYNTH
					printf("[CMnemosynthDb::GenerateDelta]: Endpoint %s %x\n", (LPSTR)m_Endpoints[iOwner].sName, m_Endpoints[iOwner].dwSeqSent);
#endif
					}

				//	Add to full array, if necessary

				if (bFullUpdateNeeded)
					{
					//	Don't bother inserting Nil entries (since this is a full
					//	update).

					if (!pEntry->dValue.IsNil())
						{
						CDatum dEntry = GenerateEntry(i, pCollection->Entries.GetKey(j), pEntry);
						FullEntries[iOwner]->Insert(dEntry);
						}
					}

				//	If this entry is Nil then we can deleted. (We don't
				//	need it as a deletion stub since we just composed
				//	the update. If this message gets lost we need to
				//	resend everything).

				if (pEntry->dValue.IsNil())
					{
					pCollection->Entries.Delete(j);
					j--;
					}
				}
			}

		//	Now iterate over all destination endpoints

		for (i = 1; i < m_Endpoints.GetCount(); i++)
			{
			SEndpoint *pDestEndpoint = &m_Endpoints[i];

#ifdef DEBUG_MNEMOSYNTH
			printf("[CMnemosynthDb::GenerateDelta]: Composing for endpoint %s %s%s.\n", (LPSTR)pDestEndpoint->sName, (pDestEndpoint->bCentralModule ? "CentralModule " : ""), (pDestEndpoint->bLocalMachine ? "local" : ""));
#endif

			//	If this is a local module, then send it any updates
			//	for everything except itself

			if (pDestEndpoint->bLocalMachine && !pDestEndpoint->bCentralModule)
				{
				SMnemosynthUpdate *pUpdate = NULL;

				for (j = 0; j < m_Endpoints.GetCount(); j++)
					if (i != j)
						{
						//	If we have no update entries, then skip.

						if (!pDestEndpoint->bFullUpdate
								&& UpdatePayloads[j].GetElement(STR_ENTRIES).GetCount() == 0)
							continue;

						//	Add an update entry

						if (pUpdate == NULL)
							{
							pUpdate = retUpdates->Insert();
							pUpdate->sDestEndpoint = pDestEndpoint->sName;
							}

						if (pDestEndpoint->bFullUpdate)
							pUpdate->Payloads.Insert(FullPayloads[j]);
						else
							pUpdate->Payloads.Insert(UpdatePayloads[j]);
						}
				}

			//	Otherwise, if this is a foreign central module, then
			//	send it any updates for all local endpoints

			else if (pDestEndpoint->bCentralModule && !pDestEndpoint->bLocalMachine)
				{
				SMnemosynthUpdate *pUpdate = NULL;

#ifdef DEBUG_MNEMOSYNTH
				if (pDestEndpoint->bFullUpdate)
					printf("[CMnemosynthDb::GenerateDelta]: Composing FULL update for %s\n", (LPSTR)pDestEndpoint->sName);
				else
					printf("[CMnemosynthDb::GenerateDelta]: Composing DIFF update for %s\n", (LPSTR)pDestEndpoint->sName);
#endif

				for (j = 0; j < m_Endpoints.GetCount(); j++)
					if (m_Endpoints[j].bLocalMachine)
						{
						//	If we have no update entries, then skip.

						if (!pDestEndpoint->bFullUpdate
								&& UpdatePayloads[j].GetElement(STR_ENTRIES).GetCount() == 0)
							continue;

#ifdef DEBUG_MNEMOSYNTH
						printf("[CMnemosynthDb::GenerateDelta]: Updates from %s\n", (LPSTR)m_Endpoints[j].sName);
#endif

						//	Add an update entry

						if (pUpdate == NULL)
							{
							pUpdate = retUpdates->Insert();
							pUpdate->sDestEndpoint = pDestEndpoint->sName;
							}

						if (pDestEndpoint->bFullUpdate)
							pUpdate->Payloads.Insert(FullPayloads[j]);
						else
							pUpdate->Payloads.Insert(UpdatePayloads[j]);
						}
				}
			}

		//	Local updates

		*retdLocalUpdates = UpdatePayloads[0];
		}

	//	Reset

	for (i = 0; i < m_Endpoints.GetCount(); i++)
		{
		m_Endpoints[i].dwSeqSent = m_Endpoints[i].dwSeqRecv;
		m_Endpoints[i].bFullUpdate = false;
		}

	m_ModifiedEvent.Reset();
	}
Example #13
0
void CArchonProcess::CollectGarbage (void)

//	CollectGarbage
//
//	Collects garbage

	{
	CString sTask;

	try 
		{
		int i;

		//	Compute how long it's been since we last collected garbage

		DWORD dwStart = sysGetTickCount();
		DWORD dwTimeSinceLastCollection = dwStart - m_dwLastGarbageCollect;

		//	If it has been less than a certain time, then only collect garbage if
		//	all engines are idle.

		if (dwTimeSinceLastCollection < MAX_GARBAGE_COLLECT_WAIT)
			{
			//	Check to see if engines are idle

			bool bEnginesIdle = true;
			for (i = 0; i < m_Engines.GetCount(); i++)
				if (!m_Engines[i].pEngine->IsIdle())
					{
					bEnginesIdle = false;
					break;
					}

			//	If the engines are busy, then check to see if we have enough
			//	memory to wait some more.

			if (!bEnginesIdle)
				{
				CProcess CurrentProc;
				CurrentProc.CreateCurrentProcess();
				CProcess::SMemoryInfo MemoryInfo;
				if (!CurrentProc.GetMemoryInfo(&MemoryInfo))
					{
					LogBlackBox(ERR_CANT_GET_MEMORY_INFO);
					return;
					}

				//	If we have enough memory, then wait to collect garbage

				if (MemoryInfo.dwCurrentAlloc < MAX_GARBAGE_COLLECT_MEMORY)
					return;

				//	Warning that we're running out of memory

				LogBlackBox(ERR_MEMORY_WARNING);
				}
			}

		//	Collect

	#ifdef DEBUG_GARBAGE_COLLECTION
		printf("[%s] Collecting garbage.\n", (LPSTR)m_sName);
	#endif

		m_dwLastGarbageCollect = dwStart;

		m_RunEvent.Reset();
		m_PauseEvent.Set();

		//	Keep track of how long each engine takes to pause (for diagnostic
		//	purposes).

		TArray<DWORD> PauseTime;
		PauseTime.InsertEmpty(m_Engines.GetCount());

		//	Some engines still need an explicit call (because they don't have
		//	their own main thread).

		for (i = 0; i < m_Engines.GetCount(); i++)
			m_Engines[i].pEngine->SignalPause();

		//	Wait for the engines to stop

		for (i = 0; i < m_Engines.GetCount(); i++)
			{
			DWORD dwStart = sysGetTickCount();

			m_Engines[i].pEngine->WaitForPause();

			PauseTime[i] = sysGetTicksElapsed(dwStart);
			}

		//	Wait for our threads to stop

		m_EventThread.WaitForPause();
		m_ImportThread.WaitForPause();

		//	Now we ask all engines to mark their data in use

		for (i = 0; i < m_Engines.GetCount(); i++)
			{
			sTask = strPattern("Marking data: %s engine.", m_Engines[i].pEngine->GetName());
			m_Engines[i].pEngine->Mark();
			}

		//	Now we mark our own structures

		sTask = STR_MARKING_MNEMOSYNTH;
		m_MnemosynthDb.Mark();

		sTask = STR_MARKING_EVENT_THREAD;
		m_EventThread.Mark();

		sTask = STR_MARKING_IMPORT_THREAD;
		m_ImportThread.Mark();

		//	Now we sweep all unused

		sTask = STR_MARK_AND_SWEEP;

		DWORD dwSweepStart = sysGetTickCount();
		CDatum::MarkAndSweep();
		DWORD dwSweepTime = sysGetTickCount() - dwSweepStart;

		sTask = NULL_STR;

		//	Now we start all engines up again

		m_PauseEvent.Reset();
		m_RunEvent.Set();

		//	If garbage collection took too long, then we need to log it.

		DWORD dwTime = sysGetTickCount() - dwStart;
		if (dwTime >= 500)
			{
			//	Log each engine that took too long

			for (i = 0; i < m_Engines.GetCount(); i++)
				if (PauseTime[i] >= 500)
					Log(MSG_LOG_INFO, strPattern(STR_ENGINE_PAUSE_TIME, m_Engines[i].pEngine->GetName(), PauseTime[i] / 1000, (PauseTime[i] % 1000) / 10));

			//	Log overall time

			Log(MSG_LOG_INFO, strPattern(STR_GARBAGE_COLLECTION, 
					dwTime / 1000, (dwTime % 1000) / 10,
					dwSweepTime / 1000, (dwSweepTime % 1000) / 10));
			}
		}
	catch (...)
		{
		if (sTask.IsEmpty())
			CriticalError(ERR_CRASH_IN_COLLECT_GARBAGE);
		else
			CriticalError(strPattern("CRASH: %s", sTask));
		}
	}
Example #14
0
void GenerateImageChart (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	int i;

	enum OrderTypes
		{
		orderSmallest = 1,
		orderLargest = 2,
		orderName = 3,
		orderLevel = 4,
		orderSovereign = 5,
		orderManufacturer = 6,
		};

	//	Item criteria

	bool bHasItemCriteria;
	CString sCriteria;
	CItemCriteria ItemCriteria;
	if (bHasItemCriteria = pCmdLine->FindAttribute(CONSTLIT("itemCriteria"), &sCriteria))
		CItem::ParseCriteria(sCriteria, &ItemCriteria);
	else
		CItem::InitCriteriaAll(&ItemCriteria);

	//	Get the criteria from the command line.

	CDesignTypeCriteria Criteria;
	if (pCmdLine->FindAttribute(CONSTLIT("criteria"), &sCriteria))
		{
		if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR)
			{
			printf("ERROR: Unable to parse criteria.\n");
			return;
			}
		}
	else if (bHasItemCriteria)
		{
		if (CDesignTypeCriteria::ParseCriteria(CONSTLIT("i"), &Criteria) != NOERROR)
			{
			printf("ERROR: Unable to parse criteria.\n");
			return;
			}
		}
	else
		{
		printf("ERROR: Expected criteria.\n");
		return;
		}

	bool bAll = pCmdLine->GetAttributeBool(CONSTLIT("all"));

	//	Options

	bool bTextBoxesOnly = pCmdLine->GetAttributeBool(CONSTLIT("textBoxesOnly"));
	bool bFieldUNID = pCmdLine->GetAttributeBool(CONSTLIT("unid"));

	//	Figure out what order we want

	CString sOrder = pCmdLine->GetAttribute(CONSTLIT("sort"));
	int iOrder;
	if (strEquals(sOrder, CONSTLIT("smallest")))
		iOrder = orderSmallest;
	else if (strEquals(sOrder, CONSTLIT("largest")))
		iOrder = orderLargest;
	else if (strEquals(sOrder, CONSTLIT("level")))
		iOrder = orderLevel;
	else if (strEquals(sOrder, CONSTLIT("sovereign")))
		iOrder = orderSovereign;
	else if (strEquals(sOrder, CONSTLIT("manufacturer")))
		iOrder = orderManufacturer;
	else
		iOrder = orderName;

	bool b3DGrid = pCmdLine->GetAttributeBool(CONSTLIT("3DGrid"));
	bool bDockingPorts = pCmdLine->GetAttributeBool(CONSTLIT("portPos"));
	bool bDevicePos = pCmdLine->GetAttributeBool(CONSTLIT("devicePos"));

	//	Image size

	int cxDesiredWidth;
	if (pCmdLine->FindAttributeInteger(CONSTLIT("width"), &cxDesiredWidth))
		cxDesiredWidth = Max(512, cxDesiredWidth);
	else
		cxDesiredWidth = 1280;

	//	Spacing

	int cxSpacing = pCmdLine->GetAttributeInteger(CONSTLIT("xSpacing"));
	int cxExtraMargin = pCmdLine->GetAttributeInteger(CONSTLIT("xMargin"));
	int cxImageMargin = 2 * pCmdLine->GetAttributeInteger(CONSTLIT("xImageMargin"));

	//	Font for text

	CString sTypeface;
	int iSize;
	bool bBold;
	bool bItalic;

	if (!CG16bitFont::ParseFontDesc(pCmdLine->GetAttribute(CONSTLIT("font")),
			&sTypeface,
			&iSize,
			&bBold,
			&bItalic))
		{
		sTypeface = CONSTLIT("Arial");
		iSize = 10;
		bBold = false;
		bItalic = false;
		}

	CG16bitFont NameFont;
	NameFont.Create(sTypeface, -PointsToPixels(iSize), bBold, bItalic);
	CG32bitPixel rgbNameColor = CG32bitPixel(255, 255, 255);

	//	Rotation

	int iRotation = pCmdLine->GetAttributeInteger(CONSTLIT("rotation"));

	//	Output file

	CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output"));
	if (!sFilespec.IsBlank())
		sFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp"));

	//	Generate a sorted table of types

	TSortMap<CString, SEntryDesc> Table;
	for (i = 0; i < Universe.GetDesignTypeCount(); i++)
		{
		CDesignType *pType = Universe.GetDesignType(i);
		SEntryDesc NewEntry;

		//	Make sure we match the criteria

		if (!pType->MatchesCriteria(Criteria))
			continue;

		//	Figure stuff stuff out based on the specific design type

		switch (pType->GetType())
			{
			case designItemType:
				{
				CItemType *pItemType = CItemType::AsType(pType);
				CItem Item(pItemType, 1);

				//	Skip if not in item criteria

				if (!Item.MatchesCriteria(ItemCriteria))
					continue;

				//	Skip virtual classes

				if (pItemType->IsVirtual())
					continue;

				//	Initialize the entry

				NewEntry.pType = pType;
				NewEntry.sName = pItemType->GetNounPhrase(0);
				NewEntry.pImage = &pItemType->GetImage();
				NewEntry.iSize = RectWidth(NewEntry.pImage->GetImageRect());
				break;
				}

			case designShipClass:
				{
				CShipClass *pClass = CShipClass::AsType(pType);

				//	Skip non-generic classess

				if (!bAll && !pClass->HasLiteralAttribute(CONSTLIT("genericClass")))
					continue;

				//	Initialize the entry

				NewEntry.pType = pType;
				NewEntry.sName = pClass->GetNounPhrase(0);
				NewEntry.iSize = RectWidth(pClass->GetImage().GetImageRect());
				NewEntry.pImage = &pClass->GetImage();
				NewEntry.iRotation = pClass->Angle2Direction(iRotation);
				NewEntry.sSovereignName = (pClass->GetDefaultSovereign() ? pClass->GetDefaultSovereign()->GetTypeNounPhrase() : NULL_STR);
				break;
				}

			case designStationType:
				{
				CStationType *pStationType = CStationType::AsType(pType);

				//	Skip generic classes

				if (!bAll && !pStationType->HasLiteralAttribute(CONSTLIT("generic")))
					continue;

				NewEntry.pType = pType;
				NewEntry.sName = pStationType->GetNounPhrase(0);
				NewEntry.iSize = pStationType->GetSize();
				NewEntry.sSovereignName = (pStationType->GetSovereign() ? pStationType->GetSovereign()->GetTypeNounPhrase() : NULL_STR);

				InitStationTypeImage(NewEntry, pStationType);

				break;
				}

			default:
				//	Don't know how to handle this type
				continue;
				break;
			}

		//	Adjust name

		if (bFieldUNID)
			NewEntry.sName = strPatternSubst(CONSTLIT("%s (%x)"), NewEntry.sName, NewEntry.pType->GetUNID());

		//	Compute the sort key

		char szBuffer[1024];
		switch (iOrder)
			{
			case orderLargest:
				wsprintf(szBuffer, "%09d%s%x",
						1000000 - NewEntry.iSize,
						NewEntry.sName.GetASCIIZPointer(),
						pType->GetUNID());
				break;

			case orderLevel:
				wsprintf(szBuffer, "%09d%s%x",
						pType->GetLevel(),
						NewEntry.sName.GetASCIIZPointer(),
						pType->GetUNID());
				break;

			case orderSmallest:
				wsprintf(szBuffer, "%09d%s%x",
						NewEntry.iSize,
						NewEntry.sName.GetASCIIZPointer(),
						pType->GetUNID());
				break;

			case orderSovereign:
				wsprintf(szBuffer, "%s|%s|%x", NewEntry.sSovereignName.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID());
				NewEntry.sCategorize = NewEntry.sSovereignName;
				break;

			case orderManufacturer:
				{
				CString sManufacturer = NewEntry.pType->GetPropertyString(CONSTLIT("manufacturer"));
				wsprintf(szBuffer, "%s|%s|%x", sManufacturer.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID());
				NewEntry.sCategorize = sManufacturer;
				break;
				}

			default:
				wsprintf(szBuffer, "%s%x", NewEntry.sName.GetASCIIZPointer(), pType->GetUNID());
				break;
			}

		//	Add to list

		Table.Insert(CString(szBuffer), NewEntry);
		}

	//	Allocate an arranger that tracks where to paint each world.

	CImageArranger Arranger;

	//	Settings for the overall arrangement

	CImageArranger::SArrangeDesc Desc;
	Desc.cxDesiredWidth = Max(512, cxDesiredWidth - (2 * (cxSpacing + cxExtraMargin)));
	Desc.cxSpacing = cxSpacing;
	Desc.cxExtraMargin = cxExtraMargin;
	Desc.pHeader = &NameFont;

	//	Generate a table of cells for the arranger

	TArray<CCompositeImageSelector> Selectors;
	Selectors.InsertEmpty(Table.GetCount());

	CString sLastCategory;
	TArray<CImageArranger::SCellDesc> Cells;
	for (i = 0; i < Table.GetCount(); i++)
		{
		SEntryDesc &Entry = Table[i];

		CImageArranger::SCellDesc *pNewCell = Cells.Insert();
		pNewCell->cxWidth = (Entry.pImage ? RectWidth(Entry.pImage->GetImageRect()) : 0) + cxImageMargin;
		pNewCell->cyHeight = (Entry.pImage ? RectHeight(Entry.pImage->GetImageRect()) : 0) + cxImageMargin;
		pNewCell->sText = Entry.sName;

		if (!strEquals(sLastCategory, Entry.sCategorize))
			{
			sLastCategory = Entry.sCategorize;
			pNewCell->bStartNewRow = true;
			}
		}

	//	Arrange

	Arranger.ArrangeByRow(Desc, Cells);

	//	Create a large image

	CG32bitImage Output;
	int cxWidth = Max(cxDesiredWidth, Arranger.GetWidth());
	int cyHeight = Arranger.GetHeight();
	Output.Create(cxWidth, cyHeight);
	printf("Creating %dx%d image.\n", cxWidth, cyHeight);

	//	Paint the images

	for (i = 0; i < Table.GetCount(); i++)
		{
		SEntryDesc &Entry = Table[i];

		int x = Arranger.GetX(i);
		int y = Arranger.GetY(i);

		//	Paint

		if (x != -1)
			{
			int xCenter = x + (Arranger.GetWidth(i) / 2);
			int yCenter = y + (Arranger.GetHeight(i) / 2);

			int xOffset;
			int yOffset;
			Entry.pImage->GetImageOffset(0, Entry.iRotation, &xOffset, &yOffset);
			int cxImage = RectWidth(Entry.pImage->GetImageRect());
			int cyImage = RectHeight(Entry.pImage->GetImageRect());

			//	Paint image

			if (!bTextBoxesOnly && Entry.pImage)
				{
				Entry.pImage->PaintImageUL(Output,
						x + (Arranger.GetWidth(i) - cxImage) / 2,
						y + (Arranger.GetHeight(i) - cyImage) / 2,
						0,
						Entry.iRotation);
				}

			//	Paint type specific stuff

			switch (Entry.pType->GetType())
				{
				case designStationType:
					{
					CStationType *pStationType = CStationType::AsType(Entry.pType);
                    int xStationCenter = xCenter - xOffset;
                    int yStationCenter = yCenter - yOffset;

					if (bDockingPorts)
						pStationType->PaintDockPortPositions(Output, xStationCenter, yStationCenter);

					if (bDevicePos)
						pStationType->PaintDevicePositions(Output, xStationCenter, yStationCenter);

                    //  If we have docking or device positions, mark the center of the station

                    if (bDockingPorts || bDevicePos)
                        {
                        const int LINE_HALF_LENGTH = 24;
                        const CG32bitPixel RGB_CENTER_CROSS(255, 255, 0);
                        Output.DrawLine(xStationCenter - LINE_HALF_LENGTH, yStationCenter, xStationCenter + LINE_HALF_LENGTH, yStationCenter, 1, RGB_CENTER_CROSS);
                        Output.DrawLine(xStationCenter, yStationCenter - LINE_HALF_LENGTH, xStationCenter, yStationCenter + LINE_HALF_LENGTH, 1, RGB_CENTER_CROSS);
                        }
					break;
					}
				}

			//	Paint the 3D grid, if necessary

			if (b3DGrid)
				{
				int iScale = Entry.pImage->GetImageViewportSize();
				Metric rMaxRadius = g_KlicksPerPixel * cxImage * 0.5;
				const Metric rGridSize = LIGHT_SECOND;

				Metric rRadius;
				for (rRadius = rGridSize; rRadius <= rMaxRadius; rRadius += rGridSize)
					{
					int iRadius = (int)((rRadius / g_KlicksPerPixel) + 0.5);
					const int iGridAngle = 8;
					int iPrevAngle = 0;
					int iAngle;
					for (iAngle = iGridAngle; iAngle <= 360; iAngle += iGridAngle)
						{
						int xFrom, yFrom;
						C3DConversion::CalcCoord(iScale, iPrevAngle, iRadius, 0, &xFrom, &yFrom);

						int xTo, yTo;
						C3DConversion::CalcCoord(iScale, iAngle, iRadius, 0, &xTo, &yTo);

						Output.DrawLine(xFrom + xCenter, yFrom + yCenter, xTo + xCenter, yTo + yCenter, 1, CG32bitPixel(255, 255, 0));

						iPrevAngle = iAngle;
						}
					}
				}

			//	Paint name

			int xText = Arranger.GetTextX(i);
			int yText = Arranger.GetTextY(i);
			if (xText != -1)
				{
				if (bTextBoxesOnly)
					Output.Fill(xText, yText, Arranger.GetTextWidth(i), Arranger.GetTextHeight(i), 0xffff);

				if (!bTextBoxesOnly)
					{
					Output.FillColumn(xCenter,
							y + Arranger.GetHeight(i),
							yText - (y + Arranger.GetHeight(i)),
							rgbNameColor);

					NameFont.DrawText(Output,
							xText,
							yText,
							rgbNameColor,
							Entry.sName);
					}
				}
			}
		}

	//	Write to file or clipboard

	OutputImage(Output, sFilespec);
	}
Example #15
0
void CRayEffectPainter::CalcIntermediates (void)

//	CalcIntermediates
//
//	Calculate intermediate values used for painting.

	{
	int i, v, w;

	if (!m_bInitialized)
		{
		enum EColorTypes
			{
			colorNone,
			colorGlow,
			};

		enum EOpacityTypes
			{
			opacityNone,
			opacityGlow,
			opacityGrainy,
			opacityTaperedGlow,
			};

		enum EWidthAdjTypes
			{
			widthAdjNone,
			widthAdjBlob,
			widthAdjDiamond,
			widthAdjJagged,
			widthAdjOval,
			widthAdjTapered,
			widthAdjCone,
			};

		EColorTypes iColorTypes = colorNone;
		EOpacityTypes iOpacityTypes = opacityNone;
		EWidthAdjTypes iWidthAdjType = widthAdjNone;
		EWidthAdjTypes iReshape = widthAdjNone;
		EOpacityTypes iTexture = opacityNone;

		m_iWidthCount = m_iWidth;
		m_iLengthCount = 2 * m_iLength;

		//	Every combination requires a slightly different set up

		switch (m_iShape)
			{
			case shapeCone:
				switch (m_iStyle)
					{
					case styleBlob:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjBlob;
						iReshape = widthAdjCone;
						break;

					case styleGlow:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjCone;
						break;

					case styleGrainy:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjCone;
						iTexture = opacityGrainy;
						break;

					case styleJagged:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjJagged;
						iReshape = widthAdjCone;
						break;
					}
				break;

			case shapeDiamond:
				switch (m_iStyle)
					{
					case styleBlob:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjBlob;
						iReshape = widthAdjDiamond;
						break;

					case styleGlow:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjDiamond;
						break;

					case styleGrainy:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjDiamond;
						iTexture = opacityGrainy;
						break;

					case styleJagged:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjJagged;
						iReshape = widthAdjDiamond;
						break;
					}
				break;

			case shapeOval:
				switch (m_iStyle)
					{
					case styleBlob:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjBlob;
						iReshape = widthAdjOval;
						break;

					case styleGlow:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjOval;
						break;

					case styleGrainy:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjOval;
						iTexture = opacityGrainy;
						break;

					case styleJagged:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjJagged;
						iReshape = widthAdjOval;
						break;
					}
				break;

			case shapeStraight:
				switch (m_iStyle)
					{
					case styleBlob:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityGlow;
						iWidthAdjType = widthAdjBlob;
						break;

					case styleGlow:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityGlow;
						break;

					case styleGrainy:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityGlow;
						iTexture = opacityGrainy;
						break;

					case styleJagged:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityGlow;
						iWidthAdjType = widthAdjJagged;
						break;
					}
				break;

			case shapeTapered:
				switch (m_iStyle)
					{
					case styleBlob:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjBlob;
						iReshape = widthAdjTapered;
						break;

					case styleGlow:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjTapered;
						break;

					case styleGrainy:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjTapered;
						iTexture = opacityGrainy;
						break;

					case styleJagged:
						iColorTypes = colorGlow;
						iOpacityTypes = opacityTaperedGlow;
						iWidthAdjType = widthAdjJagged;
						iReshape = widthAdjTapered;
						break;
					}
				break;
			}

		//	Full color map

		switch (iColorTypes)
			{
			case colorGlow:
				{
				m_ColorMap.InsertEmpty(1);
				m_ColorMap[0].InsertEmpty(m_iWidthCount);

				//	The center blends towards white

				WORD wCenter = CG16bitImage::BlendPixel(m_wPrimaryColor, CG16bitImage::RGBValue(255, 255, 255), (DWORD)(255.0 * Min(50, m_iIntensity) / 50.0));

				int iBrightPoint = (int)(BRIGHT_FACTOR * m_iWidthCount * m_iIntensity);
				for (i = 0; i < iBrightPoint; i++)
					m_ColorMap[0][i] = wCenter;

				//	The rest fades (linearly) from primary color to secondary color

				Metric rFadeInc = (m_iWidthCount > 0 ? (1.0 / (m_iWidthCount - iBrightPoint)) : 0.0);
				Metric rFade = 1.0;
				for (i = iBrightPoint; i < m_iWidthCount; i++, rFade -= rFadeInc)
					m_ColorMap[0][i] = CG16bitImage::BlendPixel(m_wSecondaryColor, m_wPrimaryColor, (DWORD)(255.0 * rFade));

				break;
				}
			}

		//	Full opacity

		switch (iOpacityTypes)
			{
			case opacityGlow:
				{
				m_OpacityMap.InsertEmpty(1);
				m_OpacityMap[0].InsertEmpty(m_iWidthCount);

				//	From center to peak we have solid opacity

				int iPeakPoint = (int)(SOLID_FACTOR * m_iIntensity * m_iWidthCount);
				for (i = 0; i < iPeakPoint; i++)
					m_OpacityMap[0][i] = 255;

				//	We decay exponentially to edge

				Metric rGlowLevel = MIN_GLOW_LEVEL + (m_iIntensity * GLOW_FACTOR);
				Metric rGlowInc = (m_iWidthCount > 0 ? (1.0 / (m_iWidthCount - iPeakPoint)) : 0.0);
				Metric rGlow = 1.0;
				for (i = iPeakPoint; i < m_iWidthCount; i++, rGlow -= rGlowInc)
					m_OpacityMap[0][i] = (int)(255.0 * rGlowLevel * rGlow * rGlow);

				break;
				}

			case opacityTaperedGlow:
				{
				m_OpacityMap.InsertEmpty(m_iLengthCount);
				for (i = 0; i < m_iLengthCount; i++)
					m_OpacityMap[i].InsertEmpty(m_iWidthCount);

				//	From center to peak we have solid opacity

				int iPeakPoint = (int)(SOLID_FACTOR * m_iIntensity * m_iWidthCount);

				//	After the 1/3 point start fading out (linearly)

				int iFadePoint = m_iLengthCount / TAPER_FRACTION;
				Metric rTaperInc = (m_iLengthCount > 0 ? (1.0 / (m_iLengthCount - iFadePoint)) : 0.0);

				//	From center to peak we have solid opacity plus taper

				for (w = 0; w < iPeakPoint; w++)
					{
					for (v = 0; v < iFadePoint; v++)
						m_OpacityMap[v][w] = 255;

					Metric rTaper = 1.0;
					for (v = iFadePoint; v < m_iLengthCount; v++, rTaper -= rTaperInc)
						m_OpacityMap[v][w] = (int)(255.0 * rTaper);
					}

				//	The glow around the peak decays exponentially

				Metric rGlowLevel = MIN_GLOW_LEVEL + (m_iIntensity * GLOW_FACTOR);
				Metric rGlowInc = (m_iWidthCount > 0 ? (1.0 / (m_iWidthCount - iPeakPoint)) : 0.0);
				Metric rGlow = 1.0;
				for (w = iPeakPoint; w < m_iWidthCount; w++, rGlow -= rGlowInc)
					{
					Metric rGlowPart = rGlowLevel * rGlow * rGlow;

					for (v = 0; v < iFadePoint; v++)
						m_OpacityMap[v][w] = (int)(255.0 * rGlowPart);

					Metric rTaper = 1.0;
					for (v = iFadePoint; v < m_iLengthCount; v++, rTaper -= rTaperInc)
						m_OpacityMap[v][w] = (int)(255.0 * rGlowPart * rTaper);
					}

				break;
				}
			}

		//	Width adjustments

		switch (iWidthAdjType)
			{
			case widthAdjBlob:
				{
				m_WidthAdjTop.InsertEmpty(m_iLengthCount);
				m_WidthAdjBottom.InsertEmpty(m_iLengthCount);

				//	Initialize jagged envelope

				CalcWaves(m_WidthAdjTop, BLOB_WAVE_SIZE, m_iWidth * WAVY_WAVELENGTH_FACTOR);
				CalcWaves(m_WidthAdjBottom, BLOB_WAVE_SIZE, m_iWidth * WAVY_WAVELENGTH_FACTOR);

				break;
				}

			case widthAdjCone:
				{
				m_WidthAdjTop.InsertEmpty(m_iLengthCount);

				CalcCone(m_WidthAdjTop);
				m_WidthAdjBottom = m_WidthAdjTop;

				break;
				}

			case widthAdjDiamond:
				{
				m_WidthAdjTop.InsertEmpty(m_iLengthCount);

				CalcDiamond(m_WidthAdjTop);
				m_WidthAdjBottom = m_WidthAdjTop;

				break;
				}

			case widthAdjJagged:
				{
				m_WidthAdjTop.InsertEmpty(m_iLengthCount);
				m_WidthAdjBottom.InsertEmpty(m_iLengthCount);

				//	Initialize jagged envelope

				CalcWaves(m_WidthAdjTop, JAGGED_AMPLITUDE, m_iWidth * JAGGED_WAVELENGTH_FACTOR);
				CalcWaves(m_WidthAdjBottom, JAGGED_AMPLITUDE, m_iWidth * JAGGED_WAVELENGTH_FACTOR);

				break;
				}

			case widthAdjOval:
				{
				m_WidthAdjTop.InsertEmpty(m_iLengthCount);

				CalcOval(m_WidthAdjTop);
				m_WidthAdjBottom = m_WidthAdjTop;

				break;
				}

			case widthAdjTapered:
				{
				m_WidthAdjTop.InsertEmpty(m_iLengthCount);

				CalcTaper(m_WidthAdjTop);
				m_WidthAdjBottom = m_WidthAdjTop;

				break;
				}
			}

		//	Adjust shape

		switch (iReshape)
			{
			case widthAdjCone:
				{
				TArray<Metric> TaperAdj;
				TaperAdj.InsertEmpty(m_iLengthCount);
				CalcCone(TaperAdj);

				for (i = 0; i < m_iLengthCount; i++)
					{
					m_WidthAdjTop[i] *= TaperAdj[i];
					m_WidthAdjBottom[i] *= TaperAdj[i];
					}
				break;
				}

			case widthAdjDiamond:
				{
				TArray<Metric> TaperAdj;
				TaperAdj.InsertEmpty(m_iLengthCount);
				CalcDiamond(TaperAdj);

				for (i = 0; i < m_iLengthCount; i++)
					{
					m_WidthAdjTop[i] *= TaperAdj[i];
					m_WidthAdjBottom[i] *= TaperAdj[i];
					}
				break;
				}

			case widthAdjOval:
				{
				TArray<Metric> TaperAdj;
				TaperAdj.InsertEmpty(m_iLengthCount);
				CalcOval(TaperAdj);

				for (i = 0; i < m_iLengthCount; i++)
					{
					m_WidthAdjTop[i] *= TaperAdj[i];
					m_WidthAdjBottom[i] *= TaperAdj[i];
					}
				break;
				}

			case widthAdjTapered:
				{
				TArray<Metric> TaperAdj;
				TaperAdj.InsertEmpty(m_iLengthCount);
				CalcTaper(TaperAdj);

				for (i = 0; i < m_iLengthCount; i++)
					{
					m_WidthAdjTop[i] *= TaperAdj[i];
					m_WidthAdjBottom[i] *= TaperAdj[i];
					}
				break;
				}
			}

		//	Apply texture

		switch (iTexture)
			{
			case opacityGrainy:
				{
				const int DIAMETER = 11;
				const int START = -(DIAMETER / 2);
				const int CENTER_X = (DIAMETER / 2);
				const int CENTER_Y = (DIAMETER / 2);
				const Metric RADIUS = (DIAMETER / 2.0);

				Metric Adj[DIAMETER][DIAMETER];
				for (v = 0; v < DIAMETER; v++)
					for (w = 0; w < DIAMETER; w++)
						{
						int vDiff = v - CENTER_X;
						int wDiff = w - CENTER_Y;

						Metric rDist = sqrt((Metric)(vDiff * vDiff + wDiff * wDiff)) / RADIUS;
						Adj[v][w] = Max(0.0, 1.0 - rDist);
						}

				int iPeakPoint = (int)(SOLID_FACTOR * m_iIntensity * m_iWidthCount);

				int iGrainCount = (int)(4 * sqrt((Metric)m_iLength * m_iWidth));
				for (i = 0; i < iGrainCount; i++)
					{
					int vCount = m_OpacityMap.GetCount();
					int wCount = m_OpacityMap[0].GetCount();
					int vCenter = mathRandom(0, vCount - 1);
					int wCenter = mathRandom(0, wCount - 1);

					Metric rCenter = GRAINY_SIGMA * mathRandomGaussian();

					for (v = 0; v < DIAMETER; v++)
						{
						int vPos = START + vCenter + v;
						if (vPos < 0 || vPos >= vCount)
							continue;

						for (w = 0; w < DIAMETER; w++)
							{
							int wPos = START + wCenter + w;
							if (wPos < iPeakPoint || wPos >= wCount)
								continue;

							m_OpacityMap[vPos][wPos] = (BYTE)Min(Max(0, (int)((Metric)m_OpacityMap[vPos][wPos] * (1.0 + rCenter * Adj[v][w]))), 255);
							}
						}
					}
				
				break;
				}
			}

		//	Done

		m_bInitialized = true;
		}
	}
Example #16
0
void CGSelectorArea::SetRegionsFromMiscDevices (CSpaceObject *pSource)

//	SetRegionsFromMiscDevices
//
//	Generates regions showing misc devices (including reactor, drive, 
//	and cargo hold).

	{
	int i;
	ASSERT(pSource);
	if (pSource == NULL)
		return;

	CShip *pShip = pSource->AsShip();
	if (pShip == NULL)
		return;

	CShipClass *pClass = pShip->GetClass();

	//	Keep track of layouts that have already been used.

	TArray<bool> SlotStatus;
	SlotStatus.InsertEmpty(MISC_DEVICES_LAYOUT_COUNT);
	for (i = 0; i < MISC_DEVICES_LAYOUT_COUNT; i++)
		SlotStatus[i] = true;

	//	Reserve the slots for named device types

	SlotStatus[REACTOR_SLOT_INDEX] = false;
	SlotStatus[DRIVE_SLOT_INDEX] = false;
	SlotStatus[CARGO_SLOT_INDEX] = false;

	//	Count the number of miscellaneous devices with 0
	//	slots (because we may need to bump them).

	int iSlottedDevices = 0;
	int iNonSlotDevices = 0;
	for (i = 0; i < pShip->GetDeviceCount(); i++)
		{
		CInstalledDevice *pDevice = pShip->GetDevice(i);
		if (pDevice->IsEmpty() || pDevice->GetCategory() != itemcatMiscDevice)
			continue;

		if (pDevice->GetClass()->GetSlotsRequired() > 0)
			iSlottedDevices++;
		else
			iNonSlotDevices++;
		}

	//	We try to fit all other devices (and placeholders) before we add a
	//	non-slotted device.

	int iNonSlotDeviceSlotsAvail = Max(0, MISC_DEVICES_LAYOUT_COUNT - 4 - iSlottedDevices);

	//	Create a region for each device.

	int iIndex = -1;
	bool bHasReactor = false;
	bool bHasDrive = false;
	bool bHasCargo = false;
	int iNextUnamedSlot = FIRST_UNNAMED_SLOT_INDEX;
	for (i = 0; i < pShip->GetDeviceCount(); i++)
		{
		CInstalledDevice *pDevice = pShip->GetDevice(i);
		if (pDevice->IsEmpty())
			continue;

		//	Figure out the layout descriptor

		iIndex = -1;
		const SLayoutDesc *pLayout = NULL;
		switch (pDevice->GetCategory())
			{
			case itemcatCargoHold:
				pLayout = &g_MiscDevicesLayout[CARGO_SLOT_INDEX];
				bHasCargo = true;
				break;

			case itemcatDrive:
				pLayout = &g_MiscDevicesLayout[DRIVE_SLOT_INDEX];
				bHasDrive = true;
				break;

			case itemcatMiscDevice:
				{
				//	If this is a 0-slot device and we have no more room for
				//	0-slot devices, then we skip it.

				if (pDevice->GetClass()->GetSlotsRequired() == 0
						&& iNonSlotDeviceSlotsAvail <= 0)
					continue;

				//	If the device already has a position index, then use that (assuming
				//	it's free).

				iIndex = pDevice->GetSlotPosIndex();
				if (iIndex < 0 || iIndex >= SlotStatus.GetCount() || !SlotStatus[iIndex])
					iIndex = -1;

				//	If we don't have an assigned slot, figure it out.

				if (iIndex == -1)
					{
					//	Look for a new position

					if (!FindLayoutForPos(pDevice->GetPosOffset(pShip), SlotStatus, &iIndex))
						continue;

					//	Remember so we stay in this location.

					pDevice->SetSlotPosIndex(iIndex);
					}

				//	Remember the layout and mark it as used.

				pLayout = &g_MiscDevicesLayout[iIndex];
				SlotStatus[iIndex] = false;
				break;
				}

			case itemcatReactor:
				pLayout = &g_MiscDevicesLayout[REACTOR_SLOT_INDEX];
				bHasReactor = true;
				break;
			}

		//	Create the region (but only if we have a layout position
		//	for it).

		if (pLayout)
			{
			SEntry *pEntry = m_Regions.Insert();
			pEntry->iType = typeInstalledItem;
			pEntry->pItemCtx = new CItemCtx(pShip, pDevice);

			pEntry->iSlotPosIndex = iIndex;
			pEntry->rcRect.left = pLayout->xLeft;
			pEntry->rcRect.top = pLayout->yTop;
			pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
			pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
			}
		}

	//	Add empty slots, if necessary

	if (!bHasReactor)
		{
		const SLayoutDesc *pLayout = &g_MiscDevicesLayout[REACTOR_SLOT_INDEX];

		SEntry *pEntry = m_Regions.Insert();
		pEntry->iType = typeEmptySlot;
		pEntry->iSlotType = devReactor;

		pEntry->rcRect.left = pLayout->xLeft;
		pEntry->rcRect.top = pLayout->yTop;
		pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
		pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
		}

	if (!bHasDrive)
		{
		const SLayoutDesc *pLayout = &g_MiscDevicesLayout[DRIVE_SLOT_INDEX];

		SEntry *pEntry = m_Regions.Insert();
		pEntry->iType = typeEmptySlot;
		pEntry->iSlotType = devDrive;

		pEntry->rcRect.left = pLayout->xLeft;
		pEntry->rcRect.top = pLayout->yTop;
		pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
		pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
		}

	if (!bHasCargo)
		{
		const SLayoutDesc *pLayout = &g_MiscDevicesLayout[CARGO_SLOT_INDEX];

		SEntry *pEntry = m_Regions.Insert();
		pEntry->iType = typeEmptySlot;
		pEntry->iSlotType = devCargo;

		pEntry->rcRect.left = pLayout->xLeft;
		pEntry->rcRect.top = pLayout->yTop;
		pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
		pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
		}

	//	Figure out how many empty weapon slots we should create. We add one 
	//	empty slot for each weapon slot, but we subtract one if we don't have
	//	a launcher and we always have at least 1 empty slot, in case the player
	//	finds a slot-less weapon.

#ifdef SINGLE_FREE_SLOT
	int iEmptySlots = 1;
#else
	int iNonWeaponSlotsInUse;
	int iTotalSlotsInUse = pShip->CalcDeviceSlotsInUse(NULL, &iNonWeaponSlotsInUse);
	int iEmptySlots = Max(1, Min((pClass->GetMaxDevices() - iTotalSlotsInUse), (pClass->GetMaxNonWeapons() - iNonWeaponSlotsInUse)) - (bHasReactor ? 0 : 1) - (bHasDrive ? 0 : 1) - (bHasCargo ? 0 : 1));
#endif

	for (i = 0; i < iEmptySlots; i++)
		{
		if (FindLayoutForPos(CVector(), SlotStatus, &iIndex))
			{
			const SLayoutDesc *pLayout = &g_MiscDevicesLayout[iIndex];

			SEntry *pEntry = m_Regions.Insert();
			pEntry->iType = typeEmptySlot;
			pEntry->iSlotType = devNone;

			pEntry->iSlotPosIndex = iIndex;
			pEntry->rcRect.left = pLayout->xLeft;
			pEntry->rcRect.top = pLayout->yTop;
			pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
			pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;

			SlotStatus[iIndex] = false;
			}
		}
	}
Example #17
0
void CItemList::SortItems (void)

//	SortItems
//
//	Sorts items in order:
//
//	installed/not-installed
//	armor/weapon/device/other

	{
	if (GetCount() == 0)
		return;

	int i;
	CSymbolTable Sort(false, true);

	for (i = 0; i < GetCount(); i++)
		{
		CItem &Item = GetItem(i);
		CItemType *pType = Item.GetType();

		//	All installed items first

		CString sInstalled;
		if (Item.IsInstalled())
			sInstalled = CONSTLIT("0");
		else
			sInstalled = CONSTLIT("1");

		//	Next, sort on category

		CString sCat;
		switch (pType->GetCategory())
			{
			case itemcatWeapon:
			case itemcatLauncher:
				sCat = CONSTLIT("0");
				break;

			case itemcatMissile:
				sCat = CONSTLIT("1");
				break;

			case itemcatShields:
				sCat = CONSTLIT("2");
				break;

			case itemcatReactor:
				sCat = CONSTLIT("3");
				break;

			case itemcatDrive:
				sCat = CONSTLIT("4");
				break;

			case itemcatCargoHold:
				sCat = CONSTLIT("5");
				break;

			case itemcatMiscDevice:
				sCat = CONSTLIT("6");
				break;

			case itemcatArmor:
				sCat = CONSTLIT("7");
				break;

			case itemcatFuel:
			case itemcatUseful:
				sCat = CONSTLIT("8");
				break;

			default:
				sCat = CONSTLIT("9");
			}

		//	Next, sort by install location

		if (Item.IsInstalled())
			sCat.Append(strPatternSubst(CONSTLIT("%03d%08x"), Item.GetInstalled(), Item.GetType()->GetUNID()));
		else
			sCat.Append(CONSTLIT("99900000000"));

		//	Within category, sort by level (highest first)

		sCat.Append(strPatternSubst(CONSTLIT("%02d"), MAX_ITEM_LEVEL - Item.GetType()->GetApparentLevel()));

		//	Enhanced items before others

		if (Item.IsEnhanced())
			sCat.Append(CONSTLIT("0"));
		else if (Item.IsDamaged())
			sCat.Append(CONSTLIT("2"));
		else
			sCat.Append(CONSTLIT("1"));

		CString sName = pType->GetSortName();
		CString sSort = strPatternSubst(CONSTLIT("%s%s%s%d"), sInstalled, sCat, sName, (i * (int)this) % 0x10000);
		Sort.AddEntry(sSort, (CObject *)i);
		}

	//	Allocate a new list

	TArray<CItem *> NewList;
	NewList.InsertEmpty(GetCount());

	//	Move the items from the old list to the new list in the new order

	for (i = 0; i < GetCount(); i++)
		{
		int iOld = (int)Sort.GetValue(i);
		NewList[i] = m_List[iOld];
		}

	//	Swap

	m_List.TakeHandoff(NewList);
	}
void CCompositeEntry::GetImage (const CCompositeImageSelector &Selector, CObjectImageArray *retImage)

//	GetImage
//
//	Fills in the image

	{
	int i;

	//	Null case

	if (m_Layers.GetCount() == 0)
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	//	Get all the layers

	TArray<CObjectImageArray> Result;
	Result.InsertEmpty(m_Layers.GetCount());
	for (i = 0; i < m_Layers.GetCount(); i++)
		m_Layers[i]->GetImage(Selector, &Result[i]);

	//	Create the composited image
	//
	//	First we need to determine the size of the final image, based
	//	on the size and position of each layer.

	int xMin = 0;
	int xMax = 0;
	int yMin = 0;
	int yMax = 0;

	for (i = 0; i < m_Layers.GetCount(); i++)
		{
		CObjectImageArray &LayerImage = Result[i];
		const RECT &rcRect = LayerImage.GetImageRect();

		int xImageOffset = 0;
		int yImageOffset = 0;

		int xMaxImage = (RectWidth(rcRect) / 2) + xImageOffset;
		int xMinImage = xMaxImage - RectWidth(rcRect);
		int yMaxImage = (RectHeight(rcRect) / 2) + yImageOffset;
		int yMinImage = yMaxImage - RectHeight(rcRect);

		xMin = Min(xMin, xMinImage);
		xMax = Max(xMax, xMaxImage);
		yMin = Min(yMin, yMinImage);
		yMax = Max(yMax, yMaxImage);
		}

	//	Create destination image

	int cxWidth = xMax - xMin;
	int cyHeight = yMax - yMin;
	if (cxWidth <= 0 || cyHeight <= 0)
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	CG16bitImage *pComp = new CG16bitImage;
	pComp->CreateBlank(cxWidth, cyHeight, false);
	pComp->SetTransparentColor();

	int xCenter = cxWidth / 2;
	int yCenter = cyHeight / 2;

	//	Blt on the destination

	for (i = 0; i < m_Layers.GetCount(); i++)
		{
		CObjectImageArray &LayerImage = Result[i];
		const RECT &rcRect = LayerImage.GetImageRect();

		//	Paint the image

		LayerImage.PaintImage(*pComp,
				xCenter,
				yCenter,
				0,
				0);
		}

	//	Initialize an image

	RECT rcFinalRect;
	rcFinalRect.left = 0;
	rcFinalRect.top = 0;
	rcFinalRect.right = cxWidth;
	rcFinalRect.bottom = cyHeight;

	CObjectImageArray Comp;
	Comp.Init(pComp, rcFinalRect, 0, 0, true);

	//	Done

	retImage->TakeHandoff(Comp);
	}
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;
	}
Example #20
0
void CGSelectorArea::SetRegionsFromWeapons (CSpaceObject *pSource)

//	SetRegionsFromWeapons
//
//	Creates regions based on installed weapons.

	{
	int i;
	ASSERT(pSource);
	if (pSource == NULL)
		return;

	CShip *pShip = pSource->AsShip();
	if (pShip == NULL)
		return;

	CShipClass *pClass = pShip->GetClass();

	//	Keep track of layouts that have already been used.

	TArray<bool> SlotStatus;
	SlotStatus.InsertEmpty(MISC_DEVICES_LAYOUT_COUNT);
	for (i = 0; i < MISC_DEVICES_LAYOUT_COUNT; i++)
		SlotStatus[i] = true;

	//	If we don't have a launcher, we place the launcher slot first because we
	//	want it to take precedence (position-wise).

	int iIndex;
	bool bHasLauncher = (pShip->GetNamedDevice(devMissileWeapon) != NULL);
	if (!bHasLauncher)
		{
		//	See if we can figure out the proper position for the launcher based
		//	on the class slots

		CVector vLauncherPos;
		SDeviceDesc DeviceDesc;
		if (pClass->FindDeviceSlotDesc(devMissileWeapon, &DeviceDesc))
			vLauncherPos = pClass->GetPosOffset(DeviceDesc.iPosAngle, DeviceDesc.iPosRadius, DeviceDesc.iPosZ, DeviceDesc.b3DPosition);

		//	Find a layout

		if (FindLayoutForPos(vLauncherPos, SlotStatus, &iIndex))
			{
			const SLayoutDesc *pLayout = &g_MiscDevicesLayout[iIndex];

			SEntry *pEntry = m_Regions.Insert();
			pEntry->iType = typeEmptySlot;
			pEntry->iSlotType = devMissileWeapon;

			pEntry->iSlotPosIndex = iIndex;
			pEntry->rcRect.left = pLayout->xLeft;
			pEntry->rcRect.top = pLayout->yTop;
			pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
			pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;

			SlotStatus[iIndex] = false;
			}
		}

	//	Create a region for each weapon.

	for (i = 0; i < pShip->GetDeviceCount(); i++)
		{
		CInstalledDevice *pDevice = pShip->GetDevice(i);
		if (pDevice->IsEmpty() 
				|| (pDevice->GetCategory() != itemcatWeapon 
					&& pDevice->GetCategory() != itemcatLauncher))
			continue;

		if (pDevice->GetCategory() == itemcatLauncher)
			bHasLauncher = true;

		//	If the device already has a position index, then use that (assuming
		//	it's free).

		iIndex = pDevice->GetSlotPosIndex();
		if (iIndex < 0 || iIndex >= SlotStatus.GetCount() || !SlotStatus[iIndex])
			iIndex = -1;

		//	If we don't have an assigned slot, figure it out.

		if (iIndex == -1)
			{
			if (!FindLayoutForPos(pDevice->GetPosOffset(pShip), SlotStatus, &iIndex))
				continue;

			//	Remember so we stay in this location.

			pDevice->SetSlotPosIndex(iIndex);
			}

		//	Create the region

		const SLayoutDesc *pLayout = &g_MiscDevicesLayout[iIndex];

		SEntry *pEntry = m_Regions.Insert();
		pEntry->iType = typeInstalledItem;
		pEntry->pItemCtx = new CItemCtx(pShip, pDevice);

		pEntry->iSlotPosIndex = iIndex;
		pEntry->rcRect.left = pLayout->xLeft;
		pEntry->rcRect.top = pLayout->yTop;
		pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
		pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;

		//	Mark the layout as used

		SlotStatus[iIndex] = false;
		}

	//	Figure out how many empty weapon slots we should create. We add one 
	//	empty slot for each weapon slot, but we subtract one if we don't have
	//	a launcher and we always have at least 1 empty slot, in case the player
	//	finds a slot-less weapon.

#ifdef SINGLE_FREE_SLOT
	int iEmptySlots = 1;
#else
	int iWeaponSlotsInUse;
	int iTotalSlotsInUse = pShip->CalcDeviceSlotsInUse(&iWeaponSlotsInUse);
	int iEmptySlots = Max(1, Min((pClass->GetMaxDevices() - iTotalSlotsInUse), (pClass->GetMaxWeapons() - iWeaponSlotsInUse)) - (bHasLauncher ? 0 : 1));
#endif

	//	Try to position the empty slots

	CVector vWeaponPos;
	SDeviceDesc DeviceDesc;
	if (pClass->FindDeviceSlotDesc(devPrimaryWeapon, &DeviceDesc))
		vWeaponPos = pClass->GetPosOffset(DeviceDesc.iPosAngle, DeviceDesc.iPosRadius, DeviceDesc.iPosZ, DeviceDesc.b3DPosition);

	for (i = 0; i < iEmptySlots; i++)
		{
		//	Find a position

		if (FindLayoutForPos(vWeaponPos, SlotStatus, &iIndex))
			{
			const SLayoutDesc *pLayout = &g_MiscDevicesLayout[iIndex];

			SEntry *pEntry = m_Regions.Insert();
			pEntry->iType = typeEmptySlot;
			pEntry->iSlotType = devPrimaryWeapon;

			pEntry->iSlotPosIndex = iIndex;
			pEntry->rcRect.left = pLayout->xLeft;
			pEntry->rcRect.top = pLayout->yTop;
			pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
			pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;

			SlotStatus[iIndex] = false;
			}
		}
	}
Example #21
0
void CAeonEngine::MsgGetRows (const SArchonMessage &Msg, const CHexeSecurityCtx *pSecurityCtx)

//	MsgGetRows
//
//	Aeon.getRows {tableAndView} {key} {count}
//	Aeon.getMoreRows {tableAndView} {lastKey} {count}

	{
	int i;

	CAeonTable *pTable;
	DWORD dwViewID;
	if (!ParseTableAndView(Msg, pSecurityCtx, Msg.dPayload.GetElement(0), &pTable, &dwViewID))
		return;

	//	Get the row limits

	int iRowCount;
	TArray<int> Limits;
	CDatum dLimits = Msg.dPayload.GetElement(2);
	if (dLimits.IsNil())
		iRowCount = -1;
	else if (dLimits.GetCount() <= 1)
		{
		iRowCount = (int)dLimits.GetElement(0);
		if (iRowCount <= 0)
			iRowCount = -1;
		}
	else
		{
		iRowCount = (int)dLimits.GetElement(0);
		if (iRowCount <= 0)
			iRowCount = -1;

		Limits.InsertEmpty(dLimits.GetCount() - 1);
		for (i = 1; i < dLimits.GetCount(); i++)
			Limits[i - 1] = (int)dLimits.GetElement(i);
		}

	//	Set up flags and options

	DWORD dwFlags = 0;
	dwFlags |= (strEquals(Msg.sMsg, MSG_AEON_GET_ROWS) ? 0 : CAeonTable::FLAG_MORE_ROWS);

	CDatum dOptions = Msg.dPayload.GetElement(3);
	for (i = 0; i < dOptions.GetCount(); i++)
		{
		if (strEquals(dOptions.GetElement(i), OPTION_INCLUDE_KEY))
			dwFlags |= CAeonTable::FLAG_INCLUDE_KEY;
		else if (strEquals(dOptions.GetElement(i), OPTION_NO_KEY))
			dwFlags |= CAeonTable::FLAG_NO_KEY;
		else
			{
			SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, strPattern(ERR_INVALID_GET_ROWS_OPTION, Msg.sMsg, dOptions.GetElement(i).AsString()), Msg);
			return;
			}
		}

	//	Ask the table

	CDatum dResult;
	CString sError;
	if (!pTable->GetRows(dwViewID, Msg.dPayload.GetElement(1), iRowCount, Limits, dwFlags, &dResult, &sError))
		{
		SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, sError, Msg);
		return;
		}

	//	Done

	SendMessageReply(MSG_REPLY_DATA, dResult, Msg);
	}