Ejemplo n.º 1
0
void CFractureEffect::OnUpdateExtended (const CTimeSpan &ExtraTime)

//	OnUpdateExtended
//
//	Update a prolonged time

	{
	//	Updates don't last for an extended period of time

	Destroy(removedFromSystem, CDamageSource());
	}
Ejemplo n.º 2
0
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);
		}
	}
Ejemplo n.º 3
0
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
}
Ejemplo n.º 4
0
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;
	}
Ejemplo n.º 5
0
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));
	}
Ejemplo n.º 7
0
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));
	}
Ejemplo n.º 8
0
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++;
}
Ejemplo n.º 9
0
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));
	}
Ejemplo n.º 10
0
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();
	}
Ejemplo n.º 11
0
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();
	}