Trebuchet vs Catapults

Collateral damage for both are exactly the same:

<iCollateralDamage>100</iCollateralDamage>
<iCollateralDamageLimit>50</iCollateralDamageLimit>
<iCollateralDamageMaxUnits>6</iCollateralDamageMaxUnits>

but Trebuchet get 100% bonus on city attacks with a base strength that's only 1 less than a Catapult. You do the math.

Seriously? Evidently stealth bombers do the same collateral damage as a catapult. Come on, 6000+ post members shouldn't have such rookie misunderstandings.

Cannon
Code:
  <iCollateralDamage>100</iCollateralDamage> 
  <iCollateralDamageLimit>60</iCollateralDamageLimit> 
  <iCollateralDamageMaxUnits>7</iCollateralDamageMaxUnits>
Artillery
Code:
  <iCollateralDamage>100</iCollateralDamage> 
  <iCollateralDamageLimit>70</iCollateralDamageLimit> 
  <iCollateralDamageMaxUnits>8</iCollateralDamageMaxUnits>
Battleship, ChoKoNu, Missile Cruiser
Code:
  <iCollateralDamage>50</iCollateralDamage> 
  <iCollateralDamageLimit>60</iCollateralDamageLimit> 
  <iCollateralDamageMaxUnits>5</iCollateralDamageMaxUnits>
Bomber
Code:
  <iCollateralDamage>100</iCollateralDamage> 
  <iCollateralDamageLimit>50</iCollateralDamageLimit> 
  <iCollateralDamageMaxUnits>5</iCollateralDamageMaxUnits>
Stealth Bombers
Code:
  <iCollateralDamage>100</iCollateralDamage> 
  <iCollateralDamageLimit>50</iCollateralDamageLimit> 
  <iCollateralDamageMaxUnits>6</iCollateralDamageMaxUnits>
 
Code:
int iCollateralStrength = (getDomainType() == DOMAIN_AIR ? airBaseCombatStr() : baseCombatStr()) * collateralDamage() / 100;
That's the base.

I think I have posted the code quite a few times. Keep in mind, the xml doesn't tell you anything at all, the code dose. People can speculate about the meaning of the values in the xml due to human friendly names, but that's all about it.
Spoiler :

Code:
void CvUnit::collateralCombat(const CvPlot* pPlot, CvUnit* pSkipUnit)
{
	CLLNode<IDInfo>* pUnitNode;
	CvUnit* pLoopUnit;
	CvUnit* pBestUnit;
	CvWString szBuffer;
	int iTheirStrength;
	int iStrengthFactor;
	int iCollateralDamage;
	int iUnitDamage;
	int iDamageCount;
	int iPossibleTargets;
	int iCount;
	int iValue;
	int iBestValue;
	std::map<CvUnit*, int> mapUnitDamage;
	std::map<CvUnit*, int>::iterator it;

[B]	int iCollateralStrength = (getDomainType() == DOMAIN_AIR ? airBaseCombatStr() : baseCombatStr()) * collateralDamage() / 100;[/B]
	if (iCollateralStrength == 0)
	{
		return;
	}

	iPossibleTargets = std::min((pPlot->getNumVisibleEnemyDefenders(this) - 1), collateralDamageMaxUnits());

	pUnitNode = pPlot->headUnitNode();

	while (pUnitNode != NULL)
	{
		pLoopUnit = ::getUnit(pUnitNode->m_data);
		pUnitNode = pPlot->nextUnitNode(pUnitNode);

		if (pLoopUnit != pSkipUnit)
		{
			if (isEnemy(pLoopUnit->getTeam(), pPlot))
			{
				if (!(pLoopUnit->isInvisible(getTeam(), false)))
				{
					if (pLoopUnit->canDefend())
					{
						iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "Collateral Damage"));

						iValue *= pLoopUnit->currHitPoints();

						mapUnitDamage[pLoopUnit] = iValue;
					}
				}
			}
		}
	}

	CvCity* pCity = NULL;
	if (getDomainType() == DOMAIN_AIR)
	{
		pCity = pPlot->getPlotCity();
	}

	iDamageCount = 0;
	iCount = 0;

	while (iCount < iPossibleTargets)
	{
		iBestValue = 0;
		pBestUnit = NULL;

		for (it = mapUnitDamage.begin(); it != mapUnitDamage.end(); it++)
		{
			if (it->second > iBestValue)
			{
				iBestValue = it->second;
				pBestUnit = it->first;
			}
		}

		if (pBestUnit != NULL)
		{
			mapUnitDamage.erase(pBestUnit);

			if (NO_UNITCOMBAT == getUnitCombatType() || !pBestUnit->getUnitInfo().getUnitCombatCollateralImmune(getUnitCombatType()))
			{
				[B]iTheirStrength = pBestUnit->baseCombatStr();

				iStrengthFactor = ((iCollateralStrength + iTheirStrength + 1) / 2);

				iCollateralDamage = (GC.getDefineINT("COLLATERAL_COMBAT_DAMAGE") * (iCollateralStrength + iStrengthFactor)) / (iTheirStrength + iStrengthFactor);

				iCollateralDamage *= 100 + getExtraCollateralDamage();
[/B]
				iCollateralDamage *= std::max(0, 100 - pBestUnit->getCollateralDamageProtection());
				iCollateralDamage /= 100;

				if (pCity != NULL)
				{
					iCollateralDamage *= 100 + pCity->getAirModifier();
					iCollateralDamage /= 100;
				}

				iCollateralDamage /= 100;

				iCollateralDamage = std::max(0, iCollateralDamage);

				int iMaxDamage = std::min(collateralDamageLimit(), (collateralDamageLimit() * (iCollateralStrength + iStrengthFactor)) / (iTheirStrength + iStrengthFactor));
				iUnitDamage = std::max(pBestUnit->getDamage(), std::min(pBestUnit->getDamage() + iCollateralDamage, iMaxDamage));

				if (pBestUnit->getDamage() != iUnitDamage)
				{
					pBestUnit->setDamage(iUnitDamage, getOwnerINLINE());
					iDamageCount++;
				}
			}

			iCount++;
		}
		else
		{
			break;
		}
	}

	if (iDamageCount > 0)
	{
		szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_SUFFER_COL_DMG", iDamageCount);
		gDLL->getInterfaceIFace()->addMessage(pSkipUnit->getOwnerINLINE(), (pSkipUnit->getDomainType() != DOMAIN_AIR), GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_COLLATERAL", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pSkipUnit->getX_INLINE(), pSkipUnit->getY_INLINE(), true, true);

		szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_INFLICT_COL_DMG", getNameKey(), iDamageCount);
		gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_COLLATERAL", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pSkipUnit->getX_INLINE(), pSkipUnit->getY_INLINE());
	}
}
 
I think it's unrealistic to just compare the units directly. To prevent rude surprises, a stack will need dedicated defenders to discourage attack (with counter or terrain promotions), and it usually pays off to have a small number of varied units so you have the most effective tool available when you need it.
After these, I usually devote the rest to can openers because in the medieval era taking cities requires a bit of effort. Here imo the alternatives are 2 Catapults + 2 Macemen or 3 Trebuchets?

The first is a lot more robust - even promoted with CR, Macemen and Catapults aren't hopeless in the field. They also fulfil their roles just fine - in a suicide charge Catapults deal twice as much collateral per hammer as Trebuchets. Accuracy cats also do their job very efficiently. Once the opponent is worn down, Macemen can clean up efficiently and with few losses, chances are you just have to replace the catapults.

The second option is in my opinion more efficient if things go well. Maybe you're better off suiciding one Barrage Catapult at first against particularly hard targets, but Trebuchets get decent odds quickly and make the job easier for subsequent attackers. With a large complement of Trebuchets, you can wear down the defenders to a point where anything can mop up without taking much damage, including stack defenders not promoted for cleanup duty. Similarly, damaged Trebuchets are still useful enough for bombarding defences, no need for Accuracy.

Against competent humans, I'd need something flexible that'll serve me well if things go south and would not build many Trebuchets. Against the AI they are a big part of what makes medieval war attractive and I'll build as many as I can get away with.
 
Back
Top Bottom