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.SaveItemVar(); Ctx.DefineItem(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; }
void CShieldClass::FireOnShieldDown (CInstalledDevice *pDevice, CSpaceObject *pSource) // FireOnShieldDown // // Fire OnShieldDown event { SEventHandlerDesc Event; if (FindEventHandlerShieldClass(evtOnShieldDown, &Event)) { CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(pSource); Ctx.SaveItemVar(); Ctx.DefineItem(pSource->GetItemForDevice(pDevice)); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) pSource->ReportEventError(ON_SHIELD_DOWN_EVENT, pResult); Ctx.Discard(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.SaveItemVar(); CCCtx.DefineItem(ItemCtx); 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 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); } }
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); } }