예제 #1
0
int CArmorClass::GetMaxHP (CItemCtx &ItemCtx)

//	GetMaxHP
//
//	Returns the max HP for this kind of armor

	{
	//	Start with hit points defined by the class

	int iHP = m_iHitPoints;

	//	Fire event to compute HP, if necessary

	iHP = FireGetMaxHP(ItemCtx, iHP);

	//	Add mods

	const CItemEnhancement &Mods = ItemCtx.GetMods();
	if (Mods.IsNotEmpty())
		iHP = iHP * Mods.GetHPAdj() / 100;

	//	Add complete bonus

	CInstalledArmor *pSect = ItemCtx.GetArmor();
	if (pSect && pSect->IsComplete())
		iHP += m_iArmorCompleteBonus;

	//	Done

	return iHP;
	}
예제 #2
0
void CArmorClass::CalcAdjustedDamage (CItemCtx &ItemCtx, SDamageCtx &Ctx)

//	CalcAdjustedDamage
//
//	Modifies Ctx.iDamage to account for damage type adjustments, etc.

	{
	CInstalledArmor *pArmor = ItemCtx.GetArmor();

	//	Adjust for special armor damage:
	//
	//	<0	=	2.5x damage
	//	0	=	2x damage
	//	1	=	1.5x damage
	//	2	=	1.25x damage
	//	>2	=	1x damage

	int iDamageLevel = Ctx.Damage.GetArmorDamageLevel();
	if (iDamageLevel > 0)
		Ctx.iDamage = (CalcArmorDamageAdj(Ctx.Damage) * Ctx.iDamage + 50) / 100;

	//	Adjust for damage type

	int iDamageAdj = GetDamageAdj((pArmor ? pArmor->GetMods() : CItemEnhancement()), Ctx.Damage);
	Ctx.iDamage = (iDamageAdj * Ctx.iDamage + 50) / 100;
	}
예제 #3
0
void CArmorClass::CalcAdjustedDamage (CItemCtx &ItemCtx, SDamageCtx &Ctx)

//	CalcAdjustedDamage
//
//	Modifies Ctx.iDamage to account for damage type adjustments, etc.

	{
	CInstalledArmor *pArmor = ItemCtx.GetArmor();

	//	Adjust for special armor damage:
	//
	//	<0	=	2.5x damage
	//	0	=	2x damage
	//	1	=	1.5x damage
	//	2	=	1.25x damage
	//	>2	=	1x damage

	int iDamageLevel = Ctx.Damage.GetArmorDamageLevel();
	if (iDamageLevel > 0)
		{
		int iDiff = m_pItemType->GetLevel() - iDamageLevel;
		int iAdj;

		switch (iDiff)
			{
			case 0:
				iAdj = 200;
				break;

			case 1:
				iAdj = 150;
				break;

			case 2:
				iAdj = 125;
				break;

			default:
				if (iDiff < 0)
					iAdj = 250;
				else
					iAdj = 100;
			}

		Ctx.iDamage = (iAdj * Ctx.iDamage + 50) / 100;
		}

	//	Adjust for damage type

	int iDamageAdj = GetDamageAdj((pArmor ? pArmor->GetMods() : CItemEnhancement()), Ctx.Damage);
	Ctx.iDamage = (iDamageAdj * Ctx.iDamage + 50) / 100;
	}
예제 #4
0
bool CArmorClass::IsReflective (CItemCtx &ItemCtx, const DamageDesc &Damage)

//	IsReflective
//
//	Returns TRUE if the armor reflects this damage

	{
	const CItemEnhancement &Mods = ItemCtx.GetMods();

	int iReflectChance = 0;

	//	Base armor chance

	if (m_Reflective.InSet(Damage.GetDamageType()))
		iReflectChance = MAX_REFLECTION_CHANCE;

	//	Mods

	int iModReflect;
	if (Mods.IsNotEmpty() && Mods.IsReflective(Damage, &iModReflect))
		iReflectChance = Max(iReflectChance, iModReflect);

	//	Done

	if (iReflectChance)
		{
		CInstalledArmor *pSect = ItemCtx.GetArmor();

		int iMaxHP = GetMaxHP(ItemCtx);
		int iHP = (pSect ? pSect->GetHitPoints() : iMaxHP);

		//	Adjust based on how damaged the armor is

		iReflectChance = (iMaxHP > 0 ? iHP * iReflectChance / iMaxHP : iReflectChance);

		return (mathRandom(1, 100) <= iReflectChance);
		}
	else
		return false;
	}
예제 #5
0
void CArmorClass::CalcDamageEffects (CItemCtx &ItemCtx, SDamageCtx &Ctx)

//	CalcDamageEffects
//
//	Initialize the damage effects based on the damage and on this armor type.

	{
	CSpaceObject *pSource = ItemCtx.GetSource();
	CInstalledArmor *pArmor = ItemCtx.GetArmor();

	//	Compute all the effects (if we don't have installed armor, then the 
	//	caller is responsible for setting this).

	if (pArmor)
		Ctx.iHPLeft = pArmor->GetHitPoints();

	//	Reflect

	Ctx.bReflect = (IsReflective(ItemCtx, Ctx.Damage) && Ctx.iDamage > 0);

	//	Disintegration

	int iDisintegration = Ctx.Damage.GetDisintegrationDamage();
	Ctx.bDisintegrate = (iDisintegration > 0 && !IsDisintegrationImmune(ItemCtx));

	//	Shatter

	int iShatter = Ctx.Damage.GetShatterDamage();
	if (iShatter)
		{
		//	Compute the threshold mass. Below this size, we shatter the object

		int iMassLimit = 10 * mathPower(5, iShatter);
		Ctx.bShatter = (pSource && pSource->GetMass() < iMassLimit);
		}
	else
		Ctx.bShatter = false;

	//	Blinding

	int iBlinding = Ctx.Damage.GetBlindingDamage();
	if (iBlinding && !IsBlindingDamageImmune(ItemCtx))
		{
		//	The chance of being blinded is dependent
		//	on the rating.

		int iChance = 4 * iBlinding * iBlinding * GetBlindingDamageAdj() / 100;
		Ctx.bBlind = (mathRandom(1, 100) <= iChance);
		Ctx.iBlindTime = Ctx.iDamage * g_TicksPerSecond / 2;
		}
	else
		Ctx.bBlind = false;

	//	EMP

	int iEMP = Ctx.Damage.GetEMPDamage();
	if (iEMP && !IsEMPDamageImmune(ItemCtx))
		{
		//	The chance of being paralyzed is dependent
		//	on the EMP rating.

		int iChance = 4 * iEMP * iEMP * GetEMPDamageAdj() / 100;
		Ctx.bParalyze = (mathRandom(1, 100) <= iChance);
		Ctx.iParalyzeTime = Ctx.iDamage * g_TicksPerSecond / 2;
		}
	else
		Ctx.bParalyze = false;

	//	Device disrupt

	int iDeviceDisrupt = Ctx.Damage.GetDeviceDisruptDamage();
	if (iDeviceDisrupt && !IsDeviceDamageImmune(ItemCtx))
		{
		//	The chance of damaging a device depends on the rating.

		int iChance = 4 * iDeviceDisrupt * iDeviceDisrupt * GetDeviceDamageAdj() / 100;
		Ctx.bDeviceDisrupt = (mathRandom(1, 100) <= iChance);
		Ctx.iDisruptTime = 2 * Ctx.iDamage * g_TicksPerSecond;
		}
	else
		Ctx.bDeviceDisrupt = false;

	//	Device damage

	int iDeviceDamage = Ctx.Damage.GetDeviceDamage();
	if (iDeviceDamage && !IsDeviceDamageImmune(ItemCtx))
		{
		//	The chance of damaging a device depends on the rating.

		int iChance = 4 * iDeviceDamage * iDeviceDamage * GetDeviceDamageAdj() / 100;
		Ctx.bDeviceDamage = (mathRandom(1, 100) <= iChance);
		}
	else
		Ctx.bDeviceDamage = false;

	//	Radiation

	int iRadioactive = Ctx.Damage.GetRadiationDamage();
	Ctx.bRadioactive = (iRadioactive > 0 && !IsRadiationImmune(ItemCtx));

	//	Some effects decrease damage

	if (iBlinding || iEMP)
		Ctx.iDamage = 0;
	else if (iDeviceDamage)
		Ctx.iDamage = Ctx.iDamage / 2;
	}
예제 #6
0
EDamageResults CArmorClass::AbsorbDamage (CItemCtx &ItemCtx, SDamageCtx &Ctx)

//	AbsorbDamage
//
//	Handles getting hit by damage.
//
//	Returns damageNoDamage if all the damage was absorbed and no further processing is necessary
//	Returns damageDestroyed if the source was destroyed
//	Returns damageArmorHit if source was damage and further processing (destroy check) is needed
//
//	Sets Ctx.iDamage to the amount of hit points left after damage absorption.

	{
	CSpaceObject *pSource = ItemCtx.GetSource();
	CInstalledArmor *pArmor = ItemCtx.GetArmor();
	if (pSource == NULL || pArmor == NULL)
		return damageNoDamage;

	//	Compute all the effects (this initializes elements in Ctx).

	CalcDamageEffects(ItemCtx, Ctx);

	//	First give custom weapons a chance

	bool bCustomDamage = Ctx.pDesc->FireOnDamageArmor(Ctx);
	if (pSource->IsDestroyed())
		return damageDestroyed;

	//	Damage adjustment

	CalcAdjustedDamage(ItemCtx, Ctx);

	//	If the armor has custom code to deal with damage, handle it here.

	FireOnArmorDamage(ItemCtx, Ctx);
	if (pSource->IsDestroyed())
		return damageDestroyed;

	//	If this armor section reflects this kind of damage then
	//	send the damage on

	if (Ctx.bReflect)
		{
		if (Ctx.pCause)
			Ctx.pCause->CreateReflection(Ctx.vHitPos, (Ctx.iDirection + 120 + mathRandom(0, 120)) % 360);
		return damageNoDamage;
		}

	//	If this is a disintegration attack, then disintegrate the ship

	if (Ctx.bDisintegrate)
		{
		if (!pSource->OnDestroyCheck(killedByDisintegration, Ctx.Attacker))
			return damageNoDamage;

		pSource->Destroy(killedByDisintegration, Ctx.Attacker);
		return damageDestroyed;
		}

	//	If this is a shatter attack, see if the ship is destroyed

	if (Ctx.bShatter)
		{
		if (!pSource->OnDestroyCheck(killedByShatter, Ctx.Attacker))
			return damageNoDamage;

		pSource->Destroy(killedByShatter, Ctx.Attacker);
		return damageDestroyed;
		}

	//	If this is a paralysis attack and we've gotten past the shields
	//	then freeze the ship.

	if (Ctx.bParalyze)
		pSource->MakeParalyzed(Ctx.iParalyzeTime);

	//	If this is blinding damage then our sensors are disabled

	if (Ctx.bBlind)
		pSource->MakeBlind(Ctx.iBlindTime);

	//	If this attack is radioactive, then contaminate the ship

	if (Ctx.bRadioactive)
		pSource->OnHitByRadioactiveDamage(Ctx);

	//	If this is device damage, then see if any device is damaged

	if (Ctx.bDeviceDamage)
		pSource->OnHitByDeviceDamage();

	if (Ctx.bDeviceDisrupt)
		pSource->OnHitByDeviceDisruptDamage(Ctx.iDisruptTime);

	//	Create a hit effect. (Many weapons show an effect even if no damage was
	//	done.)

	Ctx.pDesc->CreateHitEffect(pSource->GetSystem(), Ctx);

	//	If no damage has reached us, then we're done

	if (Ctx.iDamage == 0 && !bCustomDamage)
		return damageNoDamage;

	//	Give source events a chance to change the damage before we
	//	subtract from armor.

	if (pSource->HasOnDamageEvent())
		{
		pSource->FireOnDamage(Ctx);
		if (pSource->IsDestroyed())
			return damageDestroyed;
		}

	//	Take damage

	if (Ctx.iDamage <= pArmor->GetHitPoints())
		{
		pArmor->IncHitPoints(-Ctx.iDamage);
		Ctx.iDamage = 0;
		}
	else
		{
		Ctx.iDamage -= pArmor->GetHitPoints();
		pArmor->SetHitPoints(0);
		}

	return damageArmorHit;
	}