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;
	}
Exemple #2
0
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;
	}