Promotions

Thalassicus

Bytes and Nibblers
Joined
Nov 9, 2005
Messages
11,057
Location
Texas
I'm unable to select the Guerrilla promotion when units have the necessary prerequisite and experience. What did I do wrong?

Code:
<UnitPromotions>
  <Row>
    <Type>PROMOTION_GUERRILLA</Type>
    <Description>TXT_KEY_PROMOTION_GUERRILLA</Description>
    <PediaEntry>TXT_KEY_PROMOTION_GUERRILLA</PediaEntry>
    <Help>TXT_KEY_PROMOTION_GUERRILLA_HELP</Help>
    <Sound>AS2D_IF_LEVELUP</Sound>
    <PromotionPrereqOr1>PROMOTION_PROFESSIONAL_ARMY</PromotionPrereqOr1>
    <OrderPriority>3</OrderPriority>
    <PortraitIndex>23</PortraitIndex>
    <IconAtlas>PROMOTION_ATLAS</IconAtlas>
    <PediaType>PEDIA_MELEE</PediaType>
  </Row>
</UnitPromotions>
<UnitPromotions_UnitCombats>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_ARCHER</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_MOUNTED</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_MELEE</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_GUN</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_ARMOR</UnitCombatType>
  </Row>
</UnitPromotions_UnitCombats>
<UnitPromotions_Terrains>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <TerrainType>TERRAIN_HILLS</TerrainType>
    <DoubleMove>true</DoubleMove>
  </Row>
</UnitPromotions_Terrains>

Code:
<UnitPromotions>
  <Row>
    <Type>PROMOTION_PROFESSIONAL_ARMY</Type>
    <Description>TXT_KEY_PROMOTION_PROFESSIONAL_ARMY</Description>
    <Help>TXT_KEY_PROMOTION_PROFESSIONAL_ARMY_HELP</Help>
    <Sound>AS2D_IF_LEVELUP</Sound>
    <CannotBeChosen>true</CannotBeChosen>
    <PortraitIndex>59</PortraitIndex>
    <IconAtlas>ABILITY_ATLAS</IconAtlas>
    <PediaType>PEDIA_SHARED</PediaType>
    <PediaEntry>TXT_KEY_PROMOTION_PROFESSIONAL_ARMY</PediaEntry>
  </Row>
</UnitPromotions>
<Policy_FreePromotions>
  <Row>
    <PolicyType>POLICY_PROFESSIONAL_ARMY</PolicyType>
    <PromotionType>PROMOTION_PROFESSIONAL_ARMY</PromotionType>
  </Row>
</Policy_FreePromotions>
 
There is no TERRAIN_HILLS. Hills are not a Terrain type, they're a Plot type. The Hills and Mountains entries in the Terrains table are for graphical purposes only, to tell the game which ART_DEF entries to use, nothing more.

So in this case, you can't use the UnitPromotions_Terrains table. But you don't need to; this is why there's a <HillsDoubleMove> entry in the main UnitPromotions table in the first place.
 
That's certainly an odd bug with the UnitPromotions_Terrains table! Unfortunately, changing to the other version didn't solve the problem.

To add some more information, none of the three promotions I prereq'd to Professional Army can be earned. Woodsman and Naval Siege worked when they had other prereqs. For this reason I think I made a mistake somewhere with the Professional Army settings (seen above), but I don't know what it could be. Professional Army itself works okay.

Code:
<UnitPromotions>
  <Update>
    <Where Type="PROMOTION_WOODSMAN" />
    <Set PromotionPrereqOr1="PROMOTION_PROFESSIONAL_ARMY"
       PromotionPrereqOr2="NULL"
       />
  </Update>
  <Row>
    <Type>PROMOTION_NAVAL_SIEGE</Type>
    <Description>TXT_KEY_PROMOTION_SIEGE</Description>
    <Help>TXT_KEY_PROMOTION_SIEGE_HELP</Help>
    <Sound>AS2D_IF_LEVELUP</Sound>
    <PromotionPrereqOr1>PROMOTION_PROFESSIONAL_ARMY</PromotionPrereqOr1>
    <OrderPriority>3</OrderPriority>
    <CityAttack>35</CityAttack>
    <PortraitIndex>40</PortraitIndex>
    <IconAtlas>PROMOTION_ATLAS</IconAtlas>
    <PediaType>PEDIA_NAVAL</PediaType>
    <PediaEntry>TXT_KEY_PROMOTION_SIEGE</PediaEntry>
  </Row>
  <Row>
    <Type>PROMOTION_GUERRILLA</Type>
    <Description>TXT_KEY_PROMOTION_GUERRILLA</Description>
    <PediaEntry>TXT_KEY_PROMOTION_GUERRILLA</PediaEntry>
    <Help>TXT_KEY_PROMOTION_GUERRILLA_HELP</Help>
    <Sound>AS2D_IF_LEVELUP</Sound>
    <PromotionPrereqOr1>PROMOTION_PROFESSIONAL_ARMY</PromotionPrereqOr1>
    <HillsDoubleMove>true</HillsDoubleMove>
    <OrderPriority>3</OrderPriority>
    <PortraitIndex>23</PortraitIndex>
    <IconAtlas>PROMOTION_ATLAS</IconAtlas>
    <PediaType>PEDIA_MELEE</PediaType>
  </Row>
</UnitPromotions>
<UnitPromotions_UnitCombats>
  <Row>
    <PromotionType>PROMOTION_NAVAL_SIEGE</PromotionType>
    <UnitCombatType>UNITCOMBAT_NAVAL</UnitCombatType>
  </Row>
  <Delete PromotionType="PROMOTION_WOODSMAN" />
  <Row>
    <PromotionType>PROMOTION_WOODSMAN</PromotionType>
    <UnitCombatType>UNITCOMBAT_ARCHER</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_WOODSMAN</PromotionType>
    <UnitCombatType>UNITCOMBAT_MOUNTED</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_WOODSMAN</PromotionType>
    <UnitCombatType>UNITCOMBAT_MELEE</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_WOODSMAN</PromotionType>
    <UnitCombatType>UNITCOMBAT_GUN</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_WOODSMAN</PromotionType>
    <UnitCombatType>UNITCOMBAT_ARMOR</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_ARCHER</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_MOUNTED</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_MELEE</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_GUN</UnitCombatType>
  </Row>
  <Row>
    <PromotionType>PROMOTION_GUERRILLA</PromotionType>
    <UnitCombatType>UNITCOMBAT_ARMOR</UnitCombatType>
  </Row>
</UnitPromotions_UnitCombats>
 
I figured this out by narrowing it down to the two tables below.

This works:
Code:
<Unit_FreePromotions>
  <Row>
    <UnitType>UNIT_WARRIOR</UnitType>
    <PromotionType>PROMOTION_PROFESSIONAL_ARMY</PromotionType>
  </Row>
</Unit_FreePromotions>
This does not:
Code:
<Policy_FreePromotions>
  <Row>
    <PolicyType>POLICY_PROFESSIONAL_ARMY</PolicyType>
    <PromotionType>PROMOTION_PROFESSIONAL_ARMY</PromotionType>
  </Row>
</Policy_FreePromotions>
Both of these give the Professional Army promotion correctly. However, if other promotions require Professional Army, #1 works but not #2. The only explanation I can think of is a bug from poorly-designed code. It seems like this is what happens:

  1. Check if the unit has the prerequisite promotion.
  2. Check if the prereq has CannotBeChosen=false and is in one of these tables:
    • UnitPromotions_UnitCombats
    • Unit_FreePromotions
  3. Recursively start at step 1 for the prereq's prereq.

This is bad design because if a unit has a promotion, it's pointless to check if it can have that promotion! :lol: The design also makes it easy to introduce bugs like forgetting to check Policy_FreePromotions. The better solution is to only do step 1. The other steps waste processing power and resulted in buggy code.

Restrictions on features due to a lack of c++ access don't bother me much, still lots of stuff we can do... but when it's obvious where a bug is and how to fix it, but can't, and it's due to bad design, that's really frustrating! :hammer2:

Anyone have ideas? I've been trying things in the hopes of finding a workaround:

  • Give it earnable combat classes but set CannotBeChosen=true (failed, checks that).
  • Do not set CannotBeChosen, but give it no earnable combat classes (checks for both).
  • Make the prereq okay, but give the prereq a prereq that cannot be earned (recursive).
  • Instead of Policy_FreePromotions, use Policy_FreePromotionUnitCombats (apparently second table is not implemented in the c++).
  • Manually code it with lua (no event detects when a policy is acquired).
 
However, if other promotions require Professional Army, #1 works but not #2.

There are a lot of bits like this. For instance, I'd wanted to make the Colosseum require a Temple in the city. It works fine for an Ancient-era start, but let's say you start a game in the Industrial Era. Both buildings have FreeStartEra at or before that era, so it should give you both of them in every city. Except it doesn't, because the Colosseum has a lower ID number than the Temple. So it goes down the list, sees the Colosseum, and won't award it to your cities because there's no Temple yet.

So I'm not surprised that the policy award is screwing things up.
 
The behavior may be even weirder than you describe. I was playing around with some things myself and saw the following:

With the initially-posted XML plus additional UnitPromotions_UnitCombats entries for the Professional Army, a newly-built warrior after policy acquisition would get the Professional Army promotion but not be able to choose the Guerilla Promotion.

However, if I changed the Guerilla to have a second OR prereq of Drill 1, then the Guerilla promotion was available when it was built (even though the unit didn't have Drill 1.) It's like the second possible prereq suddenly triggered the Professional Army prereq to work properly.
 
I suspected that might work. If *any* of the prereqs can be earned, it figures the promotion can be earned. The real trick is I'm trying to make promotions that are unlocked with a policy. I need to somehow block it from normal aquisition, and if it has Drill 1 as an or...
 
Back
Top Bottom