void CListWrapper::PaintImageAtCursor (CG16bitImage &Dest, int x, int y) // PaintImageAtCursor // // Paints the image for the current element { if (!IsCursorValid()) return; ICCItem *pItem = m_pList->GetElement(m_iCursor); if (pItem->GetCount() <= ICON_INDEX) return; ICCItem *pIcon = pItem->GetElement(ICON_INDEX); if (pIcon->GetCount() < IMAGE_ELEMENTS) return; CG16bitImage *pImage = g_pUniverse->GetLibraryBitmap(pIcon->GetElement(IMAGE_UNID_INDEX)->GetIntegerValue()); if (pImage == NULL) return; Dest.ColorTransBlt(pIcon->GetElement(IMAGE_X_INDEX)->GetIntegerValue(), pIcon->GetElement(IMAGE_Y_INDEX)->GetIntegerValue(), ICON_WIDTH, ICON_HEIGHT, 255, *pImage, x, y); }
ICCItem *fnAtmCreate (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnAtmCreate // // Creates a new atom table // // (atmAtomTable ((atom1 entry1) (atom2 entry2) ... (atomn entryn))) -> atmtable { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pAtomTable; ICCItem *pList; int i; // Evaluate the argument pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("l")); if (pArgs->IsError()) return pArgs; // Create the table pAtomTable = pCC->CreateAtomTable(); if (pAtomTable->IsError()) return pAtomTable; // Add each entry pList = pArgs->Head(pCC); for (i = 0; i < pList->GetCount(); i++) { ICCItem *pPair = pList->GetElement(i); ICCItem *pResult; // Make sure we have two elements if (pPair->GetCount() != 2) { pAtomTable->Discard(pCC); return pCC->CreateError(CONSTLIT("Invalid format for atom table entry:"), pPair); } // Get the atom and the entry pResult = pAtomTable->AddEntry(pCC, pPair->GetElement(0), pPair->GetElement(1)); if (pResult->IsError()) { pAtomTable->Discard(pCC); return pResult; } pResult->Discard(pCC); } // Done pArgs->Discard(pCC); return pAtomTable; }
ICCItem *fnRandom (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnRandom // // (random from to) -> number // (random list) -> random item in list { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("*")); if (pArgs->IsError()) return pArgs; // Do stuff based on parameters if (pArgs->GetCount() == 2) { int iOp1 = pArgs->GetElement(0)->GetIntegerValue(); int iOp2 = pArgs->GetElement(1)->GetIntegerValue(); pArgs->Discard(pCC); pResult = pCC->CreateInteger(mathRandom(iOp1, iOp2)); } else if (pArgs->GetCount() == 1) { ICCItem *pList = pArgs->GetElement(0); if (pList->IsNil()) pResult = pCC->CreateNil(); else if (pList->GetCount() == 0) pResult = pCC->CreateNil(); else pResult = pList->GetElement(mathRandom(0, pList->GetCount()-1))->Reference(); pArgs->Discard(pCC); } else { pResult = pCC->CreateNil(); pArgs->Discard(pCC); } // Done return pResult; }
ICCItem *fnShuffle (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnShuffle // // Shuffles a list randomly { int i; CCodeChain *pCC = pCtx->pCC; if (pArgs->GetElement(0)->IsNil()) return pCC->CreateNil(); // Create a destination list ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) return pResult; CCLinkedList *pList = (CCLinkedList *)pResult; // Copy the list ICCItem *pSource = pArgs->GetElement(0); for (i = 0; i < pSource->GetCount(); i++) pList->Append(pCC, pSource->GetElement(i), NULL); // Shuffle the new list pList->Shuffle(pCC); // Done return pResult; }
ICCItem *fnAppend (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnAppend // // Appends two or more elements together { int i, j; CCodeChain *pCC = pCtx->pCC; // Create a new list to store the result in ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) return pResult; CCLinkedList *pList = (CCLinkedList *)pResult; // Loop over all arguments and add to result list for (i = 0; i < pArgs->GetCount(); i++) { ICCItem *pItem = pArgs->GetElement(i); for (j = 0; j < pItem->GetCount(); j++) pList->Append(pCC, pItem->GetElement(j), NULL); } // Done return pResult; }
ICCItem *fnCat (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnCat // // Concatenates the given strings // // (cat string1 string2 ... stringn) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; CString sResult; int i; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("*")); if (pArgs->IsError()) return pArgs; // Append each of the items for (i = 0; i < pArgs->GetCount(); i++) sResult.Append(pArgs->GetElement(i)->GetStringValue()); pResult = pCC->CreateString(sResult); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnCount (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnCount // // Returns the number of elements in the list // // (count list) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pList; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("l")); if (pArgs->IsError()) return pArgs; // The first argument is the list pList = pArgs->Head(pCC); pResult = pCC->CreateInteger(pList->GetCount()); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnSeededRandom (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnSeededRandom // // (seededRandom seed from to) -> number // (seededRandom seed list) -> random item in list { CCodeChain *pCC = pCtx->pCC; ICCItem *pResult; int iSeed = pArgs->GetElement(0)->GetIntegerValue(); // Do stuff based on parameters if (pArgs->GetCount() == 3) { int iOp1 = pArgs->GetElement(1)->GetIntegerValue(); int iOp2 = pArgs->GetElement(2)->GetIntegerValue(); pResult = pCC->CreateInteger(mathSeededRandom(iSeed, iOp1, iOp2)); } else if (pArgs->GetCount() == 2) { ICCItem *pList = pArgs->GetElement(1); if (pList->IsNil()) pResult = pCC->CreateNil(); else if (pList->GetCount() == 0) pResult = pCC->CreateNil(); else pResult = pList->GetElement(mathSeededRandom(iSeed, 0, pList->GetCount()-1))->Reference(); } else pResult = pCC->CreateNil(); // Done return 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()) return pItem->GetElement(DESC_INDEX)->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()) return pItem->GetElement(TITLE_INDEX)->GetStringValue(); } return NULL_STR; }
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); }
void CCommandLineDisplay::AutoCompleteSearch (void) // AutocompleteSearch // // Searches the global symbol table for matches to the current command. { const CString sCurCmd = GetCurrentCmd(); CString sCommon; CString sHelp; ClearHint(); if (sCurCmd.IsBlank()) return; // Get the list of global symbols ICCItem *pGlobals = g_pUniverse->GetCC().GetGlobals(); int iMatches = 0; for (int i = 0; i < pGlobals->GetCount(); i++) { CString sGlobal = pGlobals->GetKey(i); // Partial match if (strStartsWith(sGlobal, sCurCmd)) { if (iMatches == 0) sCommon = sGlobal; // If we have multiple matching commands then find the longest common stem else { int iLen = min(sCommon.GetLength(), sGlobal.GetLength()); char *pPos1 = sCommon.GetPointer(); char *pPos2 = sGlobal.GetPointer(); int i; for (i = 0; i < iLen; i++) { if (CharLower((LPTSTR)(BYTE)(*pPos1)) != CharLower((LPTSTR)(BYTE)(*pPos2))) break; pPos1++; pPos2++; } sCommon.Truncate(i); m_sHint.Append(CONSTLIT(" ")); } // Append the command to the auto complete hint m_sHint.Append(sGlobal); iMatches++; } if (strEquals(sGlobal, sCurCmd)) { // Exact match - get help text ICCItem *pItem = pGlobals->GetElement(i); if (pItem->IsPrimitive()) sHelp = pItem->GetHelp(); } } // If the common stem is longer than the current command, then auto complete if (sCommon.GetLength() > sCurCmd.GetLength()) Input(strSubString(sCommon, sCurCmd.GetLength(), -1)); // If we only have one match then no need to show hint as we have either // auto completed or will show help text insead if (iMatches == 1) m_sHint = NULL_STR; if (!sHelp.IsBlank()) { if (!m_sHint.IsBlank()) m_sHint.Append(CONSTLIT("\n")); m_sHint.Append(sHelp); } }
ICCItem *fnApply (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnApply // // Applies the given parameter list to the lambda expression // // (apply exp arg1 arg2 ... argn list) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pFunction; ICCItem *pLast; CCLinkedList *pList; int i; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("v*")); if (pArgs->IsError()) return pArgs; // We better have at least two arguments if (pArgs->GetCount() < 2) { pArgs->Discard(pCC); return pCC->CreateError(CONSTLIT("apply needs a function and a list of arguments."), NULL); } // The last argument better be a list pLast = pArgs->GetElement(pArgs->GetCount() - 1); if (!pLast->IsList()) { pArgs->Discard(pCC); return pCC->CreateError(CONSTLIT("Last argument for apply must be a list."), NULL); } // The first argument is the function pFunction = pArgs->Head(pCC); // Create a new list to store the arguments in pResult = pCC->CreateLinkedList(); if (pResult->IsError()) { pArgs->Discard(pCC); return pResult; } pList = (CCLinkedList *)pResult; // Add each of the arguments except the last for (i = 1; i < pArgs->GetCount() - 1; i++) { pList->Append(pCC, pArgs->GetElement(i), &pResult); if (pResult->IsError()) { pList->Discard(pCC); pArgs->Discard(pCC); return pResult; } pResult->Discard(pCC); } // Add each of the elements of the last list for (i = 0; i < pLast->GetCount(); i++) { pList->Append(pCC, pLast->GetElement(i), &pResult); if (pResult->IsError()) { pList->Discard(pCC); pArgs->Discard(pCC); return pResult; } pResult->Discard(pCC); } // Set the literal flag to indicate that the arguments should // not be evaluated. pList->SetQuoted(); // Execute the function if (pFunction->IsFunction()) pResult = pFunction->Execute(pCtx, pList); else pResult = pFunction->Reference(); pList->Discard(pCC); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnFilter (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnFilter // // Filters a list based on a boolean expression. // // (filter list var exp) -> list { int i; CCodeChain *pCC = pCtx->pCC; if (pArgs->GetElement(0)->IsNil()) return pCC->CreateNil(); // Args ICCItem *pSource = pArgs->GetElement(0); ICCItem *pVar = pArgs->GetElement(1); ICCItem *pBody = pArgs->GetElement(2); // Create a destination list ICCItem *pResult = pCC->CreateLinkedList(); if (pResult->IsError()) 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); return pLocalSymbols; } // Associate the enumaration variable ICCItem *pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pLocalSymbols->Discard(pCC); pResult->Discard(pCC); return pError; } pError->Discard(pCC); // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); ICCItem *pOldSymbols = pCtx->pLocalSymbols; pCtx->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); // Loop over all elements of the list for (i = 0; i < pSource->GetCount(); i++) { ICCItem *pItem = pSource->GetElement(i); // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); // Eval ICCItem *pSelect = pCC->Eval(pCtx, pBody); if (pSelect->IsError()) { pResult->Discard(pCC); pResult = pSelect; break; } // If the evaluation is not Nil, then we include the // item in the result if (!pSelect->IsNil()) pList->Append(pCC, pItem, NULL); pSelect->Discard(pCC); } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done if (pResult->GetCount() > 0) return pResult; else { pResult->Discard(pCC); return pCC->CreateNil(); } }
ICCItem *fnEnum (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnEnum // // Enumerates the elements of a list // // (enum list item-var exp) // (enumwhile list condition item-var exp) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; ICCItem *pResult; ICCItem *pVar; ICCItem *pBody; ICCItem *pList; ICCItem *pCondition; ICCItem *pLocalSymbols; ICCItem *pOldSymbols; ICCItem *pError; int i, iVarOffset; // Evaluate the arguments and validate them if (dwData == FN_ENUM_WHILE) { pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("vuqu")); if (pArgs->IsError()) return pArgs; pList = pArgs->GetElement(0); pCondition = pArgs->GetElement(1); pVar = pArgs->GetElement(2); pBody = pArgs->GetElement(3); } else { pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("vqu")); if (pArgs->IsError()) return pArgs; pList = pArgs->GetElement(0); pCondition = NULL; pVar = pArgs->GetElement(1); pBody = pArgs->GetElement(2); } // Setup the locals. We start by creating a local symbol table pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) { pArgs->Discard(pCC); return pLocalSymbols; } // Associate the enumaration variable pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pError->IsError()) { pArgs->Discard(pCC); return pError; } pError->Discard(pCC); // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Start with a default result pResult = pCC->CreateNil(); // Get the offset of the variable so we don't have to // search for it all the time iVarOffset = pLocalSymbols->FindOffset(pCC, pVar); // Loop over all elements of the list for (i = 0; i < pList->GetCount(); i++) { // Check the condition if (pCondition) { ICCItem *pEval; // Evaluate the condition pEval = pCC->Eval(pCtx, pCondition); if (pEval->IsError()) { pResult->Discard(pCC); pResult = pEval; break; } // If the condition is Nil, then we're done if (pEval->IsNil()) { pEval->Discard(pCC); break; } } ICCItem *pItem = pList->GetElement(i); // Clean up the previous result pResult->Discard(pCC); // Set the element pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem); // Eval pResult = pCC->Eval(pCtx, pBody); if (pResult->IsError()) break; } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done pArgs->Discard(pCC); return pResult; }
ICCItem *fnEquality (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnEquality // // Equality and inequality // // (eq exp1 exp2 ... expn) // (> exp1 exp2 ... expn) // (>= exp1 exp2 ... expn) // (< exp1 exp2 ... expn) // (<= exp1 exp2 ... expn) { CCodeChain *pCC = pCtx->pCC; ICCItem *pResult; ICCItem *pExp; ICCItem *pPrev = NULL; ICCItem *pArgs; int i; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("*")); if (pArgs->IsError()) return pArgs; // Loop over all arguments for (i = 0; i < pArgs->GetCount(); i++) { pExp = pArgs->GetElement(i); if (pExp->IsError()) { pExp->Reference(); pArgs->Discard(pCC); return pExp; } if (pPrev) { int iResult = HelperCompareItems(pPrev, pExp); BOOL bOk; switch (dwData) { case FN_EQUALITY_EQ: { bOk = (iResult == 0); break; } case FN_EQUALITY_LESSER: { bOk = (iResult < 0); break; } case FN_EQUALITY_LESSER_EQ: { bOk = (iResult <= 0); break; } case FN_EQUALITY_GREATER: { bOk = (iResult > 0); break; } case FN_EQUALITY_GREATER_EQ: { bOk = (iResult >= 0); break; } default: ASSERT(FALSE); } // If we don't have a match, return if (!bOk) { pArgs->Discard(pCC); return pCC->CreateNil(); } } // Remember the previous element so that we can compare pPrev = pExp; } // If we get here, then all items are ok pArgs->Discard(pCC); pResult = pCC->CreateTrue(); // Done return pResult; }
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; }
void CShieldClass::FireOnShieldDamage (CItemCtx &ItemCtx, SDamageCtx &Ctx) // FireOnShieldDamage // // Fire OnShieldDamage { SEventHandlerDesc Event; if (FindEventHandlerShieldClass(evtOnShieldDamage, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CCCtx.SaveAndDefineSourceVar(ItemCtx.GetSource()); CCCtx.SaveAndDefineItemVar(ItemCtx); CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit); 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 nothing if (pResult->IsNil()) NULL; // If an error, report it else if (pResult->IsError()) ItemCtx.GetSource()->ReportEventError(ON_SHIELD_DAMAGE_EVENT, pResult); // 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())); } } CCCtx.Discard(pResult); } }
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(); } }
ICCItem *fnBlock (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnBlock // // Evaluates a list of expressions // // (block (locals ...) exp1 exp2 ... expn) // (errblock (error locals ...) exp1 exp2 ... expn onerror) { CCodeChain *pCC = pCtx->pCC; ICCItem *pResult; ICCItem *pLocals; ICCItem *pExp; ICCItem *pLocalSymbols; ICCItem *pVar; ICCItem *pOldSymbols; int i; // The first argument must be a list of locals pLocals = pArguments->Head(pCC); if (pLocals == NULL || !pLocals->IsList()) return pCC->CreateError(CONSTLIT("Locals list expected:"), pLocals); // If this is an error block then we must have at least one local if (dwData == FN_BLOCK_ERRBLOCK && pLocals->GetCount() == 0) return pCC->CreateError(CONSTLIT("errblock must have an 'error' local variable"), NULL); // Now loop over the remaining arguments, evaluating each in turn pExp = pArguments->GetElement(1); // If there are no expressions, then we just return Nil if (pExp == NULL) return pCC->CreateNil(); // Setup the locals. We start by creating a local symbol table pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) return pLocalSymbols; pLocalSymbols->SetLocalFrame(); // Loop over each item and associate it for (i = 0; i < pLocals->GetCount(); i++) { ICCItem *pItem; pVar = pLocals->GetElement(i); pItem = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); if (pItem->IsError()) { pLocalSymbols->Discard(pCC); return pItem; } pItem->Discard(pCC); } // Setup the context if (pCtx->pLocalSymbols) pLocalSymbols->SetParent(pCtx->pLocalSymbols); else pLocalSymbols->SetParent(pCtx->pLexicalSymbols); pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Start with a default result pResult = pCC->CreateNil(); // Loop (starting with the second arg) for (i = 1; i < pArguments->GetCount(); i++) { pExp = pArguments->GetElement(i); // If this is an error block and this is the last expression, // then it must be error condition and we don't want to // execute it. if (i+1 == pArguments->GetCount() && dwData == FN_BLOCK_ERRBLOCK) break; // Evaluate the expression pResult->Discard(pCC); pResult = pCC->Eval(pCtx, pExp); // If we got an error, handle it if (pResult->IsError()) { // If this is an error block, then find the last expression // and evaluate it. if (dwData == FN_BLOCK_ERRBLOCK) { ICCItem *pItem; // Set the first local variable to be the error result pVar = pLocals->Head(pCC); pItem = pLocalSymbols->AddEntry(pCC, pVar, pResult); pItem->Discard(pCC); pResult->Discard(pCC); // Find the last expression pExp = pArguments->GetElement(pArguments->GetCount() - 1); // Evaluate it pResult = pCC->Eval(pCtx, pExp); } // Regardless, leave the block and return the result break; } } // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); // Done return pResult; }
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(); } }
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 *fnMathList (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData) // fnMathList // // Simple integer functions // // (add x1 x2 ... xn) -> z // (max x1 x2 ... xn) -> z // (min x1 x2 ... xn) -> z // (multiply x1 x2 .. .xn) -> z { int i; CCodeChain *pCC = pCtx->pCC; // Get the list ICCItem *pList; if (pArgs->GetElement(0)->IsList()) { pList = pArgs->GetElement(0); if (pList->GetCount() < 1) return pCC->CreateNil(); } else pList = pArgs; // Do the computation switch (dwData) { case FN_MATH_ADD: { int iResult = pList->GetElement(0)->GetIntegerValue(); for (i = 1; i < pList->GetCount(); i++) iResult += pList->GetElement(i)->GetIntegerValue(); return pCC->CreateInteger(iResult); } case FN_MATH_MULTIPLY: { int iResult = pList->GetElement(0)->GetIntegerValue(); for (i = 1; i < pList->GetCount(); i++) iResult *= pList->GetElement(i)->GetIntegerValue(); return pCC->CreateInteger(iResult); } case FN_MATH_MAX: { int iResult = pList->GetElement(0)->GetIntegerValue(); for (i = 1; i < pList->GetCount(); i++) { int iVal = pList->GetElement(i)->GetIntegerValue(); if (iVal > iResult) iResult = iVal; } return pCC->CreateInteger(iResult); } case FN_MATH_MIN: { int iResult = pList->GetElement(0)->GetIntegerValue(); for (i = 1; i < pList->GetCount(); i++) { int iVal = pList->GetElement(i)->GetIntegerValue(); if (iVal < iResult) iResult = iVal; } return pCC->CreateInteger(iResult); } default: ASSERT(false); return pCC->CreateNil(); } }