Scouts, Settlers and Builders Unit Abilities

Cagarustus

Prince
Joined
Mar 9, 2017
Messages
386
I want to create a cheat mod (a little one) where ONLY my Scouts, Settlers and Builders have extra movement and ignore terrain/river cost.

I assume I use the following:

MODIFIER_PLAYER_UNITS_GRANT_ABILITY
ABILITY_RELIGIOUS_IGNORE_TERRAIN_COST
MODIFIER_PLAYER_UNITS_ADJUST_MOVEMENT.

The issue is I don't know how to put all of this together. If someone could just give a brief outline as to which tables I need to fill out, then I can do the rest. For e.g. do I need Requirements, UnitAbilityModifiers.... etc.

Cheers.
 
Ok, so I had a crack at this one. I managed to give myself ONLY 99 builder charges, and it worked. I know it works because Chao's UI displays on the Unit how many charges are left. China AI had 4 charges whilst I had 97. Here is the code:

INSERT INTO Types (Type, Kind) VALUES
('TRAIT_SUPER_CIVILIAN', 'KIND_TRAIT');

INSERT INTO Traits (TraitType, Name, Description) VALUES
('TRAIT_SUPER_CIVILIAN', 'LOC_TRAIT_SUPER_CIVILIAN_NAME', 'LOC_TRAIT_SUPER_CIVILIAN_DESC');

INSERT INTO TraitModifiers (TraitType, ModifierId) VALUES
('TRAIT_SUPER_CIVILIAN', 'SUPER_BUILDCHARGES_MODIFIER'),
('TRAIT_SUPER_CIVILIAN', 'SUPER_FAST_MODIFIER'),
('TRAIT_SUPER_CIVILIAN', 'SUPER_FAST_MODIFIER_2');

INSERT INTO CivilizationTraits (CivilizationType, TraitType) VALUES
('CIVILIZATION_AMERICA', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_ARABIA', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_AUSTRALIA', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_BRAZIL', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_CHINA', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_EGYPT', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_ENGLAND', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_FRANCE', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_GERMANY', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_GREECE', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_INDIA', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_JAPAN', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_KONGO', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_MACEDON', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_NORWAY', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_PERSIA', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_POLAND', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_ROME', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_RUSSIA', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_SCYTHIA', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_SPAIN', 'TRAIT_SUPER_CIVILIAN'),
('CIVILIZATION_SUMERIA', 'TRAIT_SUPER_CIVILIAN');

INSERT INTO Modifiers (ModifierId, ModifierType,
SubjectRequirementSetId, Permanent)
VALUES
('SUPER_BUILDCHARGES_MODIFIER', 'MODIFIER_PLAYER_UNITS_ADJUST_BUILDER_CHARGES',
'PLAYER_TOBE_HUMAN', 1);

INSERT INTO ModifierArguments (ModifierId, Name, Value)
VALUES
('SUPER_BUILDCHARGES_MODIFIER', 'Amount', 95);

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

INSERT INTO RequirementSetRequirements
(RequirementSetId,
RequirementId)
VALUES ('PLAYER_TOBE_HUMAN',
'REQUIRES_PLAYER_BE_HUMAN');

INSERT INTO Requirements
(RequirementId,
RequirementType)
VALUES ('REQUIRES_PLAYER_BE_HUMAN',
'REQUIREMENT_PLAYER_IS_HUMAN');
--
However, I didn't succeed applying IGNORE_TERRAIN and IGNORE_CROSSING_RIVERS_COST at all. Here is the code:

INSERT INTO Types (Kind, Type) VALUES
('KIND_ABILITY', 'ABILITY_CIVILIAN_IGNORE_TERRAIN'),
('KIND_ABILITY', 'ABILITY_CIVILIAN_IGNORE_RIVERS');

INSERT INTO Tags (Vocabulary, Tag) VALUES
('ABILITY_CLASS', 'CLASS_IGNORE_TERRAIN'),
('ABILITY_CLASS', 'CLASS_IGNORE_RIVERS');

INSERT INTO TypeTags
(Type,
Tag)
VALUES ('ABILITY_CIVILIAN_IGNORE_TERRAIN',
'CLASS_IGNORE_TERRAIN'),
('ABILITY_CIVILIAN_IGNORE_RIVERS',
'CLASS_IGNORE_RIVERS');

INSERT INTO TypeTags (Tag, Type) VALUES
('CLASS_IGNORE_TERRAIN', 'UNIT_BUILDER'),
('CLASS_IGNORE_TERRAIN', 'UNIT_SETTLER'),
('CLASS_IGNORE_RIVERS', 'UNIT_BUILDER'),
('CLASS_IGNORE_RIVERS', 'UNIT_SETTLER');

INSERT INTO Modifiers
(ModifierId,
ModifierType,
SubjectRequirementSetId,
Permanent)
VALUES ('SUPER_FAST_MODIFIER',
'MODIFIER_PLAYER_UNIT_GRANT_ABILITY',
'PLAYER_TOBE_HUMAN', 1),
('SUPER_FAST_MODIFIER_2',
'MODIFIER_PLAYER_UNIT_GRANT_ABILITY',
'PLAYER_TOBE_HUMAN', 1);

INSERT INTO ModifierArguments
(ModifierId,
Name, Value)
VALUES ('SUPER_FAST_MODIFIER',
'AbilityType', 'ABILITY_CIVILIAN_IGNORE_TERRAIN'),
('SUPER_FAST_MODIFIER_2',
'AbilityType', 'ABILITY_CIVILIAN_IGNORE_RIVERS');

INSERT INTO UnitAbilities
(UnitAbilityType,
Name,
Description,
Inactive)
VALUES ('ABILITY_CIVILIAN_IGNORE_TERRAIN',
'LOC_ABILITY_CIVILIAN_IGNORE_TERRAIN_NAME',
'LOC_ABILITY_CIVILIAN_IGNORE_TERRAIN_DESC', 1),
('ABILITY_CIVILIAN_IGNORE_RIVERS',
'LOC_ABILITY_CIVILIAN_IGNORE_RIVERS_NAME',
'LOC_ABILITY_CIVILIAN_IGNORE_RIVERS_DESC', 1);

INSERT INTO UnitAbilityModifiers
(UnitAbilityType,
ModifierId)
VALUES ('ABILITY_CIVILIAN_IGNORE_TERRAIN',
'MOD_IGNORE_TERRAIN_COST'),
('ABILITY_CIVILIAN_IGNORE_RIVERS',
'MOD_IGNORE_CROSSING_RIVERS_COST');

The idea behind this was to use TypeTags to specifically define to which Units I wanted to apply the Ability with the Requirement that PLAYER_IS_HUMAN as worked with the BuilderCharges.

I'm not sure if I can define more than one Requirement for a single ModifierId.
--
After clearing up all the Syntax Errors, the Log Report came back as:

[500045.770] [Localization]: Validating Foreign Key Constraints...
[500045.772] [Localization]: Passed Validation.
[500045.791] [Configuration]: Validating Foreign Key Constraints...
[500045.792] [Configuration]: Passed Validation.
[500062.460] [FullTextSearch]: Initializing FullTextSearch
[500064.404] [Gameplay]: Validating Foreign Key Constraints...
[500064.420] [Gameplay]: Passed Validation.
[500065.963] [Configuration] ERROR: no such table: Types
[500065.964] [Configuration] ERROR: no such table: Types
[500066.012] [Configuration]: Validating Foreign Key Constraints...
[500066.013] [Configuration]: Passed Validation.
[500087.877] [FullTextSearch]: FTS - Creating Context
[500096.095] [Configuration] ERROR: no such table: Types
[500096.097] [Configuration] ERROR: no such table: Types
[500096.097] [Configuration]: Validating Foreign Key Constraints...
[500096.098] [Configuration]: Passed Validation.
[500098.197] [Localization] ERROR: UNIQUE constraint failed: LocalizedText.Language, LocalizedText.Tag
[500098.197] [Localization]: While executing - 'insert into BaseGameText('Tag', 'Text') values (?, ?);'
[500098.197] [Localization]: In XMLSerializer while inserting row into table insert into BaseGameText('Tag', 'Text') with values (LOC_HUD_REPORTS_TAB_CURRENT_DEALS, Current Deals, ).
[500098.197] [Localization]: In XMLSerializer while updating table BaseGameText from file ids_text.xml.
[500098.197] [Localization] ERROR: UNIQUE constraint failed: LocalizedText.Language, LocalizedText.Tag
[500098.446] [Gameplay]: Validating Foreign Key Constraints...
[500098.464] [Gameplay]: Passed Validation.
[500116.146] [FullTextSearch]: FTS - Creating Context
[500119.138] [FullTextSearch]: FTS - Creating Context
[500124.934] [FullTextSearch]: FTS - Creating Context
[500215.764] [FullTextSearch]: FullTextSearch - Shutting down

Cheers.
 
Glad to hear you worked it out. Looks great!

A few minor tips:

ATTACH TO TRAIT_LEADER_MAJOR_CIV

- instead of attaching the Modifier to every Civilization via a Trait,
- attach the Modifier to the following trait only:

INSERT INTO TraitModifiers (TraitType, ModifierId) VALUES
('TRAIT_LEADER_MAJOR_CIV', 'SUPER_BUILDCHARGES_MODIFIER');

- and make sure to use PLAYER_IS_HUMAN requirement as OWNER RequirementSetId

This way, you don't need to duplicate the trait for each civ. TRAIT_LEADER_MAJOR_CIV will give it to the leaders of all major civs, and PLAYER_IS_HUMAN will limit it only to you, human, while you are playing a specific civ.

SUBJECT vs. OWNER of MODIFIER

Now, as for the SubjectRequirementSetId vs OwnerRequirementSetId. The Modifier Type you used -- MODIFIER_PLAYER_UNITS_ADJUST_BUILDER_CHARGES -- refers to COLLECTION_PLAYER_UNITS.

So, the Subject of the Modifier is: Player Units
And, the Owner of the Modifier is: (as a result of being attached to a Trait) either Civilization or Leader Major Civ (as per my suggestion above).

As a result, PLAYER_IS_HUMAN should properly refer to the Owner of the Modifier -- you should insert it as OwnerRequirementSetId.
Any requirement that you wish to attach to Player Units would go in as SubjectRequirementSetId.

REQUIREMENTS / REQUIREMENT SETS

Generally, you can attach two Requirement Sets to each Modifier. OwnerRequirementSet attaches to the Owner - to the object that is the source of the modifier. SubjectRequirementSet attaches to the Subject - to the object being modified by the modifier.

Each Requirement Set, however, can contain multiple Requirements within. You can do this:

INSERT INTO RequirementSetRequirements (RequirementSetId, RequirementId) VALUES
('X_SET_OF_REQUIREMENTS', 'REQUIRES_X'),
('X_SET_OF_REQUIREMENTS', 'REQUIRES_X1'),
('X_SET_OF_REQUIREMENTS', 'REQUIRES_X2'),
...
('X_SET_OF_REQUIREMENTS', 'REQUIRES_X(x+1)'),

In order to mediate among all the Requirements included in a Requirement Set, you would use:

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

For RequirementSetType, you could use:

<Row Type="REQUIREMENTSET_TEST_ALL" Kind="KIND_REQUIREMENTSET"/> -- Requires all the Requirements of a Requirement Set to be met
<Row Type="REQUIREMENTSET_TEST_ANY" Kind="KIND_REQUIREMENTSET"/> -- Requires at least one of Requirements of a Requirement Set to be met, but not all.
<Row Type="REQUIREMENTSET_TEST_NONE" Kind="KIND_REQUIREMENTSET"/> -- Requires that none of the Requirements are met.

Cheers.
 
Last edited:
Ah, ok, I see you still need to work out the other two abilities. Let me look at it and I'll get back to you. Stay tuned.
 
Give this a go instead and see if it works. I avoided using/creating Abilities. Instead, I went straight to TRAIT_LEADER_MAJOR_CIV and Owner Requirement Set PLAYER_IS_HUMAN. To limit the unit types, I used a Subject Requirement Set QUALIFIED_UNIT_REQUIREMENTS, with two Requirements:

REQUIRES_UNIT_SETTLER (limits to settlers) and REQUIRES_UNIT_BUILDER (limits to builders).

The Subject Requirement Set is set to REQUIREMENTSET_TEST_ANY, so either of the Requirements would trigger it.

P.S. I've done no testing with this.

--------------------------------------------

Code:
INSERT INTO Types (Type, Kind) VALUES
('MODIFIER_SPECIFIC_UNITS_ADJUST_IGNORE_TERRAIN_COST', 'KIND_MODIFIER');

INSERT INTO DynamicModifiers (ModifierType, CollectionType, EffectType) VALUES
('MODIFIER_SPECIFIC_UNITS_ADJUST_IGNORE_TERRAIN_COST', 'COLLECTION_PLAYER_UNITS', 'EFFECT_ADJUST_UNIT_IGNORE_TERRAIN_COST');

INSERT INTO TraitModifiers (TraitType, ModifierId) VALUES
('TRAIT_LEADER_MAJOR_CIV', 'SUPER_FAST_MODIFIER1'),
('TRAIT_LEADER_MAJOR_CIV', 'SUPER_FAST_MODIFIER2'),
('TRAIT_LEADER_MAJOR_CIV', 'SUPER_FAST_MODIFIER3');

INSERT INTO Modifiers (ModifierId, ModifierType, RunOnce, Permanent, OwnerRequirementSetId, SubjectRequirementSetId) VALUES
('SUPER_FAST_MODIFIER1', 'MODIFIER_PLAYER_UNITS_ADJUST_IGNORE_RIVERS', 0, 1, 'PLAYER_IS_HUMAN', 'QUALIFIED_UNIT_REQUIREMENTS'),
('SUPER_FAST_MODIFIER2', 'MODIFIER_SPECIFIC_UNITS_ADJUST_IGNORE_TERRAIN_COST', 0, 1, 'PLAYER_IS_HUMAN', 'QUALIFIED_UNIT_REQUIREMENTS'),
('SUPER_FAST_MODIFIER3', 'MODIFIER_PLAYER_UNITS_ADJUST_MOVEMENT', 0, 1, 'PLAYER_IS_HUMAN', 'QUALIFIED_UNIT_REQUIREMENTS');

INSERT INTO ModifierArguments (ModifierId, Name, Type, Value, Extra, SecondExtra) VALUES
('SUPER_FAST_MODIFIER1', 'Ignore', 'ARGTYPE_IDENTITY', '1', NULL, NULL),
('SUPER_FAST_MODIFIER2', 'Ignore', 'ARGTYPE_IDENTITY', '1', NULL, NULL),
('SUPER_FAST_MODIFIER2', 'Type', 'ARGTYPE_IDENTITY', 'ALL', NULL, NULL),
('SUPER_FAST_MODIFIER3', 'Amount', 'ARGTYPE_IDENTITY', '2', NULL, NULL);

INSERT INTO RequirementSets (RequirementSetId, RequirementSetType) VALUES
('QUALIFIED_UNIT_REQUIREMENTS', 'REQUIREMENTSET_TEST_ANY');

INSERT INTO RequirementSetRequirements (RequirementSetId, RequirementId) VALUES
('QUALIFIED_UNIT_REQUIREMENTS', 'REQUIRES_UNIT_SETTLER'),
('QUALIFIED_UNIT_REQUIREMENTS', 'REQUIRES_UNIT_BUILDER');

INSERT INTO Requirements (RequirementId, RequirementType) VALUES
('REQUIRES_UNIT_SETTLER', 'REQUIREMENT_UNIT_TYPE_MATCHES'),
('REQUIRES_UNIT_BUILDER', 'REQUIREMENT_UNIT_TYPE_MATCHES');

INSERT INTO RequirementArguments (RequirementId, Name, Type, Value, Extra, SecondExtra) VALUES
('REQUIRES_UNIT_SETTLER', 'UnitType', 'ARGTYPE_IDENTITY', 'UNIT_SETTLER', NULL, NULL),
('REQUIRES_UNIT_BUILDER', 'UnitType', 'ARGTYPE_IDENTITY', 'UNIT_BUILDER', NULL, NULL);
 
Just one more thing, if I may trouble you. I'm trying to reduce production costs, again, only for my Units. I added the following the code above:

INSERT INTO Types (Type, Kind) VALUES
('MODIFIER_SPECIFIC_UNITS_ADJUST_IGNORE_TERRAIN_COST', 'KIND_MODIFIER'),
('MODIFIER_ALLPLAYER_UNITS_ADJUST_MAINTENANCE_DISCOUNT', 'KIND_MODIFIER'),
('MODIFIER_ALLPLAYER_UNITS_ADJUST_UNIT_PRODUCTION', 'KIND_MODIFIER');

INSERT INTO DynamicModifiers (ModifierType, CollectionType, EffectType) VALUES
('MODIFIER_SPECIFIC_UNITS_ADJUST_IGNORE_TERRAIN_COST', 'COLLECTION_PLAYER_UNITS', 'EFFECT_ADJUST_UNIT_IGNORE_TERRAIN_COST'),
('MODIFIER_ALLPLAYER_UNITS_ADJUST_MAINTENANCE_DISCOUNT', 'COLLECTION_PLAYER_UNITS', 'EFFECT_ADJUST_UNIT_MAINTENANCE_DISCOUNT'),
('MODIFIER_ALLPLAYER_UNITS_ADJUST_UNIT_PRODUCTION', 'COLLECTION_PLAYER_UNITS', 'EFFECT_ADJUST_UNIT_PRODUCTION');

INSERT INTO TraitModifiers (TraitType, ModifierId) VALUES
('TRAIT_LEADER_MAJOR_CIV', 'SUPER_FAST_MODIFIER1'),
('TRAIT_LEADER_MAJOR_CIV', 'SUPER_FAST_MODIFIER2'),
('TRAIT_LEADER_MAJOR_CIV', 'SUPER_FAST_MODIFIER3'),
('TRAIT_LEADER_MAJOR_CIV', 'SUPER_PRODUCTION_MODIFIER'),
('TRAIT_LEADER_MAJOR_CIV', 'SUPER_MAINTENANCE_DISCOUNT_MODIFIER');

INSERT INTO Modifiers (ModifierId, ModifierType, RunOnce, Permanent, OwnerRequirementSetId, SubjectRequirementSetId) VALUES
('SUPER_FAST_MODIFIER1', 'MODIFIER_PLAYER_UNITS_ADJUST_IGNORE_RIVERS', 0, 1, 'PLAYER_IS_HUMAN', 'QUALIFIED_UNIT_REQUIREMENTS'),
('SUPER_FAST_MODIFIER2', 'MODIFIER_SPECIFIC_UNITS_ADJUST_IGNORE_TERRAIN_COST', 0, 1, 'PLAYER_IS_HUMAN', 'QUALIFIED_UNIT_REQUIREMENTS'),
('SUPER_FAST_MODIFIER3', 'MODIFIER_PLAYER_UNITS_ADJUST_MOVEMENT', 0, 1, 'PLAYER_IS_HUMAN', 'QUALIFIED_UNIT_REQUIREMENTS'),
('SUPER_PRODUCTION_MODIFIER', 'MODIFIER_ALLPLAYER_UNITS_ADJUST_UNIT_PRODUCTION', 0, 1, 'PLAYER_IS_HUMAN', NULL),
('SUPER_MAINTENANCE_DISCOUNT_MODIFIER', 'MODIFIER_ALLPLAYER_UNITS_ADJUST_MAINTENANCE_DISCOUNT', 0, 1, 'PLAYER_IS_HUMAN', NULL);
--
It doesn't seem to be working. I tried just 'MODIFIER_PLAYER_UNITS_ADJUST_UNIT_PRODUCTION' as the ModifierType but that didn't work. I then checked the CollectionType and it was 'COLLECTION_OWNER', that's why I created a new DynamicModifier. I also tried using 'MODIFIER_PLAYER_CITIES_ADJUST_UNIT_PRODUCTION' but I think that applies to all cities producing ONE unit, not all the units.

So, I'm not sure how the aforementioned. Do I create 2 CollectionTypes? COLLECTION_PLAYER_CITIES and COLLECTION_PLAYER_UNITS?
 
Whoops, forget to include those. Here they are:

INSERT INTO ModifierArguments (ModifierId, Name, Type, Value, Extra, SecondExtra) VALUES
('SUPER_FAST_MODIFIER1', 'Ignore', 'ARGTYPE_IDENTITY', '1', NULL, NULL),
('SUPER_FAST_MODIFIER2', 'Ignore', 'ARGTYPE_IDENTITY', '1', NULL, NULL),
('SUPER_FAST_MODIFIER2', 'Type', 'ARGTYPE_IDENTITY', 'ALL', NULL, NULL),
('SUPER_FAST_MODIFIER3', 'Amount', 'ARGTYPE_IDENTITY', '20', NULL, NULL),
('SUPER_PRODUCTION_MODIFIER', 'Amount', 'ARGTYPE_IDENTITY', '100', NULL, NULL),
('SUPER_MAINTENANCE_DISCOUNT_MODIFIER', 'Amount', 'ARGTYPE_IDENTITY', '50', NULL, NULL);
 
Back
Top Bottom