How to prevent AI from building a specific unit type

TC_

Chieftain
Joined
Jul 8, 2017
Messages
77
I am making a new unit with functionality that the AI will not understand. How can I ensure that the AI will not create them? Will simply leaving UnitAiInfos blank suffice?

Thanks in advance
 
Anyone know a simple solution for this? The only thing I know of right now is to place a dummy building in human player cities and set it as a prereq for producing the unit, but I'd rather not have to flesh out the lua for that.
 
If you dive into the Operations, Leaders, and behavior tree files, you will see that the AI creates every unit for a reason. Usually for various operations or pseudo yields. The easiest way to prevent them from making it would be to make it part of a new unit promotion class that the AI doesn't even know about. So as long as you don't specify that it should be included in an operation, then it wont be built. Out of curiosity, what unit are you making?
 
Cool thank you for the reply chillbaka. I considered the new promotion class, but was afraid of any unwanted consequences. I went ahead and made a dummy building which is automatically built in human player cities, which allows for the creation of the unit. Your route might have been more elegant, and simpler, but I got the building and lua functionality fleshed out in about 45 mins so it wasn't too bad.

The unit is used to transfer population from one city to another. It reduces the population of the city it is produced in, and once you move it to another city that you own it is removed from the game and that city's pop is increased by 1.
 
Last edited:
Cool thank you for the reply chillbaka. I considered the new promotion class, but was afraid of any unwanted consequences. I went ahead and made a dummy building which is automatically built in human player cities, which allows for the creation of the unit. Your route might have been more elegant, and simpler, but I got the building and lua functionality fleshed out in about 45 mins so it wasn't too bad.

The unit is used to transfer population from one city to another. It reduces the population of the city it is produced in, and once you move it to another city that you own it is removed from the game and that city's pop is increased by 1.

That's actually a really interesting idea. I've been working on a Julius Caesar mod where instead of the regular legion unique unit, he gets the "Legionary First Cohort" unit which has various different advantages (cross rivers, acts as a battering ram, ect.) and is pretty much over powered but the only thing is that it costs 1 population to make. Can you share your code for how you were able to accomplish this? Im stuck.
 
PopulationCost="1"

Just that one declaration when you set up your unit is all it takes =).
 
Oh I thought you wanted to know how to make your unit cost the 1 pop. Ill post the script that i use to transfer the pop when I get back to my pc
 
Code:
local iCitizen = GameInfo.Units["UNIT_CITIZEN"].Index;

function OnUnitMoveComplete(iPlayer, iunitID, iPlotX, iPlotY)

    local pPlayer = Players[iPlayer];
    local pPlayerUnits = pPlayer:GetUnits();
    local pUnit = pPlayerUnits:FindID(iunitID);

    if (pUnit:GetType() == iCitizen) then
        
        local plot = Map.GetPlot(iPlotX, iPlotY);
        local isCity = plot:IsCity();
        
        if (isCity) then
        
            local iPlotOwner = plot:GetOwner();

            if (iPlotOwner == iPlayer) then
            
            --destroys unit
            pPlayerUnits:Destroy(pUnit);

            --increase city population by 1
            local pCity         :table  = Cities.GetCityInPlot(iPlotX,iPlotY);
            pCity:ChangePopulation(1);

            end
        end
    end   
end

Events.UnitMoveComplete.Add(OnUnitMoveComplete);

What it does: When a player moves a citizen unit to a city tile owned by that player, it will remove that unit from the game and increase the population of that city by 1.
 
Code:
local iCitizen = GameInfo.Units["UNIT_CITIZEN"].Index;

function OnUnitMoveComplete(iPlayer, iunitID, iPlotX, iPlotY)

    local pPlayer = Players[iPlayer];
    local pPlayerUnits = pPlayer:GetUnits();
    local pUnit = pPlayerUnits:FindID(iunitID);

    if (pUnit:GetType() == iCitizen) then
       
        local plot = Map.GetPlot(iPlotX, iPlotY);
        local isCity = plot:IsCity();
       
        if (isCity) then
       
            local iPlotOwner = plot:GetOwner();

            if (iPlotOwner == iPlayer) then
           
            --destroys unit
            pPlayerUnits:Destroy(pUnit);

            --increase city population by 1
            local pCity         :table  = Cities.GetCityInPlot(iPlotX,iPlotY);
            pCity:ChangePopulation(1);

            end
        end
    end  
end

Events.UnitMoveComplete.Add(OnUnitMoveComplete);

What it does: When a player moves a citizen unit to a city tile owned by that player, it will remove that unit from the game and increase the population of that city by 1.

Where did you write this code? It looks similar to c++ which im more comfortable with, but ive only been going through the xml files and using xml/sql. If i could do stuff like this that would be great.
 
Its just a document like .xml or .sql, but with the .lua extension. Id suggest just downloading any lua mod and digging around in it. My "strategic forts" mod on steam is primarily lua, feel free to use it as a learning tool
 
Its just a document like .xml or .sql, but with the .lua extension. Id suggest just downloading any lua mod and digging around in it. My "strategic forts" mod on steam is primarily lua, feel free to use it as a learning tool

Awesome, thanks so much. I always just thought that the lua stuff was for UI/visual/map stuff. I'm downloading your mod now to take a look.
 
In Rise and Fall there is a Modifier that allows you to block the building of a particular unit entirely. Here's an example where one of the "Biomes" in my Combined Tweaks mod is blocked from building Support units:

Code:
CREATE TABLE tblQuoBiomeEastEuropeSupportUnits AS
select unittype, technologies.eratype from units
inner join technologies on technologies.TechnologyType = units.PrereqTech
where promotionclass in  ("PROMOTION_CLASS_SUPPORT") AND TraitType IS NULL

union

select unittype, civics.EraType from units
inner join civics on civics.CivicType = units.PrereqCivic
where promotionclass in  ("PROMOTION_CLASS_SUPPORT") AND TraitType IS NULL;


INSERT INTO Modifiers
    (ModifierId, ModifierType, RunOnce, Permanent, OwnerRequirementSetId, SubjectRequirementSetId)
SELECT 'QUO_BIOME_EAST_EUROPE_CANNOT_BUILD_' || tblQuoBiomeEastEuropeSupportUnits.UnitType, 'MODIFIER_PLAYER_UNIT_BUILD_DISABLED', 0, 0, NULL, NULL
    FROM tblQuoBiomeEastEuropeSupportUnits;


INSERT INTO ModifierArguments
    (ModifierId,             Name,         Type,             Value,             Extra,     SecondExtra)
SELECT 'QUO_BIOME_EAST_EUROPE_CANNOT_BUILD_' || tblQuoBiomeEastEuropeSupportUnits.UnitType,     'UnitType',     'ARGTYPE_IDENTITY',     tblQuoBiomeEastEuropeSupportUnits.UnitType,            NULL,     NULL
    FROM tblQuoBiomeEastEuropeSupportUnits;

    
INSERT INTO TraitModifiers
    (TraitType,             ModifierID)
SELECT 'QUO_TRAIT_BIOME_EAST_EUROPE',    'QUO_BIOME_EAST_EUROPE_CANNOT_BUILD_' || tblQuoBiomeEastEuropeSupportUnits.UnitType
    FROM tblQuoBiomeEastEuropeSupportUnits;


This code does a few things:

- Creates a table containing a list of all units to affect (tblQuoBiomeEastEuropeSupportUnits). In this case, it's any unit that is a Support Unit. (Note that this code also contains joins to eras, so if we wanted to block all units of a certain era we could do that).

- Use the data in the temporary table created in the step above to creates a 'MODIFIER_PLAYER_UNIT_BUILD_DISABLED Modifier for each unit listed in that table, with an appropriate ModifierArgument.

- Applies these Modifiers to the Trait.


If you want to block the AI from ever building a particular unit, just use code similar to above (with your own custom table name) and populate that table with whatever units you want to block out. Then make sure on the Modifier that you have attach a RequirementSet that checks to see that the player is AI. You can use whatever means to populate your table that you want (e.g. you could directly INSERT into your temporary table, or you could do a SELECT query like the example above to pick out records based on a certain characteristic, e.g. EraType, PromotionClass, etc.
 
In Rise and Fall there is a Modifier that allows you to block the building of a particular unit entirely. Here's an example where one of the "Biomes" in my Combined Tweaks mod is blocked from building Support units:

Code:
CREATE TABLE tblQuoBiomeEastEuropeSupportUnits AS
select unittype, technologies.eratype from units
inner join technologies on technologies.TechnologyType = units.PrereqTech
where promotionclass in  ("PROMOTION_CLASS_SUPPORT") AND TraitType IS NULL

union

select unittype, civics.EraType from units
inner join civics on civics.CivicType = units.PrereqCivic
where promotionclass in  ("PROMOTION_CLASS_SUPPORT") AND TraitType IS NULL;


INSERT INTO Modifiers
    (ModifierId, ModifierType, RunOnce, Permanent, OwnerRequirementSetId, SubjectRequirementSetId)
SELECT 'QUO_BIOME_EAST_EUROPE_CANNOT_BUILD_' || tblQuoBiomeEastEuropeSupportUnits.UnitType, 'MODIFIER_PLAYER_UNIT_BUILD_DISABLED', 0, 0, NULL, NULL
    FROM tblQuoBiomeEastEuropeSupportUnits;


INSERT INTO ModifierArguments
    (ModifierId,             Name,         Type,             Value,             Extra,     SecondExtra)
SELECT 'QUO_BIOME_EAST_EUROPE_CANNOT_BUILD_' || tblQuoBiomeEastEuropeSupportUnits.UnitType,     'UnitType',     'ARGTYPE_IDENTITY',     tblQuoBiomeEastEuropeSupportUnits.UnitType,            NULL,     NULL
    FROM tblQuoBiomeEastEuropeSupportUnits;

   
INSERT INTO TraitModifiers
    (TraitType,             ModifierID)
SELECT 'QUO_TRAIT_BIOME_EAST_EUROPE',    'QUO_BIOME_EAST_EUROPE_CANNOT_BUILD_' || tblQuoBiomeEastEuropeSupportUnits.UnitType
    FROM tblQuoBiomeEastEuropeSupportUnits;


This code does a few things:

- Creates a table containing a list of all units to affect (tblQuoBiomeEastEuropeSupportUnits). In this case, it's any unit that is a Support Unit. (Note that this code also contains joins to eras, so if we wanted to block all units of a certain era we could do that).

- Use the data in the temporary table created in the step above to creates a 'MODIFIER_PLAYER_UNIT_BUILD_DISABLED Modifier for each unit listed in that table, with an appropriate ModifierArgument.

- Applies these Modifiers to the Trait.


If you want to block the AI from ever building a particular unit, just use code similar to above (with your own custom table name) and populate that table with whatever units you want to block out. Then make sure on the Modifier that you have attach a RequirementSet that checks to see that the player is AI. You can use whatever means to populate your table that you want (e.g. you could directly INSERT into your temporary table, or you could do a SELECT query like the example above to pick out records based on a certain characteristic, e.g. EraType, PromotionClass, etc.

Do you think you might be able to help with a problem im stuck on? So I am making a Julius Caesar leader mod and his unique unit is the "Legionary First Cohort" and it has a bunch of buffs, but costs 1 pop to make. Two of the abilities I am trying to implement is "Form Testudo" and "Throw Pilums".

Form Testudo: I am trying to make this a new unit action (eg. spread religion, range attack, use great person ability) that reduces the movement points to 1, but provides +20 strength when defending against range attacks. I am able to figure out most of the modifier stuff but I am having trouble with creating the button. Any Ideas?

Throw Pilums: This is another unit action that allows you to perform a range attack (range of 1) that does not cost any movement points, which allows you to do a follow up melee attack. I have been trying to mimic the immortals code but with no luck.

Any help is greatly appreciated.
 
Back
Top Bottom