CSpaceObject *IDockScreenDisplay::EvalListSource (const CString &sString, CString *retsError) // EvalListSource // // Returns the object from which we should display items { char *pPos = sString.GetPointer(); // See if we need to evaluate if (*pPos == '=') { CCodeChainCtx Ctx; Ctx.SetScreen(this); Ctx.SaveAndDefineSourceVar(m_pLocation); Ctx.SaveAndDefineDataVar(m_pData); ICCItem *pExp = Ctx.Link(sString, 1, NULL); ICCItem *pResult = Ctx.Run(pExp); // LATER:Event Ctx.Discard(pExp); if (pResult->IsError()) { *retsError = pResult->GetStringValue(); Ctx.Discard(pResult); return NULL; } // Convert to an object pointer CSpaceObject *pSource; if (strEquals(pResult->GetStringValue(), DATA_FROM_PLAYER)) pSource = m_pPlayer->GetShip(); else if (strEquals(pResult->GetStringValue(), DATA_FROM_STATION) || strEquals(pResult->GetStringValue(), DATA_FROM_SOURCE)) pSource = m_pLocation; else pSource = Ctx.AsSpaceObject(pResult); Ctx.Discard(pResult); return pSource; } // Otherwise, compare to constants else if (strEquals(sString, DATA_FROM_PLAYER)) return m_pPlayer->GetShip(); else return m_pLocation; }
bool IDockScreenDisplay::EvalBool (const CString &sCode, bool *retbResult, CString *retsError) // EvalBool // // Evaluates the given string { CCodeChainCtx Ctx; Ctx.SetScreen(m_pDockScreen); Ctx.SaveAndDefineSourceVar(m_pLocation); Ctx.SaveAndDefineDataVar(m_pData); char *pPos = sCode.GetPointer(); ICCItem *pExp = Ctx.Link(sCode, 1, NULL); ICCItem *pResult = Ctx.Run(pExp); // LATER:Event Ctx.Discard(pExp); if (pResult->IsError()) { *retsError = pResult->GetStringValue(); Ctx.Discard(pResult); return false; } *retbResult = !pResult->IsNil(); Ctx.Discard(pResult); return true; }
bool GetLinkedFireOptions (ICCItem *pArg, DWORD *retdwOptions, CString *retsError) // GetLinkedFireOptions // // Parses a list of linked fire options { int i; DWORD dwOptions = 0; if (pArg && !pArg->IsNil()) { SDesignLoadCtx LoadCtx; DWORD dwOption; for (i = 0; i < pArg->GetCount(); i++) { ICCItem *pOption = pArg->GetElement(i); if (CDeviceClass::ParseLinkedFireOptions(LoadCtx, pOption->GetStringValue(), &dwOption) != NOERROR) { *retsError = LoadCtx.sError; return false; } dwOptions |= dwOption; } } // Done *retdwOptions = dwOptions; return true; }
ALERROR CExtension::LoadGlobalsElement (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // LoadGlobalsElement // // Loads <Globals> { CCodeChainCtx CCCtx; // Parse the code and keep it ICCItem *pCode = CCCtx.Link(pDesc->GetContentText(0), 0, NULL); if (pCode->IsError()) { Ctx.sError = strPatternSubst(CONSTLIT("%s globals: %s"), Ctx.sErrorFilespec, pCode->GetStringValue()); return ERR_FAIL; } SGlobalsEntry *pEntry = m_Globals.Insert(); pEntry->pCode = pCode; pEntry->sFilespec = Ctx.sErrorFilespec; #ifdef DEBUG_GLOBALS ::kernelDebugLogMessage("Loading globals in %s", Ctx.sErrorFilespec); #endif return NOERROR; }
ICCItem *fnFind (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnFind // // Finds a target in a source { int i; CCodeChain *pCC = pCtx->pCC; // Get the source and target ICCItem *pSource = pArgs->GetElement(0); ICCItem *pTarget = pArgs->GetElement(1); // If this is a list, then look for the target in the list and // return the item position in the list int iPos; if (pSource->IsList()) { iPos = -1; for (i = 0; i < pSource->GetCount(); i++) { ICCItem *pItem = pSource->GetElement(i); if (HelperCompareItems(pItem, pTarget) == 0) { iPos = i; break; } } } // Otherwise, look for the target string in the source string else { iPos = strFind(pSource->GetStringValue(), pTarget->GetStringValue()); } // Done if (iPos == -1) return pCC->CreateNil(); else return pCC->CreateInteger(iPos); }
ICCItem *CCSymbolTable::UnstreamItem (CCodeChain *pCC, IReadStream *pStream) // UnstreamItem // // Unstream the sub-class specific data { ALERROR error; int i, iCount; // Read the count if (error = pStream->Read((char *)&iCount, sizeof(iCount), NULL)) return pCC->CreateSystemError(error); // Read all the items for (i = 0; i < iCount; i++) { ICCItem *pItem; CString sKey; CObject *pOldEntry; // Load the key pItem = pCC->UnstreamItem(pStream); if (pItem->IsError()) return pItem; sKey = pItem->GetStringValue(); pItem->Discard(pCC); // Now load the value pItem = pCC->UnstreamItem(pStream); // Note that we don't abort in case of an error // because the list might contain errors // Append the item to the symbol table if (m_Symbols.ReplaceEntry(sKey, pItem, TRUE, &pOldEntry) != NOERROR) return pCC->CreateMemoryError(); // No need to discard pItem because we're adding it to the // symbol table. // If we have a previous entry, decrement its refcount since we're // throwing it away ASSERT(pOldEntry == NULL); } // We are never a local symbol table m_bLocalFrame = FALSE; return pCC->CreateTrue(); }
void CEffectCreator::InitPainterParameters (CCreatePainterCtx &Ctx, IEffectPainter *pPainter) // InitPainterParameters // // Initialize painter parameters { SEventHandlerDesc Event; if (FindEventHandlerEffectType(evtGetParameters, &Event)) { CCodeChainCtx CCCtx; CCCtx.SaveAndDefineDataVar(Ctx.GetData()); ICCItem *pResult = CCCtx.Run(Event); if (pResult->IsError()) ::kernelDebugLogMessage(CONSTLIT("EffectType %x GetParameters: %s"), GetUNID(), (LPSTR)pResult->GetStringValue()); else if (pResult->IsSymbolTable()) { int i; CCSymbolTable *pTable = (CCSymbolTable *)pResult; for (i = 0; i < pTable->GetCount(); i++) { CString sParam = pTable->GetKey(i); ICCItem *pValue = pTable->GetElement(i); CEffectParamDesc Value; if (pValue->IsNil()) Value.InitNull(); else if (pValue->IsInteger()) Value.InitInteger(pValue->GetIntegerValue()); else if (pValue->IsIdentifier()) { CString sValue = pValue->GetStringValue(); char *pPos = sValue.GetASCIIZPointer(); // If this is a color, parse it if (*pPos == '#') Value.InitColor(::LoadRGBColor(sValue)); // Otherwise, a string else Value.InitString(sValue); } pPainter->SetParam(Ctx, sParam, Value); } } else ::kernelDebugLogMessage(CONSTLIT("EffectType %x GetParameters: Expected struct result."), GetUNID()); CCCtx.Discard(pResult); } }
ALERROR CDesignCollection::CreateTemplateTypes (SDesignLoadCtx &Ctx) // CreateTemplateTypes // // This is called inside of BindDesign to create all template types { ALERROR error; int i; // Create an appropriate context for running code CCodeChainCtx CCCtx; // Loop over all active types looking for templates. // NOTE: We cannot use the type-specific arrays because they have not been // set up yet (remember that we are inside of BindDesign). for (i = 0; i < m_AllTypes.GetCount(); i++) { CDesignType *pTemplate = m_AllTypes.GetEntry(i); if (pTemplate->GetType() != designTemplateType) continue; // Get the function to generate the type source CString sSource; SEventHandlerDesc Event; if (pTemplate->FindEventHandler(GET_TYPE_SOURCE_EVENT, &Event)) { ICCItem *pResult = CCCtx.Run(Event); if (pResult->IsError()) { Ctx.sError = strPatternSubst(CONSTLIT("GetTypeSource (%x): %s"), pTemplate->GetUNID(), pResult->GetStringValue()); return ERR_FAIL; } else if (pResult->IsNil()) sSource = NULL_STR; else sSource = pResult->GetStringValue(); CCCtx.Discard(pResult); } // Define the type if (!sSource.IsBlank()) { if (error = AddDynamicType(pTemplate->GetExtension(), pTemplate->GetUNID(), sSource, true, &Ctx.sError)) return error; } } return NOERROR; }
bool CCodeChainCtx::RunEvalString (const CString &sString, bool bPlain, CString *retsResult) // RunString // // If sString starts with '=' or if bPlain is TRUE, then we evaluate sString as an // expression. If success (no error) we return TRUE. Otherwise, we return FALSE and // the error is in retsResult. { char *pPos = sString.GetPointer(); if (bPlain || *pPos == '=') { ICCItem *pExp = Link(sString, (bPlain ? 0 : 1), NULL); ICCItem *pResult = Run(pExp); // LATER:Event Discard(pExp); if (pResult->IsError()) { *retsResult = pResult->GetStringValue(); Discard(pResult); return false; } // Note: We use GetStringValue instead of Unlink because we don't // want to preserve CC semantics (e.g., we don't need strings to // be quoted). *retsResult = pResult->GetStringValue(); Discard(pResult); return true; } else { *retsResult = strCEscapeCodes(sString); return true; } }
ALERROR CEventHandler::AddEvent (const CString &sEvent, const CString &sCode, CString *retsError) // AddEvent // // Adds an event { ICCItem *pCode = g_pUniverse->GetCC().Link(sCode, 0, NULL); if (pCode->IsError()) { if (retsError) *retsError = pCode->GetStringValue(); return ERR_FAIL; } m_Handlers.Insert(sEvent, pCode); return NOERROR; }
ALERROR CUniverse::LoadGlobals (SDesignLoadCtx &Ctx, CXMLElement *pElement) // LoadGlobals // // Load global code { ICCItem *pCode = m_CC.Link(pElement->GetContentText(0), 0, NULL); ICCItem *pResult = m_CC.TopLevel(pCode, &g_pUniverse); if (pResult->IsError()) { Ctx.sError = pResult->GetStringValue(); return ERR_FAIL; } pResult->Discard(&m_CC); return NOERROR; }
void CAdventureDesc::FireOnGameStart (void) // FireOnGameStart // // Fire OnGameStart event { SEventHandlerDesc Event; if (FindEventHandler(ON_GAME_START_EVENT, &Event)) { CCodeChainCtx Ctx; // Run code ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) kernelDebugLogMessage("OnGameStart error: %s", pResult->GetStringValue()); Ctx.Discard(pResult); } }
CString CListWrapper::GetDescAtCursor (void) // GetDescAtCursor // // Returns the description of the list element { if (IsCursorValid()) { ICCItem *pItem = m_pList->GetElement(m_iCursor); if (DESC_INDEX < pItem->GetCount()) { ICCItem *pDesc = pItem->GetElement(DESC_INDEX); if (pDesc->IsNil()) return NULL_STR; return pDesc->GetStringValue(); } } return NULL_STR; }
CString CListWrapper::GetTitleAtCursor (void) // GetTitleAtCursor // // Returns the title of the list element { if (IsCursorValid()) { ICCItem *pItem = m_pList->GetElement(m_iCursor); if (TITLE_INDEX < pItem->GetCount()) { ICCItem *pTitle = pItem->GetElement(TITLE_INDEX); if (pTitle->IsNil()) return NULL_STR; return pTitle->GetStringValue(); } } return NULL_STR; }
ALERROR CEventHandler::InitFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // InitFromXML // // Load all handlers { int i; for (i = 0; i < pDesc->GetContentElementCount(); i++) { CXMLElement *pHandler = pDesc->GetContentElement(i); ICCItem *pCode = g_pUniverse->GetCC().Link(pHandler->GetContentText(0), 0, NULL); if (pCode->IsError()) { Ctx.sError = strPatternSubst("<%s> event: %s", pHandler->GetTag(), pCode->GetStringValue()); return ERR_FAIL; } // If this is an old extension, then make sure the code is not using the // gStation variable, because we no longer support it if (Ctx.pExtension && Ctx.pExtension->dwVersion < 2) { if (g_pUniverse->GetCC().HasIdentifier(pCode, CONSTLIT("gStation"))) { Ctx.sError = CONSTLIT("gStation variable has been deprecated--use gSource instead."); return ERR_FAIL; } } // Done m_Handlers.Insert(pHandler->GetTag(), pCode); } return NOERROR; }
void CAdventureDesc::FireOnGameEnd (const CGameRecord &Game, const SBasicGameStats &BasicStats) // FireOnGameEnd // // Fire OnGameEnd event { SEventHandlerDesc Event; if (FindEventHandler(ON_GAME_END_EVENT, &Event)) { CCodeChainCtx Ctx; // Initialize variables Ctx.DefineInteger(CONSTLIT("aScore"), Game.GetScore()); Ctx.DefineInteger(CONSTLIT("aResurrectCount"), Game.GetResurrectCount()); Ctx.DefineInteger(CONSTLIT("aSystemsVisited"), BasicStats.iSystemsVisited); Ctx.DefineInteger(CONSTLIT("aEnemiesDestroyed"), BasicStats.iEnemiesDestroyed); Ctx.DefineInteger(CONSTLIT("aBestEnemiesDestroyed"), BasicStats.iBestEnemyDestroyedCount); if (BasicStats.dwBestEnemyDestroyed) Ctx.DefineInteger(CONSTLIT("aBestEnemyClass"), BasicStats.dwBestEnemyDestroyed); else Ctx.DefineNil(CONSTLIT("aBestEnemyClass")); Ctx.DefineString(CONSTLIT("aEndGameReason"), Game.GetEndGameReason()); Ctx.DefineString(CONSTLIT("aEpitaph"), Game.GetEndGameEpitaph()); Ctx.DefineString(CONSTLIT("aEpitaphOriginal"), Game.GetEndGameEpitaph()); Ctx.DefineString(CONSTLIT("aTime"), Game.GetPlayTimeString()); // Invoke ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) kernelDebugLogMessage("OnGameEnd error: %s", pResult->GetStringValue()); Ctx.Discard(pResult); } }
ALERROR CExtension::ExecuteGlobals (SDesignLoadCtx &Ctx) // ExecuteGlobals // // Execute the globals { DEBUG_TRY int i; CCodeChainCtx CCCtx; // Add a hook so that all lambda expressions defined in this global block // are wrapped with something that sets the extension UNID to the context. if (m_iType != extBase) CCCtx.SetGlobalDefineWrapper(this); // Run the code (which will likely define a bunch of functions) for (i = 0; i < m_Globals.GetCount(); i++) { ICCItem *pResult = CCCtx.Run(m_Globals[i].pCode); if (pResult->IsError()) { Ctx.sError = strPatternSubst(CONSTLIT("%s globals: %s"), m_Globals[i].sFilespec, pResult->GetStringValue()); return ERR_FAIL; } CCCtx.Discard(pResult); } // Done return NOERROR; DEBUG_CATCH }
bool CDockPane::SetControlValue (const CString &sID, ICCItem *pValue) // SetControlValue // // Sets the value of the given control. Return FALSE if we could not find a // control of the given ID. { CCodeChain &CC = g_pUniverse->GetCC(); SControl *pControl; if (!FindControl(sID, &pControl)) return false; switch (pControl->iType) { case controlCounter: { CGTextArea *pTextArea = pControl->AsTextArea(); CString sText = strFromInt(pValue->GetIntegerValue()); pTextArea->SetText(sText); pControl->bReplaceInput = true; return true; } case controlDesc: { CGTextArea *pTextArea = pControl->AsTextArea(); CUIHelper UIHelper(*g_pHI); CString sRTF; UIHelper.GenerateDockScreenRTF(pValue->GetStringValue(), &sRTF); pTextArea->SetRichText(sRTF); return true; } case controlItemDisplay: { CGItemDisplayArea *pItemDisplayArea = pControl->AsItemDisplayArea(); // Nil means nil if (pValue->IsNil()) { pItemDisplayArea->SetItem(NULL, CItem::NullItem()); return true; } // If a structure, we expect two fields: else if (pValue->IsSymbolTable()) { ICCItem *pItemCC = pValue->GetElement(CONSTLIT("item")); if (pItemCC == NULL) { CString sTitle; CString sDesc; // If no item, then we expect title and desc ICCItem *pTitleCC = pValue->GetElement(CONSTLIT("title")); if (pTitleCC) sTitle = pTitleCC->GetStringValue(); ICCItem *pDescCC = pValue->GetElement(CONSTLIT("desc")); if (pDescCC) sDesc = pDescCC->GetStringValue(); pItemDisplayArea->SetItem(NULL, CItem::NullItem()); pItemDisplayArea->SetText(sTitle, sDesc); return true; } CItem Item = ::CreateItemFromList(CC, pItemCC); CSpaceObject *pSource = NULL; ICCItem *pSourceCC = pValue->GetElement(CONSTLIT("source")); if (pSourceCC) pSource = ::CreateObjFromItem(CC, pSourceCC); pItemDisplayArea->SetItem(pSource, Item); return true; } // If this is a list then we expect an item value else if (pValue->IsList()) { CItem Item = ::CreateItemFromList(CC, pValue); pItemDisplayArea->SetItem(NULL, Item); return true; } return false; } case controlTextInput: { CGTextArea *pTextArea = pControl->AsTextArea(); CString sValue = pValue->GetStringValue(); pTextArea->SetText(sValue); pTextArea->SetCursor(0, sValue.GetLength()); return true; } } return false; }
ALERROR CLanguageDataBlock::InitFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // InitFromXML // // Initializes from an XML block { int i; for (i = 0; i < pDesc->GetContentElementCount(); i++) { CXMLElement *pItem = pDesc->GetContentElement(i); CString sID = pItem->GetAttribute(ID_ATTRIB); if (sID.IsBlank()) { Ctx.sError = strPatternSubst(CONSTLIT("Invalid id in <Language> block")); return ERR_FAIL; } if (strEquals(pItem->GetTag(), TEXT_TAG)) { // Link the code CCodeChainCtx CCCtx; ICCItem *pCode = CCCtx.Link(pItem->GetContentText(0), 0, NULL); if (pCode->IsError()) { Ctx.sError = strPatternSubst(CONSTLIT("Language id: %s : %s"), sID, pCode->GetStringValue()); return ERR_FAIL; } // Add an entry bool bIsNew; SEntry *pEntry = m_Data.SetAt(sID, &bIsNew); if (!bIsNew) { Ctx.sError = strPatternSubst(CONSTLIT("Duplicate <Language> element: %s"), sID); return ERR_FAIL; } // If pCode is a string and not an identifier, then we can just // store it directly. if (pCode->IsIdentifier() && pCode->IsQuoted()) { pEntry->pCode = NULL; pEntry->sText = pCode->GetStringValue(); } // Otherwise we store the code else pEntry->pCode = pCode->Reference(); // Done CCCtx.Discard(pCode); } else if (strEquals(pItem->GetTag(), MESSAGE_TAG)) { // Add an entry bool bIsNew; SEntry *pEntry = m_Data.SetAt(sID, &bIsNew); if (!bIsNew) { Ctx.sError = strPatternSubst(CONSTLIT("Duplicate <Language> element: %s"), sID); return ERR_FAIL; } // Set the text pEntry->pCode = NULL; pEntry->sText = pItem->GetAttribute(TEXT_ATTRIB); } else { Ctx.sError = strPatternSubst(CONSTLIT("Invalid element in <Language> block: <%s>"), pItem->GetTag()); return ERR_FAIL; } } return NOERROR; }
CLanguageDataBlock::ETranslateResult CLanguageDataBlock::Translate (CSpaceObject *pObj, const CString &sID, TArray<CString> *retText, CString *retsText) const // Translate // // Translates an entry to either a string or an array of strings. { int i; // If we can't find this ID then we can't translate SEntry *pEntry = m_Data.GetAt(sID); if (pEntry == NULL) return resultNotFound; // If we don't want the text back then all we need to do is return that we // have the text. if (retText == NULL && retsText == NULL) return resultFound; // If we don't need to run code then we just return the string. if (pEntry->pCode == NULL) { if (retsText) { *retsText = ::ComposePlayerNameString(pEntry->sText, g_pUniverse->GetPlayerName(), g_pUniverse->GetPlayerGenome()); return resultString; } else return resultFound; } // Otherwise we have to run some code CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(pObj); Ctx.DefineString(CONSTLIT("aTextID"), sID); ICCItem *pResult = Ctx.Run(pEntry->pCode); // LATER:Event ETranslateResult iResult; // Nil if (pResult->IsNil()) iResult = resultNotFound; // List of strings else if (pResult->GetCount() > 1) { if (retText) { CString sPlayerName = g_pUniverse->GetPlayerName(); GenomeTypes iPlayerGenome = g_pUniverse->GetPlayerGenome(); retText->DeleteAll(); retText->InsertEmpty(pResult->GetCount()); for (i = 0; i < pResult->GetCount(); i++) retText->GetAt(i) = ::ComposePlayerNameString(pResult->GetElement(i)->GetStringValue(), sPlayerName, iPlayerGenome); iResult = resultArray; } else iResult = resultFound; } // String else { if (retsText) { *retsText = ::ComposePlayerNameString(pResult->GetStringValue(), g_pUniverse->GetPlayerName(), g_pUniverse->GetPlayerGenome()); iResult = resultString; } else iResult = resultFound; } // Done Ctx.Discard(pResult); return iResult; }
ICCItem *fnPageMap (CEvalContext *pEvalCtx, ICCItem *pArgs, DWORD dwData) // fnPageMap // // (pageMap address|pageID enumMethod ['excludeNil] var exp) -> filtered list { CCodeChain *pCC = pEvalCtx->pCC; // Args ICCItem *pAddress = pArgs->GetElement(0); ICCItem *pMethod = pArgs->GetElement(1); bool bExcludeNil; int iOptionalArg = 2; if (pArgs->GetCount() > 4) bExcludeNil = strEquals(pArgs->GetElement(iOptionalArg++)->GetStringValue(), CONSTLIT("excludeNil")); else bExcludeNil = false; ICCItem *pVar = pArgs->GetElement(iOptionalArg++); ICCItem *pBody = pArgs->GetElement(iOptionalArg++); // Open the page IPage *pPage; CString sError; if (g_PM.OpenPage(pAddress->GetStringValue(), &pPage, &sError) != NOERROR) return pCC->CreateError(sError, NULL); // Prepare the method SPageEnumCtx EnumCtx; if (pPage->EnumReset(*pCC, pMethod, EnumCtx, &sError)) { g_PM.ClosePage(pPage); return pCC->CreateError(sError, NULL); } // Create a destination list ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) { g_PM.ClosePage(pPage); return pResult; } CCLinkedList *pList = (CCLinkedList *)pResult; // Setup the locals. We start by creating a local symbol table ICCItem *pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) { pResult->Discard(pCC); g_PM.ClosePage(pPage); return pLocalSymbols; } // Associate the enumaration variable ICCItem *pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pLocalSymbols->Discard(pCC); pResult->Discard(pCC); g_PM.ClosePage(pPage); return pError; } pError->Discard(pCC); // Setup the context if (pEvalCtx->pLocalSymbols) pLocalSymbols->SetParent(pEvalCtx->pLocalSymbols); else pLocalSymbols->SetParent(pEvalCtx->pLexicalSymbols); ICCItem *pOldSymbols = pEvalCtx->pLocalSymbols; pEvalCtx->pLocalSymbols = pLocalSymbols; // Get the offset of the variable so we don't have to // search for it all the time int iVarOffset = pLocalSymbols->FindOffset(pCC, pVar); // Enumerate the page while (pPage->EnumHasMore(EnumCtx)) { ICCItem *pItem = pPage->EnumGetNext(*pCC, EnumCtx); if (pItem->IsError()) { pResult->Discard(pCC); pResult = pItem; break; } // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); // Eval ICCItem *pMapped = pCC->Eval(pEvalCtx, pBody); if (pMapped->IsError()) { pItem->Discard(pCC); pResult->Discard(pCC); pResult = pMapped; break; } // If the evaluation is not Nil, then we include the // item in the result if (!bExcludeNil || !pMapped->IsNil()) pList->Append(*pCC, pMapped); pItem->Discard(pCC); pMapped->Discard(pCC); } // Clean up pEvalCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); g_PM.ClosePage(pPage); // Done if (pResult->GetCount() > 0) return pResult; else { pResult->Discard(pCC); return pCC->CreateNil(); } }
ICCItem *fnPageGet (CEvalContext *pEvalCtx, ICCItem *pArgs, DWORD dwData) // fnPageGet // // (pageGet address|pageID enumMethod [startIndex] [count]) -> list { CCodeChain *pCC = pEvalCtx->pCC; // Args ICCItem *pAddress = pArgs->GetElement(0); ICCItem *pMethod = pArgs->GetElement(1); int iStart = (pArgs->GetCount() > 2 ? pArgs->GetElement(2)->GetIntegerValue() : 0); int iCount = (pArgs->GetCount() > 3 ? pArgs->GetElement(3)->GetIntegerValue() : -1); // Open the page IPage *pPage; CString sError; if (g_PM.OpenPage(pAddress->GetStringValue(), &pPage, &sError) != NOERROR) return pCC->CreateError(sError, NULL); // Prepare the method SPageEnumCtx EnumCtx; if (pPage->EnumReset(*pCC, pMethod, EnumCtx, &sError)) { g_PM.ClosePage(pPage); return pCC->CreateError(sError, NULL); } // Create a destination list ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) { g_PM.ClosePage(pPage); return pResult; } CCLinkedList *pList = (CCLinkedList *)pResult; // Enumerate the page while ((iCount == -1 || iCount > 0) && pPage->EnumHasMore(EnumCtx)) { ICCItem *pItem = pPage->EnumGetNext(*pCC, EnumCtx); if (pItem->IsError()) { pResult->Discard(pCC); pResult = pItem; break; } // Add to list if (iStart == 0) { pList->Append(*pCC, pItem); iCount--; } else iStart--; pItem->Discard(pCC); } // Clean up g_PM.ClosePage(pPage); // Done if (pResult->GetCount() > 0) return pResult; else { pResult->Discard(pCC); return pCC->CreateNil(); } }
bool CWeaponFireDesc::FireOnDamageShields (SDamageCtx &Ctx, int iDevice) // FireOnDamageShields // // Fire OnDamageShields event. Returns TRUE if we should skip further shields damage { SEventHandlerDesc Event; if (FindEventHandler(evtOnDamageShields, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CItemListManipulator ItemList(Ctx.pObj->GetItemList()); CShip *pShip = Ctx.pObj->AsShip(); if (pShip) pShip->SetCursorAtDevice(ItemList, iDevice); CCCtx.SaveAndDefineSourceVar(Ctx.pObj); CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit); CCCtx.DefineInteger(CONSTLIT("aDevice"), iDevice); CCCtx.DefineItem(CONSTLIT("aDeviceItem"), ItemList.GetItemAtCursor()); CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause); CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj()); CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL)); CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos); CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection); CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage); CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType())); CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType()); CCCtx.DefineInteger(CONSTLIT("aShieldHP"), Ctx.iHPLeft); CCCtx.DefineInteger(CONSTLIT("aShieldDamageHP"), Ctx.iShieldDamage); CCCtx.DefineInteger(CONSTLIT("aArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb); if (Ctx.bReflect) { CCCtx.DefineString(CONSTLIT("aShieldReflect"), STR_SHIELD_REFLECT); CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iOriginalShieldDamage); CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iOriginalAbsorb); } else { CCCtx.DefineNil(CONSTLIT("aShieldReflect")); CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iShieldDamage); CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb); } ICCItem *pResult = CCCtx.Run(Event); // If we return Nil, then we continue processing bool bResult; if (pResult->IsNil()) bResult = false; // If this is an integer, we pass damage to armor else if (pResult->IsInteger()) { Ctx.iDamage = pResult->GetIntegerValue(); bResult = true; } // If we return a list, then modify variables else if (pResult->IsList()) { // A single value means we modified the damage to armor if (pResult->GetCount() == 1) { if (strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT)) { Ctx.bReflect = true; Ctx.iAbsorb = Ctx.iDamage; Ctx.iShieldDamage = 0; } else { Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft)); if (Ctx.bReflect) { Ctx.bReflect = false; Ctx.iAbsorb = Ctx.iOriginalAbsorb; } } } // Two values mean we modified both damage to armor and shield damage else if (pResult->GetCount() == 2) { Ctx.bReflect = false; Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft)); Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(1)->GetIntegerValue())); } // Otherwise, we deal with reflection else { Ctx.bReflect = strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT); Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(1)->GetIntegerValue(), Ctx.iHPLeft)); Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(2)->GetIntegerValue())); } // Proceed with processing bResult = false; } // If this is the string "reflect" then we reflect else if (strEquals(pResult->GetStringValue(), STR_SHIELD_REFLECT)) { Ctx.bReflect = true; Ctx.iAbsorb = Ctx.iDamage; Ctx.iShieldDamage = 0; bResult = false; } // Otherwise, error else { Ctx.pObj->ReportEventError(ON_DAMAGE_OVERLAY_EVENT, pResult); bResult = true; } CCCtx.Discard(pResult); return bResult; } else return false; }
CString ComposePlayerNameString (const CString &sString, const CString &sPlayerName, int iGenome, ICCItem *pArgs) // ComposePlayerNameString // // Replaces the following variables: // // %name% player name // %he% he or she // %his% his or her (matching case) // %hers% his or hers (matching case) // %him% him or her (matching case) // %sir% sir or ma'am (matching case) // %man% man or woman (matching case) // %brother% brother or sister (matching case) // %% % { // Prepare output CString sOutput; int iOutLeft = sString.GetLength() * 2; char *pOut = sOutput.GetWritePointer(iOutLeft); // Compose. Loop once for each segment that we need to add bool bDone = false; bool bVar = false; char *pPos = sString.GetASCIIZPointer(); while (!bDone) { CString sVar; char *pSeg; char *pSegEnd; if (bVar) { ASSERT(*pPos == '%'); // Skip % pPos++; char *pStart = pPos; while (*pPos != '%' && *pPos != '\0') pPos++; sVar = CString(pStart, pPos - pStart); // Skip the next % if (*pPos == '%') { pPos++; bVar = false; } else bDone = true; bool bCapitalize = (*sVar.GetASCIIZPointer() >= 'A' && *sVar.GetASCIIZPointer() <= 'Z'); // Setup the segment depending on the variable if (sVar.IsBlank()) sVar = CONSTLIT("%"); else if (strEquals(sVar, CONSTLIT("name"))) sVar = sPlayerName; else if (strEquals(sVar, CONSTLIT("he"))) { if (iGenome == genomeHumanMale) sVar = CONSTLIT("he"); else sVar = CONSTLIT("she"); } else if (strEquals(sVar, CONSTLIT("sir"))) { if (iGenome == genomeHumanMale) sVar = CONSTLIT("sir"); else sVar = CONSTLIT("ma'am"); } else if (strEquals(sVar, CONSTLIT("man"))) { if (iGenome == genomeHumanMale) sVar = CONSTLIT("man"); else sVar = CONSTLIT("woman"); } else if (strEquals(sVar, CONSTLIT("his"))) { if (iGenome == genomeHumanMale) sVar = CONSTLIT("his"); else sVar = CONSTLIT("her"); } else if (strEquals(sVar, CONSTLIT("him"))) { if (iGenome == genomeHumanMale) sVar = CONSTLIT("him"); else sVar = CONSTLIT("her"); } else if (strEquals(sVar, CONSTLIT("hers"))) { if (iGenome == genomeHumanMale) sVar = CONSTLIT("his"); else sVar = CONSTLIT("hers"); } else if (strEquals(sVar, CONSTLIT("brother"))) { if (iGenome == genomeHumanMale) sVar = CONSTLIT("brother"); else sVar = CONSTLIT("sister"); } else if (strEquals(sVar, CONSTLIT("son"))) { if (iGenome == genomeHumanMale) sVar = CONSTLIT("son"); else sVar = CONSTLIT("daughter"); } else if (pArgs) { int iArg = strToInt(sVar, 0); if (iArg < 0) { iArg = -iArg; bCapitalize = true; } if (iArg > 0) { ICCItem *pArg = pArgs->GetElement(iArg + 1); if (pArg) sVar = pArg->GetStringValue(); } } // If we could not find a valid var, then we assume a // single % sign. else { sVar = CONSTLIT("%"); pPos = pStart; bDone = (*pPos == '\0'); bVar = false; bCapitalize = false; } // Capitalize, if necessary if (bCapitalize) sVar = strCapitalize(sVar); // Setup segment pSeg = sVar.GetASCIIZPointer(); pSegEnd = pSeg + sVar.GetLength(); } else { // Skip to the next variable or the end of the string pSeg = pPos; while (*pPos != '%' && *pPos != '\0') pPos++; if (*pPos == '\0') bDone = true; else bVar = true; pSegEnd = pPos; } // Add the next segment int iLen = pSegEnd - pSeg; if (iLen > 0) { if (iLen > iOutLeft) { int iAlloc = sOutput.GetLength(); int iCurLen = iAlloc - iOutLeft; int iNewAlloc = max(iAlloc * 2, iAlloc + iLen); pOut = sOutput.GetWritePointer(iNewAlloc); pOut += iCurLen; iOutLeft = iNewAlloc - iCurLen; } while (pSeg < pSegEnd) *pOut++ = *pSeg++; iOutLeft -= iLen; } } // Done int iAlloc = sOutput.GetLength(); int iCurLen = iAlloc - iOutLeft; sOutput.Truncate(iCurLen); return sOutput; }
void CRandomEnhancementGenerator::EnhanceItem (CItem &Item) // EnhanceItem // // Enhances the given item { // See if this item is enhanced if (mathRandom(1, 100) > m_iChance) return; // If we have code, execute the code to figure out the mod if (m_pCode) { CCodeChainCtx Ctx; // Save the previous value of gItem Ctx.SaveItemVar(); Ctx.DefineItem(Item); // Execute the code ICCItem *pResult = Ctx.Run(m_pCode); // LATER:Event // If we have an error, report it DWORD dwMods; if (pResult->IsError()) { CString sError = strPatternSubst(CONSTLIT("Generate Enhancement: %s"), pResult->GetStringValue()); kernelDebugLogMessage(sError); dwMods = 0; } // Otherwise, the result code is the mods else dwMods = (DWORD)pResult->GetIntegerValue(); // Done with code Ctx.Discard(pResult); // Enhance the item Item.AddEnhancement(dwMods); } // Otherwise, if we have a constant mod, apply that else if (m_dwMods) { Item.AddEnhancement(m_dwMods); } // Otherwise, we need to generate a random mod appropriate to the // particular item else { DWORD dwMods; CItemType *pType = Item.GetType(); int iRoll = mathRandom(1, 100); switch (pType->GetCategory()) { case itemcatArmor: case itemcatShields: if (iRoll < 40) // HP + 10% dwMods = 0x0101; else if (iRoll < 65) // HP + 20% dwMods = 0x0102; else if (iRoll < 80) // HP + 30% dwMods = 0x0103; else if (iRoll < 90) // Damage Adj at 50% (and 75%) dwMods = 0x0A05 + (mathRandom(0, 3) << 4); else if (iRoll < 95) // Immunity to special ion attacks dwMods = 0x0C00; else // Regeneration dwMods = 0x0200; break; case itemcatWeapon: if (iRoll < 50) // Damage + 10% dwMods = 0x0101; else if (iRoll < 80) // Damage + 20% dwMods = 0x0102; else if (iRoll < 95) // Damage + 30% dwMods = 0x0103; else // Delay time at 70% of original dwMods = 0x1003; break; default: dwMods = 0; } Item.AddEnhancement(dwMods); } }
void RunFile (const CString &sFilespec, bool bNoLogo) { ALERROR error; CCodeChain &CC = g_pUniverse->GetCC(); CCodeChainCtx Ctx; // Verify the file CString sRunFile = sFilespec; if (!strEndsWith(sRunFile, CONSTLIT(".")) && pathGetExtension(sRunFile).IsBlank()) sRunFile.Append(CONSTLIT(".tlisp")); // Open the file CFileReadBlock InputFile(sRunFile); if (error = InputFile.Open()) { printf("error : Unable to open file '%s'.\n", sRunFile.GetASCIIZPointer()); return; } if (!bNoLogo) printf("%s\n", sRunFile.GetASCIIZPointer()); // Parse CString sInputFile(InputFile.GetPointer(0), InputFile.GetLength(), TRUE); CString sOutput; int iOffset = 0; while (true) { int iCharCount; ICCItem *pCode = Ctx.Link(sInputFile, iOffset, &iCharCount); if (pCode->IsNil()) break; else if (pCode->IsError()) { printf("error : %s\n", pCode->GetStringValue().GetASCIIZPointer()); Ctx.Discard(pCode); return; } iOffset += iCharCount; // Execute ICCItem *pResult = Ctx.Run(pCode); // Compose output if (pResult->IsIdentifier()) sOutput = pResult->Print(&CC, PRFLAG_NO_QUOTES | PRFLAG_ENCODE_FOR_DISPLAY); else sOutput = CC.Unlink(pResult); // Free Ctx.Discard(pResult); Ctx.Discard(pCode); } // Output result printf("%s\n", sOutput.GetASCIIZPointer()); }
ICCItem *CCLambda::Execute (CEvalContext *pCtx, ICCItem *pArgs) // Execute // // Executes the function and returns a result { CCodeChain *pCC = pCtx->pCC; ICCItem *pItem; ICCItem *pOldSymbols; ICCItem *pLocalSymbols; ICCItem *pVar; ICCItem *pArg; ICCItem *pResult; int i; BOOL bNoEval; // We must have been initialized if (m_pArgList == NULL || m_pCode == NULL) return pCC->CreateNil(); // If the argument list if quoted, then it means that the arguments // have already been evaluated. This happens if we've been called by // (apply). bNoEval = pArgs->IsQuoted(); // Set up the symbol table pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) return pLocalSymbols; // Loop over each item and associate it for (i = 0; i < m_pArgList->GetCount(); i++) { pVar = m_pArgList->GetElement(i); pArg = pArgs->GetElement(i); // If the name of this variable is %args, then the rest of the arguments // should go into a list if (strCompareAbsolute(pVar->GetStringValue(), CONSTLIT("%args")) == 0) { ICCItem *pVarArgs; // If there are arguments left, add them to a list if (pArg) { int j; ICCItem *pError; CCLinkedList *pList; // Create a list pVarArgs = pCC->CreateLinkedList(); if (pVarArgs->IsError()) { pLocalSymbols->Discard(pCC); return pVarArgs; } pList = (CCLinkedList *)pVarArgs; // Add each argument to the list for (j = i; j < pArgs->GetCount(); j++) { pArg = pArgs->GetElement(j); if (bNoEval) pResult = pArg->Reference(); else pResult = pCC->Eval(pCtx, pArg); pList->Append(pCC, pResult, &pError); pResult->Discard(pCC); if (pError->IsError()) { pVarArgs->Discard(pCC); pLocalSymbols->Discard(pCC); return pError; } pError->Discard(pCC); } } else pVarArgs = pCC->CreateNil(); // Add to the local symbol table pItem = pLocalSymbols->AddEntry(pCC, pVar, pVarArgs); pVarArgs->Discard(pCC); } // Bind the variable to the argument else if (pArg == NULL) pItem = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); else { ICCItem *pResult; // Evaluate the arg and add to the table if (bNoEval) pResult = pArg->Reference(); else pResult = pCC->Eval(pCtx, pArg); pItem = pLocalSymbols->AddEntry(pCC, pVar, pResult); pResult->Discard(pCC); } // Check for error if (pItem->IsError()) { pLocalSymbols->Discard(pCC); return pItem; } pItem->Discard(pCC); } // Setup the context pLocalSymbols->SetParent(pCtx->pLexicalSymbols); pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Evalute the code pResult = pCC->Eval(pCtx, m_pCode); // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); return pResult; }
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; }