CString CShieldClass::GetReference (CItemCtx &Ctx, int iVariant, DWORD dwFlags) // GetReference // // Returns a string that describes the basic attributes // of this shield // // Example: // // 20 hp (average regen); 100MW { int i; CString sReference; CString sRegeneration; const CItemEnhancement &Mods = Ctx.GetMods(); // Compute the strength string int iMin, iMax; CalcMinMaxHP(Ctx, m_iMaxCharges, 0, 0, &iMin, &iMax); // Compute the regeneration if (m_iRegenHP > 0) { int iRate = (int)((10.0 * g_TicksPerSecond * m_iRegenHP / m_iRegenRate) + 0.5); if (iRate == 0) sRegeneration = CONSTLIT("<0.1 hp/sec"); else if ((iRate % 10) == 0) sRegeneration = strPatternSubst(CONSTLIT("%d hp/sec"), iRate / 10); else sRegeneration = strPatternSubst(CONSTLIT("%d.%d hp/sec"), iRate / 10, iRate % 10); } else sRegeneration = CONSTLIT("none"); sReference = strPatternSubst("%s — regen @ %s", GetReferencePower(Ctx), sRegeneration); // Reflection for (i = 0; i < damageCount; i++) { if (m_Reflective.InSet((DamageTypes)i) || (Mods.IsReflective() && Mods.GetDamageType() == i)) sReference.Append(strPatternSubst(CONSTLIT(" — %s-reflecting"), GetDamageShortName((DamageTypes)i))); } return sReference; }
CString CMissile::GetName (DWORD *retdwFlags) // GetName // // This is only used if the source has been destroyed { if (retdwFlags) *retdwFlags = nounNoArticle; return strPatternSubst(CONSTLIT("%s damage"), GetDamageShortName(m_pDesc->m_Damage.GetDamageType())); }
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; }
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); } }
CString CShieldClass::GetReference (CItemCtx &Ctx, int iVariant, DWORD dwFlags) // GetReference // // Returns a string that describes the basic attributes // of this shield // // Example: // // 20 hp (average regen); 100MW { int i; CString sReference; const CItemEnhancement &Mods = Ctx.GetMods(); // Compute the strength string int iMin, iMax; CalcMinMaxHP(Ctx, m_iMaxCharges, 0, 0, &iMin, &iMax); // Compute the regeneration sReference = strPatternSubst("%s — regen @ %s", GetReferencePower(Ctx), m_Regen.GetReferenceRate(CONSTLIT("hp/sec"))); // Reflection for (i = 0; i < damageCount; i++) { if (m_Reflective.InSet((DamageTypes)i) || (Mods.IsReflective() && Mods.GetDamageType() == i)) sReference.Append(strPatternSubst(CONSTLIT(" — %s-reflecting"), GetDamageShortName((DamageTypes)i))); } return sReference; }
CString CArmorClass::GetReference (CItemCtx &Ctx, int iVariant) // GetReference // // Returns a string that describes the basic attributes // of this armor. // // Example: // // 30 hp; laser-resistant; impact-resistant { int i; CString sReference; // Get modifications int iLevel = m_pItemType->GetLevel(); const CItemEnhancement &Mods = Ctx.GetMods(); // Radiation if (m_fRadiationImmune || Mods.IsRadiationImmune()) { if (iLevel < RADIATION_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("radiation-immune")); } else if (iLevel >= RADIATION_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("radiation-vulnerable")); // If we're immune to blinding/EMP/device damage, then collapse // it all under a single entry bool bCheckedBlind = false; bool bCheckedEMP = false; bool bCheckedDevice = false; if ((m_iBlindingDamageAdj == 0 || Mods.IsBlindingImmune()) && (m_iEMPDamageAdj == 0 || Mods.IsEMPImmune()) && (m_iDeviceDamageAdj < 100 || Mods.IsDeviceDamageImmune())) { if (iLevel < DEVICE_DAMAGE_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("ion effect-immune")); bCheckedBlind = true; bCheckedEMP = true; bCheckedDevice = true; } // Collapse blind and EMP resistance else if ((m_iBlindingDamageAdj == 0 || Mods.IsBlindingImmune()) && (m_iEMPDamageAdj == 0 || Mods.IsEMPImmune())) { if (iLevel < EMP_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("blind-, EMP-immune")); bCheckedBlind = true; bCheckedEMP = true; } else if ((m_iBlindingDamageAdj < 100) && (iLevel < BLIND_IMMUNE_LEVEL) && (m_iEMPDamageAdj < 100)) { AppendReferenceString(&sReference, CONSTLIT("blind-, EMP-resistant")); bCheckedBlind = true; bCheckedEMP = true; } // Otherwise, treat each separate // // Blindness if (!bCheckedBlind) { if (m_iBlindingDamageAdj == 0 || Mods.IsBlindingImmune()) { if (iLevel < BLIND_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("blind-immune")); } else if (m_iBlindingDamageAdj < 100) { if (iLevel < BLIND_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("blind-resistant")); else AppendReferenceString(&sReference, CONSTLIT("blind-vulnerable")); } else if (iLevel >= BLIND_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("blind-vulnerable")); } // EMP if (!bCheckedEMP) { if (m_iEMPDamageAdj == 0 || Mods.IsEMPImmune()) { if (iLevel < EMP_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("EMP-immune")); } else if (m_iEMPDamageAdj < 100) { if (iLevel < EMP_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("EMP-resistant")); else AppendReferenceString(&sReference, CONSTLIT("EMP-vulnerable")); } else if (iLevel >= EMP_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("EMP-vulnerable")); } // Device damage if (!bCheckedDevice) { if (m_iDeviceDamageAdj < 100 || Mods.IsDeviceDamageImmune()) { if (iLevel < DEVICE_DAMAGE_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("device-protect")); } else if (iLevel >= DEVICE_DAMAGE_IMMUNE_LEVEL) AppendReferenceString(&sReference, CONSTLIT("device-vulnerable")); } // Disintegration if (m_fDisintegrationImmune || Mods.IsDisintegrationImmune()) AppendReferenceString(&sReference, CONSTLIT("disintegrate-immune")); // Shatter if (IsShatterImmune(Ctx)) AppendReferenceString(&sReference, CONSTLIT("shatter-immune")); // Shield interference if (m_fShieldInterference || Mods.IsShieldInterfering()) AppendReferenceString(&sReference, CONSTLIT("no-shields")); // Photo repair if (m_fPhotoRepair || Mods.IsPhotoRegenerating()) AppendReferenceString(&sReference, CONSTLIT("photo-repair")); // Solar power if (m_fPhotoRecharge || Mods.IsPhotoRecharge()) AppendReferenceString(&sReference, CONSTLIT("solar")); // Regeneration if ((!m_Regen.IsEmpty() && !m_fPhotoRepair) || Mods.IsRegenerating()) AppendReferenceString(&sReference, CONSTLIT("regenerate")); // Decay if (!m_Decay.IsEmpty() || Mods.IsDecaying()) AppendReferenceString(&sReference, CONSTLIT("decay")); // Reflection for (i = 0; i < damageCount; i++) { if (m_Reflective.InSet((DamageTypes)i) || (Mods.IsReflective() && Mods.GetDamageType() == i)) AppendReferenceString(&sReference, strPatternSubst(CONSTLIT("%s-reflecting"), GetDamageShortName((DamageTypes)i))); } // Done return sReference; }
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); } }