void CFractureEffect::OnUpdateExtended (const CTimeSpan &ExtraTime) // OnUpdateExtended // // Update a prolonged time { // Updates don't last for an extended period of time Destroy(removedFromSystem, CDamageSource()); }
void CParticleDamage::OnUpdate (SUpdateCtx &Ctx, Metric rSecondsPerTick) // OnUpdate // // Update { m_iTick++; // Update the single particle painter if (m_pPainter) m_pPainter->OnUpdate(); // Set up context block for particle array update SEffectUpdateCtx EffectCtx; EffectCtx.pSystem = GetSystem(); EffectCtx.pObj = this; EffectCtx.pDamageDesc = m_pDesc; EffectCtx.iTotalParticleCount = m_iParticleCount; EffectCtx.pEnhancements = m_pEnhancements; EffectCtx.iCause = m_iCause; EffectCtx.bAutomatedWeapon = IsAutomatedWeapon(); EffectCtx.Attacker = m_Source; // Update (includes doing damage) m_Particles.Update(EffectCtx); // If we're tracking, change velocity to follow target if (m_pTarget && m_pDesc->IsTrackingTime(m_iTick)) m_Particles.UpdateTrackTarget(m_pTarget, m_pDesc->GetManeuverRate(), m_pDesc->GetRatedSpeed()); // Expired? if (--m_iLifeLeft <= 0) { Destroy(removedFromSystem, CDamageSource()); return; } // Emit new particles if (m_iTick < m_iEmitTime && !m_Source.IsEmpty()) { InitParticles(m_pDesc->GetParticleCount(), m_vEmitSourcePos - GetPos(), GetVel(), m_iEmitDirection); } }
void CBeam::OnUpdate (SUpdateCtx &Ctx, Metric rSecondsPerTick) // OnUpdate // // Update the beam { DEBUG_TRY bool bDestroy = false; m_iTick++; // See if the beam hit anything if (m_pHit) { // Tell the object hit that it has been damaged SDamageCtx Ctx; Ctx.pObj = m_pHit; Ctx.pDesc = m_pDesc; Ctx.Damage = m_pDesc->m_Damage; Ctx.Damage.AddBonus(m_iBonus); Ctx.Damage.SetCause(m_iCause); if (IsAutomatedWeapon()) Ctx.Damage.SetAutomatedWeapon(); Ctx.iDirection = (m_iHitDir + 360 + mathRandom(0, 30) - 15) % 360; Ctx.vHitPos = m_vPaintTo; Ctx.pCause = this; Ctx.Attacker = m_Source; EDamageResults result = m_pHit->Damage(Ctx); // Set the beam to destroy itself after a hit if (m_pDesc->GetPassthrough() == 0 || result == damageNoDamage || result == damageAbsorbedByShields || mathRandom(1, 100) > m_pDesc->GetPassthrough()) bDestroy = true; } // See if the beam has faded out if (bDestroy || --m_iLifeLeft <= 0) Destroy(removedFromSystem, CDamageSource()); DEBUG_CATCH }
void CParticleDamage::OnMove (const CVector &vOldPos, Metric rSeconds) // OnMove // // Handle moving { // Update the single particle painter if (m_pPainter) { SEffectMoveCtx Ctx; Ctx.pObj = this; m_pPainter->OnMove(Ctx); } // Update particle motion bool bAlive; CVector vNewPos; m_Particles.UpdateMotionLinear(&bAlive, &vNewPos); // If no particles are left alive, then we destroy the object if (!bAlive) { Destroy(removedFromSystem, CDamageSource()); return; } // Set the position of the object base on the average particle position SetPos(m_Particles.GetOrigin() + vNewPos); // Set the bounds (note, we make the bounds twice as large to deal // with the fact that we're moving). RECT rcBounds = m_Particles.GetBounds(); SetBounds(g_KlicksPerPixel * Max(RectWidth(rcBounds), RectHeight(rcBounds))); // Update emit source position m_vEmitSourcePos = m_vEmitSourcePos + m_vEmitSourceVel; }
void CTranscendenceWnd::DestroyIntroShips (void) // DestroyIntroShips // // Destroys all ships of the same class as the POV { int i; CShip *pShip = g_pUniverse->GetPOV()->AsShip(); if (pShip == NULL) return; // Destroy all ships of the current class CSystem *pSystem = pShip->GetSystem(); CShipClass *pClassToDestroy = pShip->GetClass(); TArray<CSpaceObject *> ShipsToDestroy; CSpaceObject *pOtherShip = NULL; for (i = 0; i < pSystem->GetObjectCount(); i++) { CSpaceObject *pObj = pSystem->GetObject(i); CShip *pShip; if (pObj && !pObj->IsInactive() && !pObj->IsVirtual() && (pShip = pObj->AsShip())) { if (pShip->GetClass() == pClassToDestroy) ShipsToDestroy.Insert(pObj); else if (pOtherShip == NULL) pOtherShip = pObj; } } // Destroy ships for (i = 0; i < ShipsToDestroy.GetCount(); i++) ShipsToDestroy[i]->Destroy(removedFromSystem, CDamageSource()); }
void CDisintegrationEffect::OnUpdate (SUpdateCtx &Ctx, Metric rSecondsPerTick) // OnUpdate // // Update the effect { int i; // See if the effect has faded out m_iTick++; if (m_iTick >= LIFETIME) { Destroy(removedFromSystem, CDamageSource()); return; } // Otherwise, update the particles SParticle *pParticle = m_pParticles; for (i = 0; i < m_iParticleCount; i++, pParticle++) { pParticle->iTicksLeft--; pParticle->x += pParticle->xV; pParticle->y += pParticle->yV; if (m_iTick < DISPERSE_POINT) { if (pParticle->iTicksLeft <= 0) InitParticle(pParticle); } } // If we're moving, slow down SetVel(CVector(GetVel().GetX() * g_SpaceDragFactor, GetVel().GetY() * g_SpaceDragFactor)); }
void CFractureEffect::OnUpdate (SUpdateCtx &Ctx, Metric rSecondsPerTick) // OnUpdate // // Update the effect { // See if the effect has faded out m_iTick++; if (m_iTick >= m_iLifeTime) { Destroy(removedFromSystem, CDamageSource()); return; } // Update particles if (m_pParticles) { SParticle *pParticle = m_pParticles; SParticle *pParticleEnd = pParticle + m_iParticleCount; // If we have an attractor, accelerate all particles towards it if (m_pAttractor) { bool bParticlesLeft = false; // Compute the position of the attractor in the particle // coordinate system. CVector vDist = m_pAttractor->GetPos() - GetPos(); int xAttract = FIXED_POINT * (int)(vDist.GetX() / g_KlicksPerPixel); int yAttract = -FIXED_POINT * (int)(vDist.GetY() / g_KlicksPerPixel); while (pParticle < pParticleEnd) { int xDelta = xAttract - pParticle->x; int yDelta = yAttract - pParticle->y; int xDist = abs(xDelta); int yDist = abs(yDelta); // If within threshold, then particles do not move if (xDist < (8 * FIXED_POINT) && yDist < (8 * FIXED_POINT)) ; // Otherwise, move towards attractor else { int iDist = Max(xDist, yDist); int iSpeed = 256 * 256 * FIXED_POINT / iDist; iSpeed = Min(iSpeed, 4 * FIXED_POINT); int iFade = (m_iTick > 100 ? 0 : (100 - m_iTick)); int xV = (iSpeed * xDelta / iDist) + (iFade * pParticle->xV / 100); int yV = (iSpeed * yDelta / iDist) + (iFade * pParticle->yV / 100); pParticle->x += xV; pParticle->y += yV; bParticlesLeft = true; } pParticle++; } // If no particles left, destroy the effect if (!bParticlesLeft) { Destroy(removedFromSystem, CDamageSource()); return; } } // Otherwise, follow normal trajectory else { while (pParticle < pParticleEnd) { pParticle->x += pParticle->xV; pParticle->y += pParticle->yV; pParticle++; } } } else { Destroy(removedFromSystem, CDamageSource()); return; } // If we're moving, slow down SetVel(CVector(GetVel().GetX() * g_SpaceDragFactor, GetVel().GetY() * g_SpaceDragFactor)); }
void CMissile::OnUpdate (SUpdateCtx &Ctx, Metric rSecondsPerTick) // OnUpdate // // Update the beam { // If we're already destroyed, then just update the timer until the // vapor trail fades out if (m_fDestroyed) { // Update the painter if (m_pPainter) { m_pPainter->OnUpdate(); // LATER: We shouldn't have to update bounds here because // it is set in OnMove. SetBounds(m_pPainter); } // Done? if (--m_iLifeLeft <= 0) { Destroy(removedFromSystem, CDamageSource()); return; } } // Otherwise, update else { int i; CSystem *pSystem = GetSystem(); int iTick = m_iTick + GetDestiny(); bool bDestroy = false; // Accelerate, if necessary if (m_pDesc->m_iAccelerationFactor > 0 && (iTick % 10 ) == 0) { if (m_pDesc->m_iAccelerationFactor < 100 || GetVel().Length() < m_pDesc->m_rMaxMissileSpeed) SetVel(GetVel() * (Metric)(m_pDesc->m_iAccelerationFactor / 100.0)); } // If we can choose new targets, see if we need one now if (m_pDesc->CanAutoTarget() && m_pTarget == NULL) m_pTarget = GetNearestEnemy(MAX_TARGET_RANGE, false); // If this is a tracking missile, change direction to face the target if (m_pDesc->IsTrackingTime(iTick) && m_pTarget) { // Get the position and velocity of the target CVector vTarget = m_pTarget->GetPos() - GetPos(); CVector vTargetVel = m_pTarget->GetVel() - GetVel(); // Figure out which direction to move in int iFireAngle; Metric rCurrentSpeed = GetVel().Length(); Metric rTimeToIntercept = CalcInterceptTime(vTarget, vTargetVel, rCurrentSpeed); if (rTimeToIntercept > 0.0) { CVector vInterceptPoint = vTarget + vTargetVel * rTimeToIntercept; iFireAngle = VectorToPolar(vInterceptPoint, NULL); } else iFireAngle = VectorToPolar(vTarget); // Turn to desired direction. if (!AreAnglesAligned(iFireAngle, m_iRotation, 1)) { int iTurn = (iFireAngle + 360 - m_iRotation) % 360; if (iTurn >= 180) { int iTurnAngle = Min((360 - iTurn), m_pDesc->GetManeuverRate()); m_iRotation = (m_iRotation + 360 - iTurnAngle) % 360; } else { int iTurnAngle = Min(iTurn, m_pDesc->GetManeuverRate()); m_iRotation = (m_iRotation + iTurnAngle) % 360; } } SetVel(PolarToVector(m_iRotation, rCurrentSpeed)); } // Update exhaust if (m_pExhaust) { if (iTick % m_pDesc->m_iExhaustRate) { if (m_pExhaust->GetCount() == m_pExhaust->GetMaxCount()) m_pExhaust->Dequeue(); SExhaustParticle &New = m_pExhaust->GetAt(m_pExhaust->Queue()); New.vPos = GetPos(); New.vVel = GetVel(); } for (int i = 0; i < m_pExhaust->GetCount(); i++) { SExhaustParticle &Particle = m_pExhaust->GetAt(i); Particle.vVel = m_pDesc->m_rExhaustDrag * Particle.vVel; Particle.vPos = Particle.vPos + Particle.vVel * g_SecondsPerUpdate; } } // Update the painter if (m_pPainter) { m_pPainter->OnUpdate(); // LATER: We shouldn't have to update bounds here because // it is set in OnMove. SetBounds(m_pPainter); } // If we have a vapor trail and need to save rotation, do it if (m_pDesc->GetVaporTrailLength() && m_pDesc->IsTracking()) { // Compute the current rotation int iDirection = (m_iRotation + 180) % 360; // Add the current rotation to the list of saved rotations if (m_pSavedRotations == NULL) { m_pSavedRotations = new int [m_pDesc->GetVaporTrailLength()]; m_iSavedRotationsCount = 0; } int iStart = Min(m_iSavedRotationsCount, m_pDesc->GetVaporTrailLength() - 1); for (i = iStart; i > 0; i--) m_pSavedRotations[i] = m_pSavedRotations[i - 1]; m_pSavedRotations[0] = iDirection; if (m_iSavedRotationsCount < m_pDesc->GetVaporTrailLength()) m_iSavedRotationsCount++; } // See if the missile hit anything if (m_fDetonate && m_pDesc->ProximityBlast()) { CreateFragments(GetPos()); bDestroy = true; } else if (m_pHit) { // If we have fragments, then explode now if (m_iHitDir == -1 && m_pDesc->ProximityBlast() && m_iTick >= m_pDesc->GetProximityFailsafe()) { CreateFragments(m_vHitPos); bDestroy = true; } // Otherwise, if this was a direct hit, then we do damage else if (m_iHitDir != -1) { SDamageCtx DamageCtx; DamageCtx.pObj = m_pHit; DamageCtx.pDesc = m_pDesc; DamageCtx.Damage = m_pDesc->m_Damage; DamageCtx.Damage.AddBonus(m_iBonus); DamageCtx.Damage.SetCause(m_iCause); if (IsAutomatedWeapon()) DamageCtx.Damage.SetAutomatedWeapon(); DamageCtx.iDirection = (m_iHitDir + 360 + mathRandom(0, 30) - 15) % 360; DamageCtx.vHitPos = m_vHitPos; DamageCtx.pCause = this; DamageCtx.Attacker = m_Source; EDamageResults result = m_pHit->Damage(DamageCtx); // If we hit another missile (or some small object) there is a chance // that we continue if (result == damagePassthrough || result == damagePassthroughDestroyed) { m_iHitPoints = m_iHitPoints / 2; bDestroy = (m_iHitPoints == 0); } // Set the missile to destroy itself after a hit, if we did not // pass through else if (!m_fPassthrough) bDestroy = true; } } // See if the missile has faded out if (bDestroy || --m_iLifeLeft <= 0) { // If this is a fragmentation weapon, then we explode at the end of life if (!bDestroy && m_pDesc->ProximityBlast()) CreateFragments(GetPos()); // If we've got a vapor trail effect, then keep the missile object alive // but mark it destroyed int iFadeLife; if (m_pDesc->GetVaporTrailLength()) { m_fDestroyed = true; m_iLifeLeft = m_pDesc->GetVaporTrailLength(); } // If we've got an effect that needs time to fade out, then keep // the missile object alive else if (m_pPainter && (iFadeLife = m_pPainter->GetFadeLifetime())) { m_pPainter->OnBeginFade(); m_fDestroyed = true; m_iLifeLeft = iFadeLife; } // Otherwise, destroy the missile else { Destroy(removedFromSystem, CDamageSource()); return; } } } m_iTick++; }
void CParticleEffect::OnUpdate (SUpdateCtx &Ctx, Metric rSecondsPerTick) // OnUpdate // // Update the effect { int iTick = GetSystem()->GetTick() + GetDestiny(); // Do not bother updating everything if we are far from the POV bool bFarAway = false; if (g_pUniverse->GetPOV() && g_pUniverse->GetCurrentSystem() == GetSystem()) { Metric rPOVDist2 = (GetPos() - g_pUniverse->GetPOV()->GetPos()).Length2(); Metric rMaxUpdateDist2 = LIGHT_SECOND * LIGHT_SECOND * 3600; bFarAway = (rPOVDist2 > rMaxUpdateDist2); } // Update the particles SParticleArray *pGroup = m_pFirstGroup; while (pGroup) { SParticleType *pType = pGroup->pType; // Max distance for a particle in this group Metric rMaxDist2 = pType->rRadius * pType->rRadius; Metric rMinDist2 = pType->rHoleRadius * pType->rHoleRadius; // If the particle field causes damage then we need to // compute its average density int iDensity = 0; if (pType->pDamageDesc) { Metric rRadius2 = pType->rRadius * pType->rRadius; Metric rArea = rRadius2 / (LIGHT_SECOND * LIGHT_SECOND); iDensity = (int)(4 * pGroup->iCount / rArea); } // Get an array of objects in the particle field that // may influence the particles CSpaceObject *Objects[ctMaxObjsInField]; int iObjCount = 0; if (!bFarAway && (pType->m_fWake || pType->pDamageDesc)) { Metric rMaxInfluenceDist2 = rMaxDist2; for (int i = 0; i < GetSystem()->GetObjectCount(); i++) { CSpaceObject *pObj = GetSystem()->GetObject(i); if (pObj && pObj->GetCategory() == catShip && !pObj->IsInactive() && pObj->CanBeHit() && !pObj->IsDestroyed() && pObj != this) { CVector vDist = GetPos() - pObj->GetPos(); Metric rDist2 = vDist.Length2(); if (rDist2 < rMaxInfluenceDist2 && (pObj->GetVel().Length2() > g_KlicksPerPixel) && iObjCount < ctMaxObjsInField) { Objects[iObjCount++] = pObj; // See if the object should take damage if (pType->pDamageDesc) { CVector vDeltaV = pObj->GetVel() - GetVel(); int iSpeed = (int)(vDeltaV.Length() / g_KlicksPerPixel); if (iSpeed == 0) iSpeed = 1; if (mathRandom(1, 1000) < (iDensity * iSpeed)) { SDamageCtx Ctx; Ctx.pObj = pObj; Ctx.pDesc = pType->pDamageDesc; Ctx.Damage = pType->pDamageDesc->m_Damage; if (IsAutomatedWeapon()) Ctx.Damage.SetAutomatedWeapon(); Ctx.iDirection = VectorToPolar(vDeltaV); Ctx.vHitPos = pObj->GetPos(); Ctx.pCause = this; Ctx.Attacker = CDamageSource(this, killedByDamage); pObj->Damage(Ctx); } } } } } } // If we're computing drag then we need to compute the new velocity // of the whole particle system CVector vNewVel; if (pType->m_fDrag) vNewVel = GetVel() * g_SpaceDragFactor; // Iterate over all particles SParticle *pParticle = pGroup->pParticles; SParticle *pEnd = pParticle + pGroup->iCount; while (pParticle < pEnd) { if (pParticle->IsValid()) { // Lifespan. If we're far away and we're regenerating, // then don't bother to compute lifespan. if (pType->m_fLifespan && !(bFarAway && (pType->m_fRegenerate && pType->iRegenerationTimer))) { if (--pParticle->iLifeLeft == 0) { // Do we regenerate? if (pType->m_fRegenerate && pType->iRegenerationTimer) { pParticle->iLifeLeft = pType->iLifespan; pParticle->vPos = NullVector; // Speed Metric rSpeed = mathRandom(1, 100) * (pType->rAveSpeed / 100.0); if (pType->iDirection == -1) pParticle->vVel = PolarToVector(mathRandom(0, 359), rSpeed); else { int iAngle = (pType->iDirection + 360 + mathRandom(0, 2 * pType->iDirRange) - pType->iDirRange) % 360; pParticle->vVel = PolarToVector(iAngle, rSpeed); } } // Otherwise we die else { pParticle->iLifeLeft = -1; pGroup->iAlive--; pParticle++; continue; } } } // Update the position if (!bFarAway) { pParticle->vPos = pParticle->vPos + pParticle->vVel; // Change the velocity to keep the particles within // the radius if (pType->m_fMaxRadius) { Metric rDist2 = pParticle->vPos.Length2(); if (pType->m_fMaxRadius && rDist2 > rMaxDist2) { CVector vChange = pParticle->vPos + g_KlicksPerPixel * pParticle->vPos.Perpendicular().Normal(); pParticle->vVel = pParticle->vVel - (0.00005 * vChange); } else if (rDist2 < rMinDist2) { CVector vNormal = pParticle->vPos.Normal(); CVector vChange = g_KlicksPerPixel * (400 * vNormal - 50 * vNormal.Perpendicular()); pParticle->vVel = pParticle->vVel + (0.00005 * vChange); } else pParticle->vVel = pParticle->vVel * pType->rDampening; } if (pType->m_fDrag) { // Compute the new absolute velocity (after drag) CVector vAbsolute = pType->rDampening * (pParticle->vVel + GetVel()); // The particle velocity is the absolute vel minus the // system velocity. pParticle->vVel = vAbsolute - vNewVel; } // Change the velocity based on influences from other objects if (pType->m_fWake && (iTick % 4) == 0) { for (int i = 0; i < iObjCount; i++) { Metric rDist2 = (Objects[i]->GetPos() - (pParticle->vPos + GetPos())).Length2(); if (rDist2 < g_KlicksPerPixel * g_KlicksPerPixel * 1000) { if (Objects[i]->GetVel().Dot(pParticle->vVel) < Objects[i]->GetVel().Length2()) pParticle->vVel = pParticle->vVel + 0.2 * Objects[i]->GetVel(); } } } } } pParticle++; } // Regeneration timer if (pType->m_fRegenerate && pType->iRegenerationTimer) pType->iRegenerationTimer--; // If there are no more particles left alive in this group then kill // the group if (pGroup->iAlive == 0) { SParticleArray *pNext = pGroup->pNext; SParticleArray *pPrev = NULL; // Find the previous group SParticleArray *pFind = m_pFirstGroup; while (pFind != pGroup) { if (pPrev) pPrev = pPrev->pNext; else pPrev = m_pFirstGroup; pFind = pFind->pNext; } // Fix up the linked list if (pPrev) pPrev->pNext = pNext; else m_pFirstGroup = pNext; // Delete the group delete pGroup; pGroup = pNext; } // Otherwise, next group else pGroup = pGroup->pNext; } // If we have no more groups then we destroy ourselves if (m_pFirstGroup == NULL) { Destroy(removedFromSystem, CDamageSource()); return; } // If we're moving, slow down SetVel(CVector(GetVel().GetX() * g_SpaceDragFactor, GetVel().GetY() * g_SpaceDragFactor)); }
CDamageSource GetDamageSourceArg (CCodeChain &CC, ICCItem *pArg) // GetDamageSourceArg // // Returns a CDamageSource { if (pArg->IsNil()) return CDamageSource(NULL, killedByDamage); // Killed by the given object (explosion) else if (pArg->IsInteger()) { CSpaceObject *pSource = CreateObjFromItem(CC, pArg); return CDamageSource(pSource, killedByDamage); } // Custom death; string describes the cause of death (no explosion) else if (pArg->IsIdentifier()) { CString sCause = pArg->GetElement(0)->GetStringValue(); return CDamageSource(NULL, killedByOther, NULL, sCause, 0); } // Killed by a custom cause (explosion) else if (pArg->IsList() && pArg->GetCount() == 2 && pArg->GetElement(0)->IsIdentifier()) { CString sSourceName = pArg->GetElement(0)->GetStringValue(); DWORD dwSourceFlags = (DWORD)pArg->GetElement(1)->GetIntegerValue(); return CDamageSource(NULL, killedByDamage, NULL, sSourceName, dwSourceFlags); } // Full control over death else if (pArg->IsList()) { CSpaceObject *pSource = NULL; CSpaceObject *pSecondarySource = NULL; CString sSourceName; DWORD dwSourceFlags = 0; DestructionTypes iCause = killedByDamage; if (pArg->GetCount() >= 1) pSource = CreateObjFromItem(CC, pArg->GetElement(0)); if (pArg->GetCount() >= 2) iCause = ::GetDestructionCause(pArg->GetElement(1)->GetStringValue()); if (pArg->GetCount() >= 3) pSecondarySource = CreateObjFromItem(CC, pArg->GetElement(2)); if (pArg->GetCount() >= 4) sSourceName = pArg->GetElement(3)->GetStringValue(); if (pArg->GetCount() >= 5) dwSourceFlags = (DWORD)pArg->GetElement(4)->GetIntegerValue(); return CDamageSource(pSource, iCause, pSecondarySource, sSourceName, dwSourceFlags); } else return CDamageSource(); }
CDamageSource GetDamageSourceArg (CCodeChain &CC, ICCItem *pArg) // GetDamageSourceArg // // Returns a CDamageSource { if (pArg->IsNil()) return CDamageSource(NULL, killedByDamage); // Killed by the given object (explosion) else if (pArg->IsInteger()) { // NOTE: CDamageSource knows how to deal with destroyed objects, so it // is OK if we don't bother checking here whether pSource is destroyed. CSpaceObject *pSource = CreateObjFromItem(CC, pArg); return CDamageSource(pSource, killedByDamage); } // Custom death; string describes the cause of death (no explosion) else if (pArg->IsIdentifier()) { CString sCause = pArg->GetElement(0)->GetStringValue(); // If the cause happens to be a destruction cause ID, then use that. DestructionTypes iCause = ::GetDestructionCause(sCause); if (iCause != killedNone) return CDamageSource(NULL, iCause, NULL, NULL_STR, 0); // Otherwise, this is a custom death return CDamageSource(NULL, killedByOther, NULL, sCause, 0); } // Killed by a custom cause (explosion) else if (pArg->IsList() && pArg->GetCount() == 2 && pArg->GetElement(0)->IsIdentifier()) { CString sSourceName = pArg->GetElement(0)->GetStringValue(); DWORD dwSourceFlags = (DWORD)pArg->GetElement(1)->GetIntegerValue(); return CDamageSource(NULL, killedByDamage, NULL, sSourceName, dwSourceFlags); } // Full control over death else if (pArg->IsList()) { CSpaceObject *pSource = NULL; CSpaceObject *pSecondarySource = NULL; CString sSourceName; DWORD dwSourceFlags = 0; DestructionTypes iCause = killedByDamage; if (pArg->GetCount() >= 1) pSource = CreateObjFromItem(CC, pArg->GetElement(0)); if (pArg->GetCount() >= 2) iCause = ::GetDestructionCause(pArg->GetElement(1)->GetStringValue()); if (pArg->GetCount() >= 3) pSecondarySource = CreateObjFromItem(CC, pArg->GetElement(2)); if (pArg->GetCount() >= 4) sSourceName = pArg->GetElement(3)->GetStringValue(); if (pArg->GetCount() >= 5) dwSourceFlags = (DWORD)pArg->GetElement(4)->GetIntegerValue(); return CDamageSource(pSource, iCause, pSecondarySource, sSourceName, dwSourceFlags); } else return CDamageSource(); }