Exemplo n.º 1
0
ALERROR CEffectCreator::CreateBeamEffect (SDesignLoadCtx &Ctx, CXMLElement *pDesc, const CString &sUNID, CEffectCreator **retpCreator)

//	CreateBeamEffect
//
//	Create a beam effect

	{
	ALERROR error;

	//	Create the effect

	CEffectCreator *pCreator = new CBeamEffectCreator;
	pCreator->m_sUNID = sUNID;

	//	Type-specific creation

	if (error = pCreator->OnEffectCreateFromXML(Ctx, pDesc, sUNID))
		return error;

	//	Done

	*retpCreator = pCreator;

	return NOERROR;
	}
Exemplo n.º 2
0
ALERROR CEffectCreator::CreateSimpleFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc, const CString &sUNID, CEffectCreator **retpCreator)

//	CreateSimpleFromXML
//
//	Creates the creator from an XML element

	{
	ALERROR error;
	CEffectCreator *pCreator;

	//	Create the effect based on the tag

	if (error = CreateFromTag(pDesc->GetTag(), &pCreator))
		{
		Ctx.sError = strPatternSubst(CONSTLIT("Invalid painter tag: %s"), pDesc->GetTag());
		return error;
		}

	if (pCreator == NULL)
		return ERR_MEMORY;

	pCreator->m_sUNID = sUNID;

	//	Type-specific creation

	if (error = pCreator->OnEffectCreateFromXML(Ctx, pDesc, sUNID))
		return error;

	//	Done

	*retpCreator = pCreator;

	return NOERROR;
	}
Exemplo n.º 3
0
void CWeaponFireDesc::CreateHitEffect (CSystem *pSystem, SDamageCtx &DamageCtx)

//	CreateHitEffect
//
//	Creates an effect when the weapon hits an object

	{
	//	See if this weapon has a hit effect

	CEffectCreator *pHitEffect = m_pHitEffect;

	//	If not, compute a default hit effect depending on the weapon damage type

	if (pHitEffect == NULL)
		pHitEffect = g_pUniverse->FindDefaultHitEffect(m_Damage.GetDamageType());

	//	If we could not come up with a hit effect then we're done.

	if (pHitEffect == NULL)
		return;

	//	Create the effect

	pHitEffect->CreateEffect(pSystem,
			((DamageCtx.pObj && !DamageCtx.pObj->IsDestroyed()) ? DamageCtx.pObj : NULL),
			DamageCtx.vHitPos,
			(DamageCtx.pObj ? DamageCtx.pObj->GetVel() : CVector()),
			DamageCtx.iDirection,
			DamageCtx.iDamage);
	}
Exemplo n.º 4
0
ALERROR CEffectCreator::CreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc, const CString &sUNID, CEffectCreator **retpCreator)

//	CreateFromXML
//
//	Creates the creator from an XML element

	{
	ALERROR error;
	CEffectCreator *pCreator;

	//	Basic info

	CString sEffectUNID = sUNID;
	if (sEffectUNID.IsBlank())
		{
		DWORD dwUNID = pDesc->GetAttributeInteger(UNID_ATTRIB);
		if (dwUNID)
			sEffectUNID = strFromInt(dwUNID, FALSE);
		else
			sEffectUNID = STR_NO_UNID;
		}

	//	Create the effect based on the child tag

	if (pDesc->GetContentElementCount() == 0)
		{
		*retpCreator = NULL;
		return NOERROR;
		}
	else if (pDesc->GetContentElementCount() == 1)
		{
		if (error = CreateSimpleFromXML(Ctx, pDesc->GetContentElement(0), sEffectUNID, &pCreator))
			return error;
		}
	else
		{
		pCreator = new CEffectGroupCreator;
		if (pCreator == NULL)
			return ERR_MEMORY;

		pCreator->m_sUNID = sEffectUNID;

		//	Type-specific creation

		if (error = pCreator->OnEffectCreateFromXML(Ctx, pDesc, sEffectUNID))
			return error;
		}

	//	Sound Effect (resolved later)

	pCreator->m_dwSoundUNID = pDesc->GetAttributeInteger(SOUND_ATTRIB);
	pCreator->m_iSound = -1;
	
	//	Done

	*retpCreator = pCreator;

	return NOERROR;
	}
Exemplo n.º 5
0
CSpaceObject::DamageResults CMissile::Damage (CSpaceObject *pCause, const CVector &vHitPos, int iDirection, const DamageDesc &Damage)

//	Damage
//
//	Object takes damage from the given source

	{
	CSpaceObject *pAttacker = pCause->GetDamageCause();

	//	Compute damage

	bool bDestroy = false;
	int iDamage = Damage.RollDamage();
	if (iDamage == 0)
		return damageNoDamage;

	//	If this is a momentum attack then we are pushed

	int iMomentum;
	if (iMomentum = Damage.GetMomentumDamage())
		{
		CVector vAccel = PolarToVector(iDirection, -10 * iMomentum * iMomentum);
		Accelerate(vAccel, g_MomentumConstant);
		ClipSpeed(GetMaxSpeed());
		}

	//	Create a hit effect

	CEffectCreator *pEffect = g_pUniverse->FindEffectType(g_HitEffectUNID);
	if (pEffect)
		pEffect->CreateEffect(GetSystem(),
				this,
				vHitPos,
				GetVel());

	//	Take damage

	if (iDamage < m_iHitPoints)
		{
		m_iHitPoints -= iDamage;
		return damageArmorHit;
		}

	//	We are destroyed

	m_iHitPoints = 0;
	if (m_pDesc->m_iVaporTrailLength)
		{
		m_fDestroyed = true;
		m_iLifeLeft = m_pDesc->m_iVaporTrailLength;
		}
	else
		Destroy(killedByDamage, pAttacker);

	//	A missile might be able to pass through after hitting us

	return damagePassthrough;
	}
Exemplo n.º 6
0
ALERROR IEffectPainter::ValidateClass (SLoadCtx &Ctx, const CString &sOriginalClass)

//	ValidateClass
//
//	Reads the class string. If the class does not match the current painter,
//	we read the old data and return ERR_FAIL.

	{
	if (Ctx.dwVersion >= 40)
		{
		CString sClass;
		sClass.ReadFromStream(Ctx.pStream);

		//	If the original class doesn't match the current one, then it means
		//	that the design changed. In that case, we load the painter using the
		//	old class.

		if (!strEquals(sClass, sOriginalClass))
			{
			//	If sClass is blank, then it means that the original did not have
			//	an effect painter (but the current design does)

			if (!sClass.IsBlank())
				{
				//	Get the original creator

				CEffectCreator *pOriginalCreator;
				if (CEffectCreator::CreateFromTag(sClass, &pOriginalCreator) != NOERROR)
					{
					kernelDebugLogMessage("Unable to find original effect creator: %s", sClass.GetASCIIZPointer());
					return ERR_FAIL;
					}

				//	Load the original painter

				IEffectPainter *pOriginalPainter = pOriginalCreator->CreatePainter();
				pOriginalPainter->ReadFromStream(Ctx);

				//	Discard

				pOriginalPainter->Delete();
				delete pOriginalCreator;
				}

			//	Done

			return ERR_FAIL;
			}
		}

	return NOERROR;
	}
Exemplo n.º 7
0
void CMissile::CreateHitEffect (const CVector &vPos, int iRotation)

//	CreateHitEffect
//
//	Create hit effect

{
    CEffectCreator *pEffect;
    if (pEffect = m_pDesc->GetHitEffect())
        pEffect->CreateEffect(GetSystem(),
                              (m_iHitDir == -1 ? NULL : m_pHit),
                              vPos,
                              CVector(),
                              iRotation);
}
Exemplo n.º 8
0
CSpaceObject::DamageResults CParticleEffect::Damage (CSpaceObject *pCause, const CVector &vHitPos, int iDirection, const DamageDesc &Damage)

//	Damage
//
//	Damage the particle field

	{
	//	Create hit effect

	CEffectCreator *pEffect = g_pUniverse->FindEffectType(g_HitEffectUNID);
	if (pEffect)
		pEffect->CreateEffect(GetSystem(),
				this,
				vHitPos,
				GetVel());

	return damagePassthrough;
	}
Exemplo n.º 9
0
void CEffectVariantPainter::Paint (CG16bitImage &Dest, int x, int y, SViewportPaintCtx &Ctx)

//	Paint
//
//	Paint the effect

	{
	//	Find the appropriate effect

	int iIndex = m_pCreator->GetVariantCreatorIndex(Ctx.iVariant);
	if (m_Cache[iIndex] == NULL)
		{
		CEffectCreator *pCreator = m_pCreator->GetVariantCreator(iIndex);
		m_Cache[iIndex] = pCreator->CreatePainter(CCreatePainterCtx());
		}

	//	Paint

	m_Cache[iIndex]->Paint(Dest, x, y, Ctx);
	}
Exemplo n.º 10
0
CEffectCreator *CEffectCreator::OnFindEffectCreator (const CString &sUNID)

//	OnFindEffectCreator
//
//	Finds the effect creator by UNID

	{
	char *pPos = sUNID.GetASCIIZPointer();

	//	If we're done, then we mean ourselves

	if (*pPos == '\0')
		return this;

	if (*pPos++ != '/')
		return NULL;

	//	Damage selector?

	if (*pPos == 'd')
		{
		pPos++;

		if (m_pDamage == NULL)
			return NULL;

		return m_pDamage->FindEffectCreator(CString(pPos));
		}

	//	Sub effect

	int iSubEffect = strParseInt(pPos, -1, 0, &pPos);
	if (iSubEffect == -1)
		return NULL;

	CEffectCreator *pSubEffect = GetSubEffect(iSubEffect);
	if (pSubEffect == NULL)
		return NULL;

	return pSubEffect->FindEffectCreatorInType(CString(pPos));
	}
Exemplo n.º 11
0
CSmokeTrailPainter::CSmokeTrailPainter (CSmokeTrailEffectCreator *pCreator) : 
		m_pCreator(pCreator),
		m_iLastDirection(-1),
		m_iTick(0)

//	CSmokeTrailPainter constructor

	{
	int iMaxParticleCount = m_pCreator->GetParticleLifetimeMax() * m_pCreator->GetNewParticleMax();

	m_Particles.Init(iMaxParticleCount);

	int iTotalLifetime = m_pCreator->GetLifetime();
	m_iEmitLifetime = (iTotalLifetime == -1 ? -1 : m_pCreator->GetEmitLifetime() * iTotalLifetime / 100);

	CEffectCreator *pEffect = pCreator->GetParticleEffect();
	if (pEffect)
		m_pParticlePainter = pEffect->CreatePainter();
	else
		m_pParticlePainter = NULL;
	}
void CCompositeImageDesc::InitDamagePainters (void)

//	InitDamagePainters
//
//	Initializes station damage bitmaps

	{
	if (g_pMediumDamage == NULL)
		{
		CEffectCreator *pEffect = g_pUniverse->FindEffectType(MEDIUM_STATION_DAMAGE_UNID);
		if (pEffect)
			g_pMediumDamage = pEffect->CreatePainter();
		}

	if (g_pLargeDamage == NULL)
		{
		CEffectCreator *pEffect = g_pUniverse->FindEffectType(LARGE_STATION_DAMAGE_UNID);
		if (pEffect)
			g_pLargeDamage = pEffect->CreatePainter();
		}
	}
Exemplo n.º 13
0
CParticleJetEffectPainter::CParticleJetEffectPainter (CCreatePainterCtx &Ctx, CParticleJetEffectCreator *pCreator) : 
		m_pCreator(pCreator),
		m_iXformRotation(0),
		m_rXformTime(1.0),
		m_iLifetime(0),
		m_iCurDirection(-1),
		m_iLastDirection(-1),
		m_bUseObjectCenter(Ctx.UseObjectCenter()),
		m_bUseObjectMotion(false),
		m_bTrackingObject(Ctx.IsTracking())

//	CParticleJetEffectPainter constructor

	{
	//	Initialize the single particle painter

	CEffectCreator *pEffect = m_pCreator->GetParticleEffect();
	if (pEffect)
		m_pParticlePainter = pEffect->CreatePainter(Ctx);
	else
		m_pParticlePainter = NULL;
	}
Exemplo n.º 14
0
CWeaponFireDesc *CWeaponFireDesc::FindWeaponFireDescFromFullUNID (const CString &sUNID)

//	FindWeaponFireDesc
//
//	Finds the descriptor by name

	{
	char *pPos = sUNID.GetPointer();

	//	Get the UNID of the type

	DWORD dwUNID = (DWORD)strParseInt(pPos, 0, &pPos);
	if (dwUNID == 0)
		return NULL;

	//	Get the type

	CDesignType *pType = g_pUniverse->FindDesignType(dwUNID);
	if (pType == NULL)
		return NULL;

	//	If this is an item, then it must be a weapon

	if (pType->GetType() == designItemType)
		{
		CItemType *pItemType = CItemType::AsType(pType);
		ASSERT(pItemType);

		CDeviceClass *pDevice = pItemType->GetDeviceClass();
		if (pDevice == NULL)
			return NULL;

		CWeaponClass *pClass = pDevice->AsWeaponClass();
		if (pClass == NULL)
			return NULL;

		//	Get the ordinal

		ASSERT(*pPos == '/');
		pPos++;
		int iOrdinal = strParseInt(pPos, 0, &pPos);

		//	Get the weapon fire desc of the ordinal

		CWeaponFireDesc *pDesc = pClass->GetVariant(iOrdinal);
		if (pDesc == NULL)
			return NULL;

		//	Continue parsing

		return pDesc->FindWeaponFireDesc(CString(pPos));
		}

	//	If this is an effect, then get it from that

	else if (pType->GetType() == designEffectType)
		{
		CEffectCreator *pEffectType = CEffectCreator::AsType(pType);
		ASSERT(pEffectType);

		//	Expect /d

		ASSERT(*pPos == '/');
		pPos++;
		ASSERT(*pPos == 'd');
		pPos++;

		CWeaponFireDesc *pDesc = pEffectType->GetDamageDesc();
		if (pDesc == NULL)
			return NULL;

		//	Continue parsing

		return pDesc->FindWeaponFireDesc(CString(pPos));
		}

	//	Otherwise, we don't know

	else
		return NULL;
	}
Exemplo n.º 15
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;
	}
Exemplo n.º 16
0
IEffectPainter *CEffectCreator::CreatePainterFromStream (SLoadCtx &Ctx, bool bNullCreator)

//	CreatePainterFromStream
//
//	Load a painter from a stream

	{
	CEffectCreator *pCreator;

	//	For previous versions, we only stored UNID if we had a creator

	if (Ctx.dwVersion < 43 && bNullCreator)
		return NULL;

	//	At version 15 we started saving versions as string UNIDs. We need to do this
	//	because sometimes the effect creator is inside a weapon fire desc
	//	structure (also identified by string UNIDs).

	if (Ctx.dwVersion >= 15)
		{
		CString sUNID;
		sUNID.ReadFromStream(Ctx.pStream);

		pCreator = (sUNID.IsBlank() ? NULL : CEffectCreator::FindEffectCreator(sUNID));

		//	Load the creator class that saved the painter

		if (IEffectPainter::ValidateClass(Ctx, (pCreator ? pCreator->GetTag() : NULL_STR)) != NOERROR)
			return NULL;

		//	Error

		if (pCreator == NULL)
			{
			if (!sUNID.IsBlank())
				kernelDebugLogMessage("Invalid painter creator: %s", sUNID.GetASCIIZPointer());
			return NULL;
			}
		}

	//	Old style uses DWORD UNIDs

	else
		{
		//	The first DWORD is the UNID of the creator

		DWORD dwUNID;
		Ctx.pStream->Read((char *)&dwUNID, sizeof(DWORD));
		if (dwUNID == 0)
			return NULL;

		pCreator = g_pUniverse->FindEffectType(dwUNID);

		//	Error

		if (pCreator == NULL)
			{
			kernelDebugLogMessage("Invalid painter creator: %x", dwUNID);
			return NULL;
			}
		}

	//	Let the creator create the object

	IEffectPainter *pPainter = pCreator->CreatePainter();

	//	Load it

	pPainter->ReadFromStream(Ctx);

	//	Done

	return pPainter;
	}
Exemplo n.º 17
0
ALERROR CMissile::Create (CSystem *pSystem,
                          CWeaponFireDesc *pDesc,
                          int iBonus,
                          DestructionTypes iCause,
                          const CDamageSource &Source,
                          const CVector &vPos,
                          const CVector &vVel,
                          int iRotation,
                          CSpaceObject *pTarget,
                          CMissile **retpMissile)

//	Create
//
//	Creates a missile

{
    ALERROR error;
    CMissile *pMissile;

    pMissile = new CMissile;
    if (pMissile == NULL)
        return ERR_MEMORY;

    pMissile->Place(vPos, vVel);

    //	We can't save missiles without an UNID
    ASSERT(!pDesc->m_sUNID.IsBlank());

    //	Don't bother telling others when we are destroyed (Note that
    //	if we do this then we also need to set the CannotBeHit flag;
    //	otherwise we will crash when a beam hits us. This is because
    //	m_pHit is setup in Move and the object can go away between then
    //	and our Update event.)
    if (pDesc->GetInteraction() == 0)
    {
        pMissile->DisableObjectDestructionNotify();
        pMissile->SetCannotBeHit();
    }

    //	Get notifications when other objects are destroyed
    pMissile->SetObjectDestructionHook();

    pMissile->m_pDesc = pDesc;
    pMissile->m_iBonus = iBonus;
    pMissile->m_iCause = iCause;
    pMissile->m_iHitPoints = pDesc->GetHitPoints();
    pMissile->m_iLifeLeft = pDesc->GetLifetime();
    pMissile->m_iTick = 0;
    pMissile->m_Source = Source;
    pMissile->m_pHit = NULL;
    pMissile->m_iRotation = iRotation;
    pMissile->m_pTarget = pTarget;
    pMissile->m_fDestroyed = false;
    pMissile->m_fReflection = false;
    pMissile->m_fDetonate = false;
    pMissile->m_fPassthrough = false;
    pMissile->m_dwSpareFlags = 0;

    //	Friendly fire

    if (!pDesc->CanHitFriends())
        pMissile->SetNoFriendlyFire();

    //	Remember the sovereign of the source (in case the source is destroyed)

    pMissile->m_pSovereign = pMissile->m_Source.GetSovereign();

    //	Create a painter instance

    CEffectCreator *pEffect;
    if (pEffect = pDesc->GetEffect())
    {
        pMissile->m_pPainter = pEffect->CreatePainter();
        pMissile->SetBounds(pMissile->m_pPainter);
    }

    //	Create exhaust trail, if necessary

    if (pDesc->m_iExhaustRate > 0)
    {
        int iCount = (pDesc->m_iExhaustLifetime / pDesc->m_iExhaustRate) + 1;
        pMissile->m_pExhaust = new TQueue<SExhaustParticle>(iCount);
    }
    else
        pMissile->m_pExhaust = NULL;

    //	Create vapor trail, if necessary

    if (pDesc->GetVaporTrailWidth())
        pMissile->SetBounds(2048.0 * g_KlicksPerPixel);

    //	Add to system

    if (error = pMissile->AddToSystem(pSystem))
    {
        delete pMissile;
        return error;
    }

    //	Done

    if (retpMissile)
        *retpMissile = pMissile;

    return NOERROR;
}