[R&F] Making units start with abilities/promotions

Question

King
Joined
Mar 12, 2008
Messages
950
How do you make a unit start with promotions/abilities?

For example, making scouts start with the ranger/alpine promotions already? I want to change the recon tree so that they get access two promotions other than ranger/alpine.

And how are unique unit's special abilities defined? I dont see them anywhere in units.xml. For example, hoplites get +10 combat strength when next to another hoplite. Where is that defined?

Edit : I think I found the file, UnitAbilities.xml.

So do I just put :

<Row Type="ABILITY_IGNORE_TERRAIN_COST" Tag="CLASS_RECON"/>

To make all recon units ignore terrain cost?

And does anyone know how to make a unit get buffs per era, if that is even possible? Or do you have to make a seperate unit for it to upgrade to?
 
Last edited:
I don't know if this will be helpful but Hoplite stuff is defined in UnitAbilities.xml (as you noted):
Spoiler :

Code:
       <Row>
           <UnitAbilityType>ABILITY_HOPLITE</UnitAbilityType>
           <ModifierId>HOPLITE_NEIGHBOR_COMBAT</ModifierId>
       </Row>

Code:
       <Row>
           <ModifierId>HOPLITE_NEIGHBOR_COMBAT</ModifierId>
           <ModifierType>MODIFIER_SINGLE_UNIT_ATTACH_MODIFIER</ModifierType>
           <SubjectRequirementSetId>HOPLITE_PLOT_IS_HOPLITE_REQUIREMENTS</SubjectRequirementSetId>
       </Row>

Code:
       <Row>
           <ModifierId>HOPLITE_NEIGHBOR_COMBAT_MODIFIER</ModifierId>
           <ModifierType>MODIFIER_UNIT_ADJUST_COMBAT_STRENGTH</ModifierType>
       </Row>

Code:
       <Row>
           <ModifierId>HOPLITE_NEIGHBOR_COMBAT</ModifierId>
           <Name>ModifierId</Name>
           <Value>HOPLITE_NEIGHBOR_COMBAT_MODIFIER</Value>
       </Row>

Code:
       <Row>
           <ModifierId>HOPLITE_NEIGHBOR_COMBAT_MODIFIER</ModifierId>
           <Name>Amount</Name>
           <Value>10</Value>
       </Row>

Which shows all the crap you have to inject to get the ability to work right. Since most of these already exist you should be able to get by by injecting them via the SQL game defines, so if you have the effect in mind you can write it straight in as long as you find a pre-existing effect.

I'm actually working on this myself - the civ I'm building has Warrior Monk replacements that start with Martyr. At the moment it looks like this:

Code:
--==========================================================================================================================
-- CIVILIZATIONS: TRAITS
--==========================================================================================================================
-- Types
--------------------------------------------------------------------------------------------------------------------------   
INSERT INTO Types   
       (Type,                                                   Kind)
VALUES   ('TRAIT_CIVILIZATION_UNIT_ROS_MITAKIHARA_MAGICALGIRL'   'KIND_TRAIT');   
--------------------------------------------------------------------------------------------------------------------------           
-- Traits           
--------------------------------------------------------------------------------------------------------------------------               
INSERT INTO Traits               
       (TraitType,                                                   Name,                                                   Description)
VALUES   ('TRAIT_CIVILIZATION_UNIT_ROS_MITAKIHARA_MAGICALGIRL',       'LOC_TRAIT_CIVILIZATION_UNIT_ROS_MITAKIHARA_MAGICALGIRL_NAME',           'LOC_TRAIT_CIVILIZATION_UNIT_ROS_MITAKIHARA_MAGICALGIRL_DESCRIPTION');   
--------------------------------------------------------------------------------------------------------------------------       
-- TraitModifiers       
--------------------------------------------------------------------------------------------------------------------------           
INSERT INTO TraitModifiers           
       (TraitType,                                           ModifierId)
VALUES   ('TRAIT_CIVILIZATION_UNIT_ROS_MITAKIHARA_MAGICALGIRL',   'ROS_MITAKIHARA_MAGICALGIRL_MARTYR';)
                                                                                           
--------------------------------------------------------------------------------------------------------------------------
-- Modifiers
--------------------------------------------------------------------------------------------------------------------------
INSERT INTO Modifiers   
       (ModifierId,                                               ModifierType)
VALUES   ('ROS_MITAKIHARA_MAGICALGIRL_MARTYR',                       'ROS_MITAKIHARA_MAGICALGIRL_PROMOTION_MARTYR');           

--------------------------------------------------------------------------------------------------------------------------
-- ModifierTypes
--------------------------------------------------------------------------------------------------------------------------
INSERT INTO ModifierTypes
       (ModifierType,                                               CollectionType,                                           EffectType,                                       Permanent)
       ('ROS_MITAKIHARA_MAGICALGIRL_PROMOTION_MARTYR',               'COLLECTION_PLAYER_UNITS',                               'EFFECT_GRANT_PROMOTION',                       'true');
--------------------------------------------------------------------------------------------------------------------------
-- ModifierArguments
--------------------------------------------------------------------------------------------------------------------------
INSERT INTO ModifierArguments
       (ModifierId,                                               Name,                       Value)
VALUES   ('ROS_MITAKIHARA_MAGICALGIRL_PROMOTION_MARTYR'               'PromotionType'               'PROMOTION_MARTYR');

The problem is specifically attaching it to a unit, which I'm not sure on, but hopefully something here might be useful to you?

For per-era, you might be able to find something you can use if you take a look at the files containing the data for the Walls buildings, which change based on the era?
 
@RayOfSpeed : Thanks, i figured out how to give all recon class units the ignore terrain cost ability of helicopters.

The part im confused about is how to modify the existing unit promotions exactly.

For example, lets say i want to replace the "Expert crew" promotion for siege units with "emplacement".

I go to line 215 of UnitPromotions.xml and replace it with :

Code:
       <Row UnitPromotionType="PROMOTION_EMPLACEMENT" Name="LOC_PROMOTION_EMPLACEMENT_NAME" Description="LOC_PROMOTION_EMPLACEMENT_DESCRIPTION" Level="3" Specialization="" Column="3" PromotionClass="PROMOTION_CLASS_SIEGE"/>

So in theory this should simply make the emplacement ability available instead of expert crew...but it does not work ingame and the promotion menu is still showing expert crew.

What am i missing?

Edit : Disregard, I was editing the wrong file. I managed to get it working after all.
 
Last edited:
@RayOfSpeed : In regards to walls, i dont think walls auto upgrade based on era...it seems city state strength does but according to the wiki its based on the strongest melee unit available -10 or the garrisoned unit, whichever is greater. And i cant find anything in the xml files that control this so it may be hardcoded...
 
Gotta love hardcoded stuff. I just threw it out there since it was the only thing I could think of that has an era-based buff and hoped you'd be able to find something there. It might be done through the sql db files instead? Buildings_YieldsPerEra only specifies BUILDING_DAR_E_MEHR though.

Also, mind posting the correct file to edit to get your promotion replacement working?
 
Here's an example from my Combined Tweaks mod where I added an ability to Greek Hoplites that gives them +10 versus Infantry. Technically, I didn't need to create a whole RequirementSet for this since there is apparently already a RequirementSet to check if the Opponent is Infantry, but I didn't know that at the time.

Code:
-- Is this a melee unit we are attacking?
INSERT INTO Requirements
    (RequirementId,     RequirementType,     Likeliness,    Inverse,     Triggered)
VALUES    ('QUO_REQ_OPPONENT_MELEE',     'REQUIREMENT_OPPONENT_UNIT_PROMOTION_CLASS_MATCHES',    0,0,0) ;


INSERT INTO RequirementArguments
    (RequirementId,            Name,             Type,             Value,                 Extra,     SecondExtra)
VALUES     ('QUO_REQ_OPPONENT_MELEE',    'UnitPromotionClass',    'ARGTYPE_IDENTITY',    'PROMOTION_CLASS_MELEE',    NULL,    NULL     ) ;


INSERT INTO RequirementSets
    (RequirementSetId,     RequirementSetType)
VALUES     ('QUO_REQSET_OPPONENT_MELEE', 'REQUIREMENTSET_TEST_ALL') ;


INSERT INTO RequirementSetRequirements
    (RequirementSetId,    RequirementId)
VALUES    ('QUO_REQSET_OPPONENT_MELEE', 'QUO_REQ_OPPONENT_MELEE') ;


-- The modifier
INSERT INTO Modifiers
    (ModifierId, ModifierType, RunOnce, Permanent, OwnerRequirementSetId, SubjectRequirementSetId)
VALUES    ('QUO_MOD_ANTI_MELEE', 'MODIFIER_UNIT_ADJUST_COMBAT_STRENGTH', 0, 0, NULL, 'QUO_REQSET_OPPONENT_MELEE') ;


INSERT INTO ModifierArguments
    (ModifierId,             Name,         Type,             Value,         Extra,     SecondExtra)
VALUES    ('QUO_MOD_ANTI_MELEE',         'Amount',     'ARGTYPE_IDENTITY',     '10',        NULL,     NULL) ;


-- Create the ability
INSERT INTO Types
    (Type,                 Kind)
VALUES     ('QUO_ABI_ANTI_MELEE',        'KIND_ABILITY'    ) ;


INSERT INTO UnitAbilities
    (UnitAbilityType,     Name,                 Description,                     Inactive)
VALUES     ('QUO_ABI_ANTI_MELEE',     'QUO_LOC_ABI_ANTI_MELEE',    'QUO_LOC_ABILITY_ANTI_CAVALRY_DESCRIPTION',     0) ;


INSERT INTO UnitAbilityModifiers
    (UnitAbilityType,     ModifierId)
VALUES     ('QUO_ABI_ANTI_MELEE',    'QUO_MOD_ANTI_MELEE') ;    



-- Tie the ability to the unit
INSERT INTO TypeTags
    (Type,                    Tag)
VALUES  ('QUO_ABI_ANTI_MELEE',             'CLASS_HOPLITE') ;



-- Add a string to describe the ability in combat previews
INSERT INTO ModifierStrings
    (ModifierId,         Context, Text)
VALUES    ('QUO_MOD_ANTI_MELEE', 'Preview', 'QUO_LOC_ABILITY_ANTI_MELEE_MODIFIER_DESCRIPTION') ;


The part that may be sort of confusing is that you never tie an ability directly to a Unit but rather to a Tag that that unit is a part of. In this case, Firaxis had already created that tag, CLASS_HOPLITE, a tag that consists of a group containing only that unit. If you are trying to apply an ability to just one unit and it doesnt have a Tag already set up you'll need to insert a new one into the Tags table. Separate example of that below, showing code that would give Egyptian Maryannu Chariots the "shoot and move" ability of Cossacks:

Code:
-- Create the tag/class
INSERT INTO Tags
    (Tag,                 Vocabulary)
VALUES     ('QUO_CLASS_EGYPT_CHARIOT',    'ABILITY_CLASS'    ) ;

-- Add the egyptian chariot archer to the tag/class
INSERT INTO TypeTags
    (Type,                    Tag)
VALUES    ('UNIT_EGYPTIAN_CHARIOT_ARCHER',     'QUO_CLASS_EGYPT_CHARIOT') ;

-- Associate the ability with the tag/class so all members of the tag get the ability
INSERT INTO TypeTags
    (Type,                    Tag)
VALUES    ('ABILITY_COSSACK',             'QUO_CLASS_EGYPT_CHARIOT') ;
 
Last edited:
Oh, that makes sense. It's no wonder I couldn't find anything to work with and was stonewalling.
 
My question is, how you do you add a promotion to a unit and have that promotion remain on the unit after it has upgraded? I'm talking about adding unique promotions that are outside the normal promotion class of a unit. Say I wanted to have Hoplites start with a promotion (or equivalent) from the Warrior Monk tree, and I wanted them to retain that unique promotion even after being upgraded to Pikemen. Is that even possible?
 
Top Bottom