Beispiel #1
0
void CShieldClass::CalcMinMaxHP (CItemCtx &Ctx, int iCharges, int iArmorSegs, int iTotalHP, int *retiMin, int *retiMax) const

//	CalcMinMaxHP
//
//	Returns the min and max HP of this shield
//
//	iCharges = m_iMaxCharges or the current charges on item
//	iArmorSegs = count of armor segments on ship (or 0)
//	iTotalHP = current total HP of all armor segments (or 0)

	{
	int iMax = m_iHitPoints;
	int iMin = iMax;

	if (m_iExtraHPPerCharge)
		iMax = Max(0, iMax + (m_iExtraHPPerCharge * iCharges));

	if (m_iArmorShield)
		{
		iMin = m_iArmorShield;

		if (iArmorSegs > 0)
			iMax = Min(iMax, ((m_iArmorShield * iTotalHP / iArmorSegs) + 5) / 10);
		}

	//	If we're installed, fire the custom event to get max HPs

	if (Ctx.GetSource() && Ctx.GetDevice())
		{
		CItemEnhancementStack *pEnhancements = Ctx.GetDevice()->GetEnhancements();

		iMax = FireGetMaxHP(Ctx.GetDevice(), Ctx.GetSource(), iMax);

		//	Apply bonus from device (which includes mods)

		if (pEnhancements)
			iMax += (iMax * pEnhancements->GetBonus() / 100);
		}

	//	Otherwise, we just apply mods

	else
		{
		const CItemEnhancement &Mods = Ctx.GetMods();
		if (Mods.IsNotEmpty())
			iMax = iMax * Mods.GetHPAdj() / 100;
		}

	//	Done

	if (iMin > iMax)
		iMin = iMax;

	if (retiMin)
		*retiMin = iMin;

	if (retiMax)
		*retiMax = iMax;
	}
Beispiel #2
0
void CDeviceClass::AccumulateAttributes (CItemCtx &ItemCtx, int iVariant, TArray<SDisplayAttribute> *retList)

//	AccumulateAttributes
//
//	Add display attributes to the list.

	{
	//	Add general device attributes. If we have a variant, then it means 
	//	we're interested in the attributes for a missile/ammo of the device 
	//	(not the device itself).

	if (iVariant == -1)
		{
		CInstalledDevice *pDevice = ItemCtx.GetDevice();

		//	Linked-fire

		DWORD dwOptions = GetLinkedFireOptions(ItemCtx);
		if (dwOptions != 0)
			retList->Insert(SDisplayAttribute(attribPositive, CONSTLIT("linked-fire")));
		}

	//	Let our subclasses add their own attributes

	OnAccumulateAttributes(ItemCtx, iVariant, retList);
	}
Beispiel #3
0
bool CDeviceClass::AccumulateEnhancements (CItemCtx &Device, CInstalledDevice *pTarget, TArray<CString> &EnhancementIDs, CItemEnhancementStack *pEnhancements)

//	AccumulateEnhancements
//
//	If this device can enhance pTarget, then we add to the list of enhancements.

	{
	int i;
	bool bEnhanced = false;

	CInstalledDevice *pDevice = Device.GetDevice();
	CSpaceObject *pSource = Device.GetSource();

	//	See if we can enhance the target device

	if (pDevice == NULL 
			|| (pDevice->IsEnabled() && !pDevice->IsDamaged()))
		{
		for (i = 0; i < m_Enhancements.GetCount(); i++)
			{
			//	If this type of enhancement has already been applied, skip it

			if (!m_Enhancements[i].sType.IsBlank()
					&& EnhancementIDs.Find(m_Enhancements[i].sType))
				continue;

			//	If we don't match the criteria, skip it.

			if (pSource 
					&& pTarget
					&& !pSource->GetItemForDevice(pTarget).MatchesCriteria(m_Enhancements[i].Criteria))
				continue;

			//	Add the enhancement

			pEnhancements->Insert(m_Enhancements[i].Enhancement);
			bEnhanced = true;

			//	Remember that we added this enhancement class

			if (!m_Enhancements[i].sType.IsBlank())
				EnhancementIDs.Insert(m_Enhancements[i].sType);
			}
		}

	//	Let sub-classes add their own

	if (OnAccumulateEnhancements(Device, pTarget, EnhancementIDs, pEnhancements))
		bEnhanced = true;

	//	Done

	return bEnhanced;
	}
Beispiel #4
0
CString CDeviceClass::GetReference (CItemCtx &Ctx, int iVariant, DWORD dwFlags)

//	GetReference
//
//	Returns reference string

	{
	CString sReference;
	
	//	For a device we always add power and other properties.
	//	(If iVariant != -1 then it means that we're looking for reference on a
	//	missile or someting).
	
	if (iVariant == -1)
		{
		CInstalledDevice *pDevice = Ctx.GetDevice();

		//	Start with power requirements

		AppendReferenceString(&sReference, GetReferencePower(Ctx));

		//	Non-standard slots

		if (GetSlotsRequired() != 1)
			AppendReferenceString(&sReference, strPatternSubst(CONSTLIT("%d Slots"), GetSlotsRequired()));

		//	External devices

		if (IsExternal() || (pDevice && pDevice->IsExternal()))
			AppendReferenceString(&sReference, CONSTLIT("External"));
		}

	//	Combine with our subclass

	AppendReferenceString(&sReference, OnGetReference(Ctx, iVariant, dwFlags));
	return sReference;
	}
int CItemEnhancementStack::CalcActivateDelay (CItemCtx &DeviceCtx) const

//	CalcActivateDelay
//
//	Calculates the activation delay (in ticks) for the given device if we apply
//	this enhancement stack.

	{
	int i;

	CInstalledDevice *pDevice = DeviceCtx.GetDevice();
	if (pDevice == NULL)
		return 0;

	Metric rDelay = -1.0;
	for (i = 0; i < m_Stack.GetCount(); i++)
		{
		int iMin, iMax;
		int iAdj = m_Stack[i].GetActivateRateAdj(&iMin, &iMax);
		if (iAdj != 100)
			{
			if (rDelay < 0.0)
				{
				pDevice->SetActivateDelayAdj(100);
				rDelay = pDevice->GetActivateDelay(DeviceCtx.GetSource());
				}

			rDelay = iAdj * rDelay / 100.0;
			if (rDelay < (Metric)iMin)
				rDelay = (Metric)iMin;
			else if (iMax > 0 && rDelay > (Metric)iMax)
				rDelay = (Metric)iMax;
			}
		}

	return (rDelay < 0.0 ? 100 : (int)(rDelay + 0.5));
	}
Beispiel #6
0
int CItemEnhancementStack::CalcActivateDelay (CItemCtx &DeviceCtx) const

//	CalcActivateDelay
//
//	Calculates the activation delay (in ticks) for the given device if we apply
//	this enhancement stack.

	{
	int i;

	CInstalledDevice *pDevice = DeviceCtx.GetDevice();
	if (pDevice == NULL)
		return 0;

	//	Get the raw activation delay. NOTE: This DOES NOT include
	//	any enhancements on the item.

	Metric rDelay = pDevice->GetClass()->GetActivateDelay(pDevice, DeviceCtx.GetSource());

	//	Apply enhancements (including on the item itself)

	for (i = 0; i < m_Stack.GetCount(); i++)
		{
		int iMin, iMax;
		int iAdj = m_Stack[i].GetActivateRateAdj(&iMin, &iMax);
		if (iAdj != 100)
			{
			rDelay = iAdj * rDelay / 100.0;
			if (rDelay < (Metric)iMin)
				rDelay = (Metric)iMin;
			else if (iMax > 0 && rDelay > (Metric)iMax)
				rDelay = (Metric)iMax;
			}
		}

	return (int)(rDelay + 0.5);
	}
Beispiel #7
0
bool CDeviceClass::SetItemProperty (CItemCtx &Ctx, const CString &sName, ICCItem *pValue, CString *retsError)

//	SetItemProperty
//
//	Sets a device property. Subclasses should call this if they do not 
//	understand the property.

	{
	CCodeChain &CC = g_pUniverse->GetCC();

	//	Get the installed device. We need this to set anything.

	CInstalledDevice *pDevice = Ctx.GetDevice();
	if (pDevice == NULL)
		{
		*retsError = CONSTLIT("Item is not an installed device on object.");
		return false;
		}

	//	Figure out what to set

	if (strEquals(sName, PROPERTY_FIRE_ARC))
		{
		//	A value of nil means no fire arc (and no omni)

		if (pValue == NULL || pValue->IsNil())
			{
			pDevice->SetOmniDirectional(false);
			pDevice->SetFireArc(0, 0);
			}

		//	A value of "omnidirectional" counts

		else if (strEquals(pValue->GetStringValue(), PROPERTY_OMNIDIRECTIONAL))
			{
			pDevice->SetOmniDirectional(true);
			pDevice->SetFireArc(0, 0);
			}

		//	A single value means that we just point in a direction

		else if (pValue->GetCount() == 1)
			{
			int iMinFireArc = AngleMod(pValue->GetElement(0)->GetIntegerValue());
			pDevice->SetOmniDirectional(false);
			pDevice->SetFireArc(iMinFireArc, iMinFireArc);
			}

		//	Otherwise we expect a list with two elements

		else if (pValue->GetCount() >= 2)
			{
			int iMinFireArc = AngleMod(pValue->GetElement(0)->GetIntegerValue());
			int iMaxFireArc = AngleMod(pValue->GetElement(1)->GetIntegerValue());
			pDevice->SetOmniDirectional(false);
			pDevice->SetFireArc(iMinFireArc, iMaxFireArc);
			}

		//	Invalid

		else
			{
			*retsError = CONSTLIT("Invalid fireArc parameter.");
			return false;
			}
		}

	else if (strEquals(sName, PROPERTY_LINKED_FIRE_OPTIONS))
		{
		//	Parse the options

		DWORD dwOptions;
		if (!::GetLinkedFireOptions(pValue, &dwOptions, retsError))
			return false;

		//	Set

		pDevice->SetLinkedFireOptions(dwOptions);
		}

	else if (strEquals(sName, PROPERTY_POS))
		{
		//	Get the parameters. We accept a single list parameter with angle/radius/z.
		//	(The latter is compatible with the return of objGetDevicePos.)

		int iPosAngle;
		int iPosRadius;
		int iZ;
		if (pValue == NULL || pValue->IsNil())
			{
			iPosAngle = 0;
			iPosRadius = 0;
			iZ = 0;
			}
		else if (pValue->GetCount() >= 2)
			{
			iPosAngle = pValue->GetElement(0)->GetIntegerValue();
			iPosRadius = pValue->GetElement(1)->GetIntegerValue();

			if (pValue->GetCount() >= 3)
				iZ = pValue->GetElement(2)->GetIntegerValue();
			else
				iZ = 0;
			}
		else
			{
			*retsError = CONSTLIT("Invalid angle and radius");
			return false;
			}

		//	Set it

		pDevice->SetPosAngle(iPosAngle);
		pDevice->SetPosRadius(iPosRadius);
		pDevice->SetPosZ(iZ);
		}

	else if (strEquals(sName, PROPERTY_SECONDARY))
		{
		if (pValue == NULL || !pValue->IsNil())
			pDevice->SetSecondary(true);
		else
			pDevice->SetSecondary(false);
		}

	else
		{
		*retsError = strPatternSubst(CONSTLIT("Unknown item property: %s."), sName);
		return false;
		}

	return true;
	}