What factors affect a unit's contribution to city defense?
From what I've read, a unit garrisoned in a city has precisely one effect: the city's combat score is increased by a fraction of the unit's Strength (I've seen "1/3" and "1/5"). Its hitpoints are not increased, so rushing a military unit into a city that's about to fall is usually a waste of a unit.
Does anything else affect this? Are there promotions which make a unit more or less suitable as a garrison? Does a unit's presence in a city trigger attackers' bonuses or penalties against certain types of units (e.g., does a Pikeman get a bonus attacking a city garrisoned by a cavalry unit)?
A unit in a city can still attack, and then of course all the normal modifiers come into play. I'm only interested in defending a city at the moment.
Attack bonuses against units do not apply when attacking cities. The strength a unit adds varies mainly depending on it's own strength and current hp, and whether you have Oligarchy or not.
As for the strength formula, I looked at the code and this seems relevant: http://pastebin.com/3nCiC3Qv
Looks like city strength depends on the following:
- Number of techs
- Terrain
- Defensive buildings
- Garrison unit
- Population
- Religion
Specifically, the part concerning units:
// Garrisoned Unit
CvUnit* pGarrisonedUnit = GetGarrisonedUnit();
int iStrengthFromUnits = 0;
if(pGarrisonedUnit)
{
int iMaxHits = GC.getMAX_HIT_POINTS();
iStrengthFromUnits = pGarrisonedUnit->GetBaseCombatStrength() * 100 * (iMaxHits - pGarrisonedUnit->getDamage()) / iMaxHits;
}
iStrengthValue += ((iStrengthFromUnits * 100) / /*300*/ GC.getCITY_STRENGTH_UNIT_DIVISOR());
So the formula for the strength a unit adds seems to be (Unit Combat Strength * 100) * Current Unit HP / Maximum Unit HP. This value is then apparently multiplied by 100 and divided by CITY_STRENGTH_UNIT_DIVISOR (which is 500 according to GlobalDefines.xml). Then in
iValue *= /*40*/ GC.getCITY_RANGED_ATTACK_STRENGTH_MULTIPLIER();
iValue /= 100;
it is multiplied by CITY_RANGED_ATTACK_STRENGTH_MULTIPLIER (which is 75 according to GlobalDefines.xml) and divided by 100.
Finally, in
if(GetGarrisonedUnit())
{
iValue *= (100 + GET_PLAYER(m_eOwner).GetGarrisonedCityRangeStrikeModifier());
iValue /= 100;
}
it is multiplied by 100 + GetGarrisonedCityRangeStrikeModifier (which seems to be 0 normally and 100 with Oligarchy according to CIV5Policies.xml) and divided by 100 again.