void CPlayerGameStats::OnKeyEvent (EEventTypes iType, CSpaceObject *pObj, DWORD dwCauseUNID)

//	OnKeyEvent
//
//	Adds a key event involving an object

	{
	ASSERT(pObj);

	CSystem *pSystem = pObj->GetSystem();
	if (pSystem == NULL)
		return;

	//	Get the NodeID where the event happened

	CTopologyNode *pNode = pSystem->GetTopology();
	if (pNode == NULL)
		return;

	const CString &sNodeID = pNode->GetID();

	//	Get the object's type

	CDesignType *pType = pObj->GetType();
	if (pType == NULL)
		return;

	//	Get the object's name

	DWORD dwNameFlags;
	CString sName = pObj->GetName(&dwNameFlags);
	
	//	If the object name is the same as the type name then we don't bother
	//	storing it in the event (to save memory)

	if (strEquals(sName, pType->GetTypeName()))
		{
		sName = NULL_STR;
		dwNameFlags = 0;
		}

	//	Look for the list of events for this NodeID

	TArray<SKeyEventStats> *pEventList = m_KeyEventStats.Set(sNodeID);
	SKeyEventStats *pStats = pEventList->Insert();
	pStats->iType = iType;
	pStats->dwTime = g_pUniverse->GetTicks();
	pStats->dwObjUNID = pObj->GetType()->GetUNID();
	pStats->sObjName = sName;
	pStats->dwObjNameFlags = dwNameFlags;
	pStats->dwCauseUNID = dwCauseUNID;
	}
ALERROR CMission::Create (CMissionType *pType,
                          CSpaceObject *pOwner,
                          ICCItem *pCreateData,
                          CMission **retpMission,
                          CString *retsError)

//	Create
//
//	Creates a new mission object. We return ERR_NOTFOUND if the mission could
//	not be created because conditions do not allow it.

{
    CMission *pMission;

    pMission = new CMission;
    if (pMission == NULL)
    {
        *retsError = CONSTLIT("Out of memory");
        return ERR_MEMORY;
    }

    pMission->m_pType = pType;

    //	Initialize

    pMission->m_iStatus = statusOpen;
    pMission->m_fIntroShown = false;
    pMission->m_fDeclined = false;
    pMission->m_fDebriefed = false;
    pMission->m_pOwner = pOwner;

    //	NodeID

    CTopologyNode *pNode = NULL;
    CSystem *pSystem = NULL;
    if ((pSystem = (pOwner ? pOwner->GetSystem() : g_pUniverse->GetCurrentSystem()))
            && (pNode = pSystem->GetTopology()))
        pMission->m_sNodeID = pNode->GetID();

    //	Fire OnCreate

    pMission->m_fInOnCreate = true;

    CSpaceObject::SOnCreate OnCreate;
    OnCreate.pData = pCreateData;
    OnCreate.pOwnerObj = pOwner;
    pMission->FireOnCreate(OnCreate);

    pMission->m_fInOnCreate = false;

    //	If OnCreate destroyed the object then it means that the mission was not
    //	suitable. We return ERR_NOTFOUND

    if (pMission->IsDestroyed())
    {
        delete pMission;
        return ERR_NOTFOUND;
    }

    //	If we haven't subscribed to the owner, do it now

    if (pOwner && !pOwner->FindEventSubscriber(pMission))
        pOwner->AddEventSubscriber(pMission);

    //	Done

    if (retpMission)
        *retpMission = pMission;

    return NOERROR;
}