Example #1
0
void CMultiverseModel::OnUserSignedIn (const CString &sUsername)

//	OnUserSignedIn
//
//	The given user has signed in. The given username is the human-readable
//	username (not the username key).

	{
	CSmartLock Lock(m_cs);

	ASSERT(!sUsername.IsBlank());

	if (!strEquals(sUsername, m_sUsername) || !m_fUserSignedIn)
		{
		m_sUsername = sUsername;

		//	Clear out the collection so that we are forced to reload it.

		DeleteCollection();

		//	We're signed in

		m_fUserSignedIn = true;
		}
	}
Example #2
0
ALERROR CEffectCreator::CreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc, const CString &sUNID, CEffectCreator **retpCreator)

//	CreateFromXML
//
//	Creates the creator from an XML element

	{
	ALERROR error;
	CEffectCreator *pCreator;

	//	Basic info

	CString sEffectUNID = sUNID;
	if (sEffectUNID.IsBlank())
		{
		DWORD dwUNID = pDesc->GetAttributeInteger(UNID_ATTRIB);
		if (dwUNID)
			sEffectUNID = strFromInt(dwUNID, FALSE);
		else
			sEffectUNID = STR_NO_UNID;
		}

	//	Create the effect based on the child tag

	if (pDesc->GetContentElementCount() == 0)
		{
		*retpCreator = NULL;
		return NOERROR;
		}
	else if (pDesc->GetContentElementCount() == 1)
		{
		if (error = CreateSimpleFromXML(Ctx, pDesc->GetContentElement(0), sEffectUNID, &pCreator))
			return error;
		}
	else
		{
		pCreator = new CEffectGroupCreator;
		if (pCreator == NULL)
			return ERR_MEMORY;

		pCreator->m_sUNID = sEffectUNID;

		//	Type-specific creation

		if (error = pCreator->OnEffectCreateFromXML(Ctx, pDesc, sEffectUNID))
			return error;
		}

	//	Sound Effect (resolved later)

	pCreator->m_dwSoundUNID = pDesc->GetAttributeInteger(SOUND_ATTRIB);
	pCreator->m_iSound = -1;
	
	//	Done

	*retpCreator = pCreator;

	return NOERROR;
	}
Example #3
0
ALERROR IEffectPainter::ValidateClass (SLoadCtx &Ctx, const CString &sOriginalClass)

//	ValidateClass
//
//	Reads the class string. If the class does not match the current painter,
//	we read the old data and return ERR_FAIL.

	{
	if (Ctx.dwVersion >= 40)
		{
		CString sClass;
		sClass.ReadFromStream(Ctx.pStream);

		//	If the original class doesn't match the current one, then it means
		//	that the design changed. In that case, we load the painter using the
		//	old class.

		if (!strEquals(sClass, sOriginalClass))
			{
			//	If sClass is blank, then it means that the original did not have
			//	an effect painter (but the current design does)

			if (!sClass.IsBlank())
				{
				//	Get the original creator

				CEffectCreator *pOriginalCreator;
				if (CEffectCreator::CreateFromTag(sClass, &pOriginalCreator) != NOERROR)
					{
					kernelDebugLogMessage("Unable to find original effect creator: %s", sClass.GetASCIIZPointer());
					return ERR_FAIL;
					}

				//	Load the original painter

				IEffectPainter *pOriginalPainter = pOriginalCreator->CreatePainter();
				pOriginalPainter->ReadFromStream(Ctx);

				//	Discard

				pOriginalPainter->Delete();
				delete pOriginalCreator;
				}

			//	Done

			return ERR_FAIL;
			}
		}

	return NOERROR;
	}
Example #4
0
CString CAISettings::SetValue (const CString &sSetting, const CString &sValue)

//	SetValue
//
//	Set AISettings value

	{
	if (strEquals(sSetting, AGGRESSOR_ATTRIB))
		m_fAggressor = !sValue.IsBlank();
	else if (strEquals(sSetting, ASCEND_ON_GATE_ATTRIB))
		m_fAscendOnGate = !sValue.IsBlank();
	else if (strEquals(sSetting, COMBAT_SEPARATION_ATTRIB))
		m_rMinCombatSeparation = Max(1, strToInt(sValue, 1)) * g_KlicksPerPixel;
	else if (strEquals(sSetting, COMBAT_STYLE_ATTRIB))
		m_iCombatStyle = ConvertToAICombatStyle(sValue);
	else if (strEquals(sSetting, FIRE_ACCURACY_ATTRIB))
		m_iFireAccuracy = Max(0, Min(strToInt(sValue, 100), 100));
	else if (strEquals(sSetting, FIRE_RANGE_ADJ_ATTRIB))
		m_iFireRangeAdj = Max(1, strToInt(sValue, 100));
	else if (strEquals(sSetting, FIRE_RATE_ADJ_ATTRIB))
		m_iFireRateAdj = Max(1, strToInt(sValue, 10));
	else if (strEquals(sSetting, NO_DOGFIGHTS_ATTRIB))
		m_fNoDogfights = !sValue.IsBlank();
	else if (strEquals(sSetting, NO_SHIELD_RETREAT_ATTRIB))
		m_fNoShieldRetreat = !sValue.IsBlank();
	else if (strEquals(sSetting, NO_FRIENDLY_FIRE_ATTRIB))
		m_fNoFriendlyFire = !sValue.IsBlank();
	else if (strEquals(sSetting, NO_FRIENDLY_FIRE_CHECK_ATTRIB))
		m_fNoFriendlyFireCheck = !sValue.IsBlank();
	else if (strEquals(sSetting, NO_NAV_PATHS_ATTRIB))
		m_fNoNavPaths = !sValue.IsBlank();
	else if (strEquals(sSetting, NO_ORDER_GIVER_ATTRIB))
		m_fNoOrderGiver = !sValue.IsBlank();
	else if (strEquals(sSetting, NON_COMBATANT_ATTRIB))
		m_fNonCombatant = !sValue.IsBlank();
	else if (strEquals(sSetting, PERCEPTION_ATTRIB))
		m_iPerception = Max((int)CSpaceObject::perceptMin, Min(strToInt(sValue, CSpaceObject::perceptNormal), (int)CSpaceObject::perceptMax));
	else
		return NULL_STR;

	return GetValue(sSetting);
	}
Example #5
0
void CMenuData::AddMenuItem (const CString &sKey,
							 const CString &sLabel,
							 const CObjectImageArray *pImage,
							 const CString &sExtra,
							 DWORD dwFlags,
							 DWORD dwData,
							 DWORD dwData2)

//	AddMenuItem
//
//	Add an item

	{
	ASSERT(m_iCount < MAX_MENU_ITEMS);
	if (m_iCount == MAX_MENU_ITEMS)
		return;

	//	If we have a key, sort by key. Otherwise, we
	//	add it at the end.

	int iPos;
	if (sKey.IsBlank() || !(dwFlags & FLAG_SORT_BY_KEY))
		iPos = m_iCount;
	else
		{
		iPos = 0;
		while (iPos < m_iCount 
				&& !m_List[iPos].sKey.IsBlank()
				&& strCompareAbsolute(sKey, m_List[iPos].sKey) > 0)
			iPos++;

		//	Move other items up

		for (int i = m_iCount - 1; i >= iPos; i--)
			m_List[i+1] = m_List[i];
		}

	//	Add item

	m_List[iPos].sKey = sKey;
	m_List[iPos].sLabel = sLabel;
	m_List[iPos].dwData = dwData;
	m_List[iPos].dwData2 = dwData2;
	m_List[iPos].sExtra = sExtra;
	m_List[iPos].dwFlags = dwFlags;
	m_List[iPos].pImage = pImage;

	m_iCount++;
	}
Example #6
0
CurrencyValue CCurrencyBlock::IncCredits (const CString &sCurrency, CurrencyValue iInc)

//	IncCredits
//
//	Increments/decrements credits

{
    ASSERT(!sCurrency.IsBlank());

    CEconomyType *pEcon = g_pUniverse->FindEconomyType(sCurrency);
    if (pEcon == NULL)
        return 0;

    return IncCredits(pEcon->GetUNID(), iInc);
}
Example #7
0
CurrencyValue CCurrencyBlock::GetCredits (const CString &sCurrency)

//	GetCredits
//
//	Returns the number of credits available in the given currency

{
    ASSERT(!sCurrency.IsBlank());

    CEconomyType *pEcon = g_pUniverse->FindEconomyType(sCurrency);
    if (pEcon == NULL)
        return 0;

    return GetCredits(pEcon->GetUNID());
}
Example #8
0
void CCurrencyBlock::SetCredits (const CString &sCurrency, CurrencyValue iValue)

//	SetCredits
//
//	Sets the credit value for the given currency

{
    ASSERT(!sCurrency.IsBlank());

    CEconomyType *pEcon = g_pUniverse->FindEconomyType(sCurrency);
    if (pEcon == NULL)
        return;

    SetCredits(pEcon->GetUNID(), iValue);
}
Example #9
0
ALERROR CTopologyNode::AddStargateConnection (CTopologyNode *pDestNode, bool bOneWay, const CString &sFromName, const CString &sToName)

//	AddStargateConnection
//
//	Adds two stargates connecting this node with the destination.
//	The names of the stargates are optionally passed in (if not, they are autogenerated).

	{
	ALERROR error;

	CString sSourceGate = (sFromName.IsBlank() ? GenerateStargateName() : sFromName);
	CString sDestGate = ((!pDestNode->IsEndGame() && sToName.IsBlank()) ? pDestNode->GenerateStargateName() : sToName);

	//	Add stargate from source to destination

	if (error = AddGateInt(sSourceGate, pDestNode->GetID(), sDestGate))
		return ERR_FAIL;

	//	Check to see if the destination gate exists already
	//	[If sToName is blank, then we know that the gate does not exist because we autogenerated it.]

	bool bExists = (!sToName.IsBlank() && (pDestNode->m_NamedGates.Lookup(sDestGate) == NOERROR));

	//	If the gate doesn't exist AND we want both directions, create the destination gate
	//	[We don't create the other gate if it already exists OR we want a one-way gate.

	if (!bExists && !bOneWay && !pDestNode->IsEndGame())
		{
		if (error = pDestNode->AddGateInt(sDestGate, GetID(), sSourceGate))
			return ERR_FAIL;
		}

	//	Done

	return NOERROR;
	}
ALERROR CSingleParticleEffectCreator::OnEffectCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc, const CString &sUNID)

//	OnEffectCreateFromXML
//
//	Initializes from XML

	{
	ALERROR error;

	CString sStyle = pDesc->GetAttribute(STYLE_ATTRIB);
	if (sStyle.IsBlank() || strEquals(sStyle, STYLE_PLAIN))
		m_iStyle = paintPlain;
	else if (strEquals(sStyle, STYLE_FLAME))
		m_iStyle = paintFlame;
	else if (strEquals(sStyle, STYLE_SMOKE))
		m_iStyle = paintSmoke;
	else if (strEquals(sStyle, STYLE_LINE))
		m_iStyle = paintLine;
	else
		{
		Ctx.sError = CONSTLIT("Invalid SingleParticle style");
		return ERR_FAIL;
		}

	CString sRange;
	if (pDesc->FindAttribute(MAX_WIDTH_ATTRIB, &sRange))
		{
		if (error = m_MaxWidth.LoadFromXML(sRange))
			return error;
		}
	else
		m_MaxWidth = DiceRange(0, 0, DEFAULT_MAX_WIDTH);

	if (pDesc->FindAttribute(MIN_WIDTH_ATTRIB, &sRange))
		{
		if (error = m_MinWidth.LoadFromXML(sRange))
			return error;
		}
	else
		m_MinWidth = DiceRange(0, 0, DEFAULT_MIN_WIDTH);

	//	Colors

	m_wPrimaryColor = ::LoadRGBColor(pDesc->GetAttribute(PRIMARY_COLOR_ATTRIB));
	m_wSecondaryColor = ::LoadRGBColor(pDesc->GetAttribute(SECONDARY_COLOR_ATTRIB));

	return NOERROR;
	}
void CSoundtrackManager::Play (CSoundType *pTrack)

//	Play
//
//	Plays the given track.

	{
	//	If we're already playing this track, then nothing to do.

	if (pTrack == m_pNowPlaying)
		return;

	//	Play

	if (m_bEnabled
			&& pTrack)
		{
		CString sFilespec = pTrack->GetFilespec();
		if (sFilespec.IsBlank())
			{
			::kernelDebugLogMessage("Unable to find soundtrack: %x", pTrack->GetUNID());
			return;
			}

		CString sError;
		if (!g_pHI->GetSoundMgr().PlayMusic(sFilespec, 0, &sError))
			{
			::kernelDebugLogMessage("Unable to play soundtrack %s: %s", sFilespec, sError);
			return;
			}
		}

	//	Remember what we're playing

	if (m_pNowPlaying)
		m_LastPlayed.EnqueueAndOverwrite(m_pNowPlaying->GetUNID());

	if (pTrack && pTrack->HasAttribute(ATTRIB_SYSTEM_SOUNDTRACK))
		m_bSystemTrackPlayed = true;

	m_pNowPlaying = pTrack;
	}
Example #12
0
void CListSaveFilesTask::CreateFileEntry (CGameFile &GameFile, const CTimeDate &ModifiedTime, int yStart, IAnimatron **retpEntry, int *retcyHeight)

//	CreateFileEntry
//
//	Creates a display entry for the save file

	{
	const CVisualPalette &VI = m_HI.GetVisuals();
	const CG16bitFont &MediumFont = VI.GetFont(fontMedium);
	const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle);

	int x = 0;
	int y = 0;
	int xText = x + ADVENTURE_ICON_WIDTH + ICON_SPACING_HORZ;
	int cxText = m_cxWidth - (ADVENTURE_ICON_WIDTH + 2 * ICON_SPACING_HORZ + SHIP_IMAGE_WIDTH);

	//	Start with a sequencer

	CAniSequencer *pRoot = new CAniSequencer;
	pRoot->SetPropertyVector(PROP_POSITION, CVector(0, yStart));

	//	Add the character name and current star system

	CString sHeading = strPatternSubst(CONSTLIT("%s — %s"), GameFile.GetPlayerName(), GameFile.GetSystemName());

	IAnimatron *pName = new CAniText;
	pName->SetPropertyVector(PROP_POSITION, CVector(xText, y));
	pName->SetPropertyVector(PROP_SCALE, CVector(10000, 1000));
	pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput));
	pName->SetPropertyFont(PROP_FONT, &SubTitleFont);
	pName->SetPropertyString(PROP_TEXT, sHeading);

	pRoot->AddTrack(pName, 0);
	y += SubTitleFont.GetHeight();

	//	Now add some additional information

	CShipClass *pClass = g_pUniverse->FindShipClass(GameFile.GetPlayerShip());
	CString sShipClass = (pClass ? pClass->GetName() : NULL_STR);
	CString sGenome = strCapitalize(GetGenomeName(GameFile.GetPlayerGenome()));

	CString sState;
	if (GameFile.IsGameResurrect())
		sState = strPatternSubst(CONSTLIT("Resurrect in the %s System"), GameFile.GetSystemName());
	else
		sState = strPatternSubst(CONSTLIT("Continue in the %s System"), GameFile.GetSystemName());

	CString sDesc;
	if (!sGenome.IsBlank() && !sShipClass.IsBlank())
		sDesc = strPatternSubst(CONSTLIT("%s — %s — %s"), sGenome, sShipClass, sState);
	else
		sDesc = sState;

	IAnimatron *pDesc = new CAniText;
	pDesc->SetPropertyVector(PROP_POSITION, CVector(xText, y));
	pDesc->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000));
	pDesc->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput));
	pDesc->SetPropertyFont(PROP_FONT, &MediumFont);
	pDesc->SetPropertyString(PROP_TEXT, sDesc);

	RECT rcLine;
	pDesc->GetSpacingRect(&rcLine);

	pRoot->AddTrack(pDesc, 0);
	y += RectHeight(rcLine);

	//	Adventure info

	CExtension *pAdventure = NULL;
	bool bHasAdventureIcon = false;

	if (g_pUniverse->FindExtension(GameFile.GetAdventure(), 0, &pAdventure))
		{
		//	Adventure icon

		CG16bitImage *pIcon;
		pAdventure->CreateIcon(ADVENTURE_ICON_WIDTH, ADVENTURE_ICON_HEIGHT, &pIcon);

		if (pIcon)
			{
			int xOffset = (ADVENTURE_ICON_WIDTH - pIcon->GetWidth()) / 2;
			IAnimatron *pIconAni = new CAniRect;
			pIconAni->SetPropertyVector(PROP_POSITION, CVector(x + xOffset, 0));
			pIconAni->SetPropertyVector(PROP_SCALE, CVector(pIcon->GetWidth(), pIcon->GetHeight()));
			pIconAni->SetFillMethod(new CAniImageFill(pIcon, true));

			pRoot->AddTrack(pIconAni, 0);

			bHasAdventureIcon = true;
			}

		//	Adventure name

		pName = new CAniText;
		pName->SetPropertyVector(PROP_POSITION, CVector(xText, y));
		pName->SetPropertyVector(PROP_SCALE, CVector(10000, 1000));
		pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel));
		pName->SetPropertyFont(PROP_FONT, &MediumFont);
		pName->SetPropertyString(PROP_TEXT, pAdventure->GetName());

		pRoot->AddTrack(pName, 0);
		y += MediumFont.GetHeight();
		}

	//	Create an image of the ship class

	if (pClass)
		{
		const CObjectImageArray &ObjImage = pClass->GetImage();
		if (ObjImage.IsLoaded())
			{
			RECT rcRect = ObjImage.GetImageRect();
			CG16bitImage &Image = ObjImage.GetImage(NULL_STR);
			int cxImage = RectWidth(rcRect);
			int cyImage = RectHeight(rcRect);

			int cxNewWidth = Min(SHIP_IMAGE_WIDTH, cxImage);
			int cyNewHeight = cxNewWidth;

			CG16bitImage *pNewImage = new CG16bitImage;
			pNewImage->CreateFromImageTransformed(Image, 
					rcRect.left, 
					rcRect.top, 
					cxImage,
					cyImage,
					(Metric)cxNewWidth / cxImage,
					(Metric)cyNewHeight / cyImage,
					0.0);

			//	Position

			int xImage = x + m_cxWidth - SHIP_IMAGE_WIDTH + (SHIP_IMAGE_WIDTH - cxNewWidth) / 2;
			int yImage = (SHIP_IMAGE_HEIGHT - cyNewHeight) / 2;

			//	New image frame

			IAnimatron *pImageFrame = new CAniRect;
			pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xImage, yImage));
			pImageFrame->SetPropertyVector(PROP_SCALE, CVector(cxNewWidth, cyNewHeight));
			pImageFrame->SetFillMethod(new CAniImageFill(pNewImage, true));

			pRoot->AddTrack(pImageFrame, 0);
			}
		}

	//	Extra information

	CString sEpitaph = GameFile.GetEpitaph();
	int iScore = GameFile.GetScore();
	CTimeDate LocalTime = ModifiedTime.ToLocalTime();
	CString sModifiedTime = LocalTime.Format("%d %B %Y %I:%M %p");
	CString sFilename = pathGetFilename(GameFile.GetFilespec());

	CString sGameType;
	if (GameFile.IsRegistered())
		sGameType = CONSTLIT("Registered");
	else if (GameFile.IsDebug())
		sGameType = CONSTLIT("Debug");
	else
		sGameType = CONSTLIT("Unregistered");

	CString sExtra;
	if (!sEpitaph.IsBlank())
		sExtra = strPatternSubst(CONSTLIT("Score %d — %s\n%s — %s — %s"), iScore, sEpitaph, sGameType, sModifiedTime, sFilename);
	else if (iScore > 0)
		sExtra = strPatternSubst(CONSTLIT("Score %d\n%s — %s — %s"), iScore, sGameType, sModifiedTime, sFilename);
	else
		sExtra = strPatternSubst(CONSTLIT("%s — %s — %s"), sGameType, sModifiedTime, sFilename);

	pDesc = new CAniText;
	pDesc->SetPropertyVector(PROP_POSITION, CVector(xText, y));
	pDesc->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000));
	pDesc->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel));
	pDesc->SetPropertyFont(PROP_FONT, &MediumFont);
	pDesc->SetPropertyString(PROP_TEXT, sExtra);

	pDesc->GetSpacingRect(&rcLine);

	pRoot->AddTrack(pDesc, 0);
	y += RectHeight(rcLine);

	//	Done

	*retpEntry = pRoot;

	if (retcyHeight)
		*retcyHeight = (bHasAdventureIcon ? Max(ADVENTURE_ICON_HEIGHT, y) : y);
	}
Example #13
0
IEffectPainter *CEffectCreator::CreatePainterFromStream (SLoadCtx &Ctx, bool bNullCreator)

//	CreatePainterFromStream
//
//	Load a painter from a stream

	{
	CEffectCreator *pCreator;

	//	For previous versions, we only stored UNID if we had a creator

	if (Ctx.dwVersion < 43 && bNullCreator)
		return NULL;

	//	At version 15 we started saving versions as string UNIDs. We need to do this
	//	because sometimes the effect creator is inside a weapon fire desc
	//	structure (also identified by string UNIDs).

	if (Ctx.dwVersion >= 15)
		{
		CString sUNID;
		sUNID.ReadFromStream(Ctx.pStream);

		pCreator = (sUNID.IsBlank() ? NULL : CEffectCreator::FindEffectCreator(sUNID));

		//	Load the creator class that saved the painter

		if (IEffectPainter::ValidateClass(Ctx, (pCreator ? pCreator->GetTag() : NULL_STR)) != NOERROR)
			return NULL;

		//	Error

		if (pCreator == NULL)
			{
			if (!sUNID.IsBlank())
				kernelDebugLogMessage("Invalid painter creator: %s", sUNID.GetASCIIZPointer());
			return NULL;
			}
		}

	//	Old style uses DWORD UNIDs

	else
		{
		//	The first DWORD is the UNID of the creator

		DWORD dwUNID;
		Ctx.pStream->Read((char *)&dwUNID, sizeof(DWORD));
		if (dwUNID == 0)
			return NULL;

		pCreator = g_pUniverse->FindEffectType(dwUNID);

		//	Error

		if (pCreator == NULL)
			{
			kernelDebugLogMessage("Invalid painter creator: %x", dwUNID);
			return NULL;
			}
		}

	//	Let the creator create the object

	IEffectPainter *pPainter = pCreator->CreatePainter();

	//	Load it

	pPainter->ReadFromStream(Ctx);

	//	Done

	return pPainter;
	}
Example #14
0
ICCItem *CCodeChain::Eval (CEvalContext *pEvalCtx, ICCItem *pItem)

//	Eval
//
//	Evaluates the given item and returns a result

{
    //	Errors always evaluate to themselves

    if (pItem->IsError())
        return pItem->Reference();

    //	If this item is quoted, then return an unquoted item

    if (pItem->IsQuoted())
    {
        //	If this is a literal symbol table then we need to evaluate its
        //	values.

        if (pItem->IsSymbolTable())
            return EvalLiteralStruct(pEvalCtx, pItem);

        //	HACK: We clone the item so that when we try to modify a literal list we
        //	mody a copy instead of the original.

        else
        {
            ICCItem *pResult = pItem->Clone(this);
            pResult->ClearQuoted();
            return pResult;
        }
    }

    //	Evaluate differently depending on whether or not
    //	this is an atom or a list. If it is an atom, either return
    //	the value or look up the atom in a symbol table. If the item
    //	is a list, try to evaluate as a function

    else if (pItem->IsIdentifier())
        return Lookup(pEvalCtx, pItem);

    //	If this is an expression (a list with multiple terms) then we
    //	try to evaluate it.

    else if (pItem->IsExpression())
    {
        ICCItem *pFunctionName;
        ICCItem *pFunction;
        ICCItem *pArgs;
        ICCItem *pResult;

        //	The first element of the list is the function

        pFunctionName = pItem->Head(this);

        //	We must have a first element since this is a list (but not Nil)

        ASSERT(pFunctionName);

        //	If this is an identifier, then look up the function
        //	in the global symbols

        if (pFunctionName->IsIdentifier())
            pFunction = LookupFunction(pEvalCtx, pFunctionName);

        //	Otherwise, evaluate it

        else
            pFunction = Eval(pEvalCtx, pFunctionName);

        //	If we get an error, return it

        if (pFunction->IsError())
            return pFunction;

        //	Make sure this is a function

        if (!pFunction->IsFunction())
        {
            pFunction->Discard(this);
            return CreateError(LITERAL("Function name expected"), pFunctionName);
        }

        //	Get the arguments

        pArgs = pItem->Tail(this);

        //	Do it

        pResult = pFunction->Execute(pEvalCtx, pArgs);

        //	Handle error by appending the function call that failed

        if (pResult->IsError())
        {
            CCString *pError = dynamic_cast<CCString *>(pResult);
            if (pError)
            {
                CString sError = pError->GetValue();
                if (!sError.IsBlank())
                {
                    char *pPos = sError.GetASCIIZPointer() + sError.GetLength() - 1;
                    if (*pPos != '#')
                    {
                        sError.Append(strPatternSubst(CONSTLIT(" ### %s ###"), pItem->Print(this)));
                        pError->SetValue(sError);
                    }
                }
            }
        }

        //	Done

        pFunction->Discard(this);
        pArgs->Discard(this);
        return pResult;
    }

    //	Anything else is a literal so we return it.

    else
        return pItem->Reference();

}
Example #15
0
ALERROR CDockScreenCustomList::OnInitList (SInitCtx &Ctx, CString *retsError)

//	OnInitList
//
//	Initialize list

	{
	//	Get the list element

	CXMLElement *pListData = Ctx.pDesc->GetContentElementByTag(LIST_TAG);
	if (pListData == NULL)
		return ERR_FAIL;

	//	See if we define a custom row height

	CString sRowHeight;
	if (pListData->FindAttribute(ROW_HEIGHT_ATTRIB, &sRowHeight))
		{
		CString sResult;
		if (!EvalString(sRowHeight, false, eventNone, &sResult))
			{
			*retsError = sResult;
			return ERR_FAIL;
			}

		int cyRow = strToInt(sResult, -1);
		if (cyRow > 0)
			m_pItemListControl->SetRowHeight(cyRow);
		}

	//	Get the list to show

	CCodeChain &CC = g_pUniverse->GetCC();
	ICCItem *pExp = CC.Link(pListData->GetContentText(0), 0, NULL);

	//	Evaluate the function

	CCodeChainCtx CCCtx;
	CCCtx.SetScreen(m_pDockScreen);
	CCCtx.SaveAndDefineSourceVar(m_pLocation);
	CCCtx.SaveAndDefineDataVar(m_pData);

	ICCItem *pResult = CCCtx.Run(pExp);	//	LATER:Event
	CCCtx.Discard(pExp);

	if (pResult->IsError())
		{
		*retsError = pResult->GetStringValue();
		return ERR_FAIL;
		}

	//	Set this expression as the list

	m_pItemListControl->SetList(CC, pResult);
	CCCtx.Discard(pResult);

	//	Position the cursor on the next relevant item

	SelectNextItem();

	//	Give the screen a chance to start at a different item (other
	//	than the first)

	CString sInitialItemFunc = pListData->GetAttribute(INITIAL_ITEM_ATTRIB);
	if (!sInitialItemFunc.IsBlank())
		{
		bool bMore = IsCurrentItemValid();
		while (bMore)
			{
			bool bResult;
			if (!EvalBool(sInitialItemFunc, &bResult, retsError))
				return ERR_FAIL;

			if (bResult)
				break;

			bMore = SelectNextItem();
			}
		}

	return NOERROR;
	}
bool IDockScreenDisplay::GetDisplayOptions (SInitCtx &Ctx, SDisplayOptions *retOptions, CString *retsError)

//	GetDisplayOptions
//
//	Initializes the display options structure, which is used by list and 
//	selector displays.

	{
	DEBUG_TRY

	//	Initialize background image options

	CString sBackgroundID;
	if (Ctx.pDesc->FindAttribute(BACKGROUND_ID_ATTRIB, &sBackgroundID))
		{
		//	If the attribute exists, but is empty (or equals "none") then
		//	we don't have a background

		if (sBackgroundID.IsBlank() || strEquals(sBackgroundID, CONSTLIT("none")))
			retOptions->BackgroundDesc.iType = backgroundNone;

		else if (strEquals(sBackgroundID, TYPE_HERO))
			{
			retOptions->BackgroundDesc.iType = backgroundObjHeroImage;
			retOptions->BackgroundDesc.pObj = Ctx.pLocation;
			}

		//	If the ID is "object" then we should ask the object

		else if (strEquals(sBackgroundID, TYPE_OBJECT))
			{
			retOptions->BackgroundDesc.pObj = Ctx.pLocation;
            if (Ctx.pLocation->IsPlayer())
			    retOptions->BackgroundDesc.iType = backgroundObjSchematicImage;
            else
			    retOptions->BackgroundDesc.iType = backgroundObjHeroImage;
			}

		else if (strEquals(sBackgroundID, TYPE_SCHEMATIC))
			{
			retOptions->BackgroundDesc.iType = backgroundObjSchematicImage;
			retOptions->BackgroundDesc.pObj = Ctx.pLocation;
			}

		//	If the ID is "player" then we should ask the player ship

		else if (strEquals(sBackgroundID, DATA_FROM_PLAYER))
			{
			CSpaceObject *pPlayer = g_pUniverse->GetPlayerShip();
			if (pPlayer)
				{
				retOptions->BackgroundDesc.iType = backgroundObjSchematicImage;
				retOptions->BackgroundDesc.pObj = pPlayer;
				}
			}

		//	Otherwise, we expect an integer

		else
			{
			retOptions->BackgroundDesc.iType = backgroundImage;
			retOptions->BackgroundDesc.dwImageID = strToInt(sBackgroundID, 0);
			}
		}

	//	Initialize control rect. If we have a background, then initialize to
	//	backwards compatible position. Otherwise, we take up the full range.

	if (retOptions->BackgroundDesc.iType != backgroundDefault)
		{
		retOptions->rcControl.left = 4;
		retOptions->rcControl.top = 12;
		retOptions->rcControl.right = 548;
		retOptions->rcControl.bottom = 396;
		}
	else
		{
		retOptions->rcControl.left = 0;
		retOptions->rcControl.top = 23;
		retOptions->rcControl.right = 600;
		retOptions->rcControl.bottom = 502;
		}

	//	Get the type

	if (Ctx.pDisplayDesc
			&& Ctx.pDisplayDesc->FindAttribute(TYPE_ATTRIB, &retOptions->sType))
		NULL;
	else
		retOptions->sType = Ctx.pDesc->GetAttribute(TYPE_ATTRIB);

	//	There are a couple of different ways to get options (for backwards
	//	compatibility).

	CXMLElement *pOptions;
	if ((pOptions = Ctx.pDesc->GetContentElementByTag(LIST_OPTIONS_TAG)) == NULL
			&& (pOptions = Ctx.pDesc->GetContentElementByTag(LIST_TAG)) == NULL
			&& (pOptions = Ctx.pDisplayDesc) == NULL)
		return true;

	retOptions->pOptions = pOptions;

	//	Read from the element

	retOptions->sDataFrom = pOptions->GetAttribute(DATA_FROM_ATTRIB);
	if (!pOptions->FindAttribute(CRITERIA_ATTRIB, &retOptions->sItemCriteria))
		retOptions->sItemCriteria = pOptions->GetAttribute(LIST_ATTRIB);
	retOptions->sInitialItemCode = pOptions->GetAttribute(INITIAL_ITEM_ATTRIB);
	retOptions->sRowHeightCode = pOptions->GetAttribute(ROW_HEIGHT_ATTRIB);

	//	Init code

	CXMLElement *pInitCode = pOptions->GetContentElementByTag(ON_DISPLAY_INIT_TAG);
	if (pInitCode == NULL)
		pInitCode = pOptions;

	retOptions->sCode = pInitCode->GetContentText(0);

	//	List options

	retOptions->bNoArmorSpeedDisplay = pOptions->GetAttributeBool(NO_ARMOR_SPEED_DISPLAY_ATTRIB);
	retOptions->bActualItems = pOptions->GetAttributeBool(DISPLAY_ACTUAL_ATTRIB);
	retOptions->cxIcon = pOptions->GetAttributeIntegerBounded(ICON_WIDTH_ATTRIB, 0, -1, ICON_WIDTH);
	retOptions->cyIcon = pOptions->GetAttributeIntegerBounded(ICON_HEIGHT_ATTRIB, 0, -1, ICON_HEIGHT);
	retOptions->rIconScale = pOptions->GetAttributeDoubleBounded(ICON_SCALE_ATTRIB, 0.0, -1.0, 1.0);

    //  Selector options

    retOptions->bNoEmptySlots = pOptions->GetAttributeBool(NO_EMPTY_SLOTS_ATTRIB);
    retOptions->sSlotNameCode = pOptions->GetAttribute(SLOT_NAME_ATTRIB);

	//	See if we have control position

	if (pOptions->FindAttributeInteger(POS_X_ATTRIB, (int *)&retOptions->rcControl.left))
		{
		retOptions->rcControl.top = pOptions->GetAttributeIntegerBounded(POS_Y_ATTRIB, 0, -1);
		retOptions->rcControl.right = retOptions->rcControl.left + pOptions->GetAttributeIntegerBounded(WIDTH_ATTRIB, 0, -1);
		retOptions->rcControl.bottom = retOptions->rcControl.top + pOptions->GetAttributeIntegerBounded(HEIGHT_ATTRIB, 0, -1);
		}

	return true;

	DEBUG_CATCH
	}
Example #17
0
ALERROR CTopologyNode::InitFromSystemXML (CXMLElement *pSystem, CString *retsError)

//	InitFromSystemXML
//
//	Initializes the system information based on an XML element

	{
	ALERROR error;
	CString sSystemUNID = pSystem->GetAttribute(UNID_ATTRIB);
	DWORD dwUNID = strToInt(sSystemUNID, 0, NULL);

	//	If the system node contains a table of different system types, then
	//	remember the root node because some of the system information (such as the
	//	name) may be there.

	CXMLElement *pSystemParent = NULL;

	//	If there is no UNID attribute then it means that the system
	//	is randomly determined based on a table

	if (dwUNID == 0 && pSystem->GetContentElementCount() == 1)
		{
		CXMLElement *pTableElement = pSystem->GetContentElement(0);
		if (pTableElement == NULL)
			{
			ASSERT(false);
			return ERR_FAIL;
			}

		CRandomEntryResults System;
		if (error = CRandomEntryGenerator::Generate(pTableElement, System))
			{
			*retsError = strPatternSubst(CONSTLIT("Topology %s: Unable to generate random system UNID"), m_sID);
			return ERR_FAIL;
			}

		if (System.GetCount() != 1)
			{
			*retsError = strPatternSubst(CONSTLIT("Topology %s: Table generated no systems"), m_sID);
			return ERR_FAIL;
			}

		pSystemParent = pSystem;
		pSystem = System.GetResult(0);
		dwUNID = pSystem->GetAttributeInteger(UNID_ATTRIB);
		}

	//	Set the system UNID

	if (dwUNID != 0)
		m_SystemUNID = dwUNID;

	//	Set the name of the system

	CString sName;
	if (!pSystem->FindAttribute(NAME_ATTRIB, &sName))
		if (pSystemParent)
			sName = pSystemParent->GetAttribute(NAME_ATTRIB);

	if (!sName.IsBlank())
		SetName(sName);

	//	Set the level

	int iLevel = 0;
	if (!pSystem->FindAttributeInteger(LEVEL_ATTRIB, &iLevel))
		if (pSystemParent)
			iLevel = pSystemParent->GetAttributeInteger(LEVEL_ATTRIB);

	if (iLevel > 0)
		SetLevel(iLevel);

	if (GetLevel() == 0)
		SetLevel(1);

	//	Add variants for the system

	CString sVariant;
	if (pSystem->FindAttribute(VARIANT_ATTRIB, &sVariant))
		AddVariantLabel(sVariant);

	if (pSystemParent && pSystemParent->FindAttribute(VARIANT_ATTRIB, &sVariant))
		AddVariantLabel(sVariant);

	//	Add attributes for the node/system

	CString sAttribs;
	if (pSystem->FindAttribute(ATTRIBUTES_ATTRIB, &sAttribs))
		AddAttributes(sAttribs);

	if (pSystemParent && pSystemParent->FindAttribute(ATTRIBUTES_ATTRIB, &sAttribs))
		AddAttributes(sAttribs);

	return NOERROR;
	}
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;
	}
Example #19
0
void WordGenerator (CXMLElement *pCmdLine)
{
    int i;

    //	Load input file

    CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("input"));
    if (sFilespec.IsBlank())
    {
        printf("ERROR: input filename expected.\n");
        return;
    }

    CFileReadBlock InputFile(sFilespec);
    if (InputFile.Open() != NOERROR)
    {
        printf("ERROR: Unable to open file: %s\n", sFilespec.GetASCIIZPointer());
        return;
    }

    //	"Novel" means that we only generate words that are not
    //	in the input file.

    bool bNovelWordsOnly = pCmdLine->GetAttributeBool(NOVEL_ATTRIB);

    //	Build up a word generator

    CMarkovWordGenerator Generator;
    TMap<CString, DWORD> InputWords;

    //	Read each line of the file

    char *pPos = InputFile.GetPointer(0);
    char *pEndPos = pPos + InputFile.GetLength();
    while (pPos < pEndPos)
    {
        //	Skip whitespace

        while (pPos < pEndPos && (strIsWhitespace(pPos) || *pPos < ' '))
            pPos++;

        //	Parse the line

        char *pStart = pPos;
        while (pPos < pEndPos && *pPos != '\r' && *pPos != '\n' && *pPos >= ' ')
            pPos++;

        CString sWord(pStart, pPos - pStart);

        //	Add the word to the generator

        if (!sWord.IsBlank())
        {
            Generator.AddSample(strTrimWhitespace(sWord));

            //	If we are looking for novel words we need to keep a map
            //	of all words in the input file.

            if (bNovelWordsOnly)
                InputWords.Insert(sWord);
        }
    }

    //	If we have a count, then output a list of random words

    int iCount;
    if (pCmdLine->FindAttributeInteger(COUNT_ATTRIB, &iCount))
    {
        if (iCount > 0)
        {
            TArray<CString> Result;
            Generator.GenerateUnique(iCount, &Result);

            for (i = 0; i < Result.GetCount(); i++)
                if (InputWords.Find(Result[i]))
                {
                    Result.Delete(i);
                    i--;
                }

            Result.Sort();

            for (i = 0; i < Result.GetCount(); i++)
                printf("%s\n", Result[i].GetASCIIZPointer());
        }
    }

    //	Otherwise, output the generator as XML

    else
    {
        CMemoryWriteStream Output;
        if (Output.Create() != NOERROR)
        {
            printf("ERROR: Out of memory.\n");
            return;
        }

        if (Generator.WriteAsXML(&Output) != NOERROR)
        {
            printf("ERROR: Unable to output generator as XML.\n");
            return;
        }

        Output.Write("\0", 1);
        printf(Output.GetPointer());
    }
}
bool IDockScreenDisplay::ParseBackgrounDesc (ICCItem *pDesc, SBackgroundDesc *retDesc)

//	ParseBackroundDesc
//
//	Parses a descriptor. Returns TRUE if successful.

	{
	CCodeChain &CC = g_pUniverse->GetCC();

	//	Nil means no default value

	if (pDesc->IsNil())
		retDesc->iType = backgroundDefault;

	//	If we have a struct, we expect a certain format

	else if (pDesc->IsSymbolTable())
		{
		CString sType = pDesc->GetStringAt(FIELD_TYPE);
		if (sType.IsBlank() || strEquals(sType, TYPE_NONE))
			retDesc->iType = backgroundNone;

		else if (strEquals(sType, TYPE_HERO))
			{
			retDesc->iType = backgroundObjHeroImage;
			retDesc->pObj = CreateObjFromItem(CC, pDesc->GetElement(FIELD_OBJ));
			if (retDesc->pObj == NULL)
				return false;
			}
		else if (strEquals(sType, TYPE_IMAGE))
			{
			retDesc->iType = backgroundImage;

			ICCItem *pImage = pDesc->GetElement(FIELD_IMAGE);
			if (pImage == NULL)
				return false;

			else if (pImage->IsInteger())
				retDesc->dwImageID = pImage->GetIntegerValue();

			else
				return false;
			}
		else if (strEquals(sType, TYPE_OBJECT))
			{
			retDesc->pObj = CreateObjFromItem(CC, pDesc->GetElement(FIELD_OBJ));
			if (retDesc->pObj == NULL)
				return false;

            if (retDesc->pObj->IsPlayer())
    			retDesc->iType = backgroundObjSchematicImage;
            else
    			retDesc->iType = backgroundObjHeroImage;
			}
		else if (strEquals(sType, TYPE_SCHEMATIC))
			{
			retDesc->iType = backgroundObjSchematicImage;
			retDesc->pObj = CreateObjFromItem(CC, pDesc->GetElement(FIELD_OBJ));
			if (retDesc->pObj == NULL)
				return false;
			}
		else
			return false;
		}

	//	Otherwise, we can't parse.
	//
	//	LATER: We should eventually handle a list-based image descriptor, but we
	//	would need to enhance SBackgroundDesc for that.

	else
		return false;

	//	Success
	
	return true;
	}