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; }
ALERROR CParticleDamage::Create (CSystem *pSystem, CWeaponFireDesc *pDesc, CItemEnhancementStack *pEnhancements, DestructionTypes iCause, const CDamageSource &Source, const CVector &vPos, const CVector &vVel, int iDirection, CSpaceObject *pTarget, CParticleDamage **retpObj) // Create // // Create the object { ALERROR error; // Make sure we have a valid CWeaponFireDesc (otherwise we won't be // able to save the object). ASSERT(!pDesc->m_sUNID.IsBlank()); // Create the area CParticleDamage *pParticles = new CParticleDamage; if (pParticles == NULL) return ERR_MEMORY; pParticles->Place(vPos, vVel); // Get notifications when other objects are destroyed pParticles->SetObjectDestructionHook(); // Set non-linear move, meaning that we are responsible for // setting the position and velocity in OnMove pParticles->SetNonLinearMove(); pParticles->m_pDesc = pDesc; pParticles->m_pTarget = pTarget; pParticles->m_pEnhancements = (pEnhancements ? pEnhancements->AddRef() : NULL); pParticles->m_iCause = iCause; pParticles->m_iEmitDirection = iDirection; pParticles->m_vEmitSourcePos = vPos; pParticles->m_vEmitSourceVel = (Source.GetObj() ? Source.GetObj()->GetVel() : CVector()); pParticles->m_iEmitTime = Max(1, pDesc->GetParticleEmitTime()); pParticles->m_iLifeLeft = pDesc->GetMaxLifetime() + pParticles->m_iEmitTime; pParticles->m_Source = Source; pParticles->m_iTick = 0; pParticles->m_iDamage = pDesc->m_Damage.RollDamage(); // Friendly fire if (!pDesc->CanHitFriends()) pParticles->SetNoFriendlyFire(); // Painter CEffectCreator *pEffect; if (pEffect = pDesc->GetEffect()) { CCreatePainterCtx Ctx; Ctx.SetWeaponFireDesc(pDesc); pParticles->m_pPainter = pEffect->CreatePainter(Ctx); } // Remember the sovereign of the source (in case the source is destroyed) if (Source.GetObj()) pParticles->m_pSovereign = Source.GetObj()->GetSovereign(); else pParticles->m_pSovereign = NULL; // Compute the maximum number of particles that we might have int iMaxCount = pParticles->m_iEmitTime * pDesc->GetMaxParticleCount(); pParticles->m_Particles.Init(iMaxCount, vPos); // Create the initial particles int iInitCount = pDesc->GetParticleCount(); pParticles->InitParticles(iInitCount, CVector(), vVel, iDirection); // Figure out the number of particles that will cause full damage if (pParticles->m_iEmitTime > 1) pParticles->m_iParticleCount = pParticles->m_iEmitTime * pDesc->GetAveParticleCount(); else pParticles->m_iParticleCount = iInitCount; pParticles->m_iParticleCount = Max(1, pParticles->m_iParticleCount); // Add to system if (error = pParticles->AddToSystem(pSystem)) { delete pParticles; return error; } // Done if (retpObj) *retpObj = pParticles; return NOERROR; }