ICCItem *CMission::FireOnReward (ICCItem *pData) // FireOnReward // // Fire <OnReward> // // Callers are responsible for discarding the result, if not NULL. { SEventHandlerDesc Event; if (FindEventHandler(EVENT_ON_REWARD, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(this); Ctx.SaveAndDefineDataVar(pData); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) { ReportEventError(EVENT_ON_REWARD, pResult); Ctx.Discard(pResult); return NULL; } return pResult; } return NULL; }
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; }
int CShieldClass::FireGetMaxHP (CInstalledDevice *pDevice, CSpaceObject *pSource, int iMaxHP) const // FireGetMaxHP // // Fire GetMaxHP event { SEventHandlerDesc Event; if (FindEventHandlerShieldClass(evtGetMaxHP, &Event)) { ASSERT(pSource); ASSERT(pDevice); CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(pSource); Ctx.SaveAndDefineItemVar(pSource->GetItemForDevice(pDevice)); Ctx.DefineInteger(CONSTLIT("aMaxHP"), iMaxHP); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) pSource->ReportEventError(GET_MAX_HP_EVENT, pResult); else if (!pResult->IsNil()) iMaxHP = Max(0, pResult->GetIntegerValue()); Ctx.Discard(pResult); } return iMaxHP; }
COverlayType *CDeviceClass::FireGetOverlayType (CItemCtx &ItemCtx) const // FireGetOverlayType // // Fire GetOverlayType event { SEventHandlerDesc Event; if (FindEventHandlerDeviceClass(evtGetOverlayType, &Event)) { // Setup arguments CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(ItemCtx.GetSource()); Ctx.SaveAndDefineItemVar(ItemCtx); ICCItem *pResult = Ctx.Run(Event); DWORD dwUNID = 0; if (pResult->IsError()) ItemCtx.GetSource()->ReportEventError(GET_OVERLAY_TYPE_EVENT, pResult); else if (!pResult->IsNil()) dwUNID = pResult->GetIntegerValue(); Ctx.Discard(pResult); // Done return COverlayType::AsType(g_pUniverse->FindDesignType(dwUNID)); } else return GetOverlayType(); }
bool CLanguageDataBlock::Translate (CSpaceObject *pObj, const CString &sID, ICCItem **retpResult) const // Translate // // Translates to an item. The caller is responsible for discarding. { // If we can't find this ID then we can't translate SEntry *pEntry = m_Data.GetAt(sID); if (pEntry == NULL) return false; // If we don't need to run code then we just return the string. if (pEntry->pCode == NULL) { *retpResult = g_pUniverse->GetCC().CreateString(pEntry->sText); return true; } // Otherwise we have to run some code CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(pObj); Ctx.DefineString(CONSTLIT("aTextID"), sID); *retpResult = Ctx.Run(pEntry->pCode); // LATER:Event return true; }
int CArmorClass::FireGetMaxHP (CItemCtx &ItemCtx, int iMaxHP) const // FireGetMaxHP // // Fire GetMaxHP event { SEventHandlerDesc Event; if (FindEventHandlerArmorClass(evtGetMaxHP, &Event)) { // Setup arguments CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(ItemCtx.GetSource()); Ctx.SaveAndDefineItemVar(ItemCtx); Ctx.DefineInteger(CONSTLIT("aMaxHP"), iMaxHP); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) ItemCtx.GetSource()->ReportEventError(GET_MAX_HP_EVENT, pResult); else if (!pResult->IsNil()) iMaxHP = Max(0, pResult->GetIntegerValue()); Ctx.Discard(pResult); } return iMaxHP; }
ICCItem *CMission::FireOnDeclined (void) // FireOnDeclined // // Fire <OnDeclined>. We return the result of the event, which might contain // instructions for the mission screen. // // Callers are responsible for discarding the result, if not NULL. { SEventHandlerDesc Event; if (FindEventHandler(EVENT_ON_DECLINED, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(this); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) { ReportEventError(EVENT_ON_DECLINED, pResult); Ctx.Discard(pResult); return NULL; } return pResult; } return NULL; }
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 CWeaponFireDesc::FireOnDamageOverlay (SDamageCtx &Ctx, CEnergyField *pOverlay) // FireOnDamageOverlay // // Fire OnDamageOverlay event. Returns TRUE if we should skip further overlay damage { SEventHandlerDesc Event; if (FindEventHandler(evtOnDamageOverlay, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CCCtx.SaveAndDefineSourceVar(Ctx.pObj); CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit); CCCtx.DefineInteger(CONSTLIT("aOverlayID"), pOverlay->GetID()); 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()); ICCItem *pResult = CCCtx.Run(Event); if (pResult->IsError()) Ctx.pObj->ReportEventError(ON_DAMAGE_OVERLAY_EVENT, pResult); // If we return Nil, then we continue processing bool bResult; if (pResult->IsNil()) bResult = false; // Otherwise, the result is the damage left else { Ctx.iDamage = pResult->GetIntegerValue(); bResult = true; } CCCtx.Discard(pResult); return bResult; } else return false; }
bool CWeaponFireDesc::FireOnFragment (const CDamageSource &Source, CSpaceObject *pShot, const CVector &vHitPos, CSpaceObject *pNearestObj, CSpaceObject *pTarget) // FireOnFragment // // Event fires when a shot fragments. If we return TRUE then we skip the default // fragmentation event. { SEventHandlerDesc Event; if (FindEventHandler(evtOnFragment, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CCCtx.SaveAndDefineSourceVar(pShot); CCCtx.DefineSpaceObject(CONSTLIT("aNearestObj"), pNearestObj); CCCtx.DefineSpaceObject(CONSTLIT("aTargetObj"), pTarget); CCCtx.DefineVector(CONSTLIT("aHitPos"), vHitPos); CCCtx.DefineInteger(CONSTLIT("aHitDir"), (pShot ? pShot->GetRotation() : 0)); CCCtx.DefineItemType(CONSTLIT("aWeaponType"), GetWeaponType()); CCCtx.DefineString(CONSTLIT("aWeaponFragment"), m_sUNID); CSpaceObject *pAttacker = Source.GetObj(); CCCtx.DefineSpaceObject(CONSTLIT("aCause"), pShot); CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), pAttacker); CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (pAttacker ? pAttacker->GetOrderGiver(Source.GetCause()) : NULL)); ICCItem *pResult = CCCtx.Run(Event); if (pResult->IsError()) pShot->ReportEventError(ON_FRAGMENT_EVENT, pResult); // If we return Nil, then we continue processing bool bResult; if (pResult->IsNil()) bResult = false; // Otherwise, we skip fragmentation else bResult = true; CCCtx.Discard(pResult); return bResult; } else return false; }
void CArmorClass::FireOnArmorDamage (CItemCtx &ItemCtx, SDamageCtx &Ctx) // FireOnArmorDamage // // Fires OnArmorDamage event { SEventHandlerDesc Event; if (FindEventHandlerArmorClass(evtOnArmorDamage, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CCCtx.SaveAndDefineSourceVar(ItemCtx.GetSource()); CCCtx.SaveAndDefineItemVar(ItemCtx); CCCtx.DefineInteger(CONSTLIT("aArmorHP"), Ctx.iHPLeft); CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit); CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj()); CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause); CCCtx.DefineDamageEffects(CONSTLIT("aDamageEffects"), Ctx); CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage); CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType())); CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection); CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos); CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL)); CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType()); ICCItem *pResult = CCCtx.Run(Event); // If we return Nil, then nothing if (pResult->IsNil()) NULL; // If we return an integer, then this is the damage that armor should take else if (pResult->IsInteger()) Ctx.iDamage = pResult->GetIntegerValue(); // If we return a list, then we it to be a DamageEffects list (modifications to // aDamageEffects) else if (pResult->IsList()) LoadDamageEffectsFromItem(pResult, Ctx); CCCtx.Discard(pResult); } }
bool IDockScreenDisplay::EvalString (const CString &sString, bool bPlain, ECodeChainEvents iEvent, CString *retsResult) // EvalString // // Evaluates the given string. { CCodeChainCtx Ctx; Ctx.SetEvent(iEvent); Ctx.SetScreen(m_pDockScreen); Ctx.SaveAndDefineSourceVar(m_pLocation); Ctx.SaveAndDefineDataVar(m_pData); return Ctx.RunEvalString(sString, bPlain, retsResult); }
void CMission::FireOnStart (void) // FireOnStart // // Fire <OnStarted> { SEventHandlerDesc Event; if (FindEventHandler(EVENT_ON_STARTED, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(this); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) ReportEventError(EVENT_ON_STARTED, pResult); Ctx.Discard(pResult); } }
void CShieldClass::FireOnShieldDown (CInstalledDevice *pDevice, CSpaceObject *pSource) // FireOnShieldDown // // Fire OnShieldDown event { SEventHandlerDesc Event; if (FindEventHandlerShieldClass(evtOnShieldDown, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(pSource); Ctx.SaveAndDefineItemVar(pSource->GetItemForDevice(pDevice)); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) pSource->ReportEventError(ON_SHIELD_DOWN_EVENT, pResult); Ctx.Discard(pResult); } }
void CMission::FireOnReward (ICCItem *pData) // FireOnReward // // Fire <OnReward> { SEventHandlerDesc Event; if (FindEventHandler(EVENT_ON_REWARD, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(this); Ctx.SaveAndDefineDataVar(pData); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) ReportEventError(EVENT_ON_REWARD, pResult); Ctx.Discard(pResult); } }
void CMission::FireCustomEvent (const CString &sEvent) // FireCustomEvent // // Fires a custom timed event { SEventHandlerDesc Event; if (FindEventHandler(sEvent, &Event)) { CCodeChainCtx Ctx; Ctx.SetEvent(eventDoEvent); Ctx.SaveAndDefineSourceVar(this); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) ReportEventError(sEvent, pResult); Ctx.Discard(pResult); } }
void CMission::FireOnSetPlayerTarget (const CString &sReason) // FireOnSetPlayerTarget // // Fire <OnSetPlayerTarget> { SEventHandlerDesc Event; if (FindEventHandler(EVENT_ON_SET_PLAYER_TARGET, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(this); Ctx.DefineString(STR_A_REASON, sReason); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) ReportEventError(EVENT_ON_SET_PLAYER_TARGET, pResult); Ctx.Discard(pResult); } }
void CMission::FireOnStop (const CString &sReason, ICCItem *pData) // FireOnStop // // Fire <OnCompleted> { SEventHandlerDesc Event; if (FindEventHandler(EVENT_ON_COMPLETED, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(this); Ctx.SaveAndDefineDataVar(pData); Ctx.DefineString(STR_A_REASON, sReason); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) ReportEventError(EVENT_ON_COMPLETED, pResult); Ctx.Discard(pResult); } }
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; }
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; }
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; }
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); } }