Grant two or more levels for units other than Apostles

Luke Vo

Chieftain
Joined
Apr 29, 2019
Messages
59
Currently there is only EFFECT_ADJUST_CITY_RELIGION_EXTRA_PROMOTIONS GameEffect that can grant stacking level (2 promotions). I created this code to make Non-state Actors to grant Spies two extra level (and Catherine 3) instead. Hope it helps.

UI Context (because I needed to check the unit's level):

Code:
spyPromotingUnits = {};

function GetUnit(playerId, unitId)
    return Players[playerId]:GetUnits():FindID(unitId);
end

function SPT_CheckSpyPromotion(playerId, unitId)
    local playerList = spyPromotingUnits[playerId];
    if (not playerList or not playerList[unitId]) then
        return;
    end
    
    local unit = Players[playerId]:GetUnits():FindID(unitId);
    local level = unit:GetExperience():GetLevel();
    
    local expectedLevel = 3;
    if (playerList["addOneMore"]) then
        expectedLevel = expectedLevel + 1;
    end
    
    if (level < expectedLevel) then
        latestUnit = unit;
    
        local nextXP = unit:GetExperience():GetExperienceForNextLevel();
        ExposedMembers.SPT_GrantPromotion(playerId, unitId, nextXP + 1);
    else
        spyPromotingUnits[playerId][unitId] = nil;
    end
end

function SPT_CheckSpiesPromotion(playerId)
    local units = Players[playerId]:GetUnits();
    
    for k, unit in units:Members() do
        SPT_CheckSpyPromotion(playerId, unit:GetID());
    end
end

function SPT_UnitCreated(playerId, unitId)
    -- Get the unit & its info
    local player = Players[playerId];
    local unit = player:GetUnits():FindID(unitId);
    local unitType = GameInfo.Units[unit:GetType()];
    
    if (unitType.UnitType == "UNIT_SPY") then
        -- Check if they have the modifier
        local modifiers = GameEffects.GetModifiers();
        for k, v in pairs(modifiers) do
            local definition = GameEffects.GetModifierDefinition(v);
            if (definition.Id == "FUTURE_COUNTER_SCIENCE_SPY_GRANT_TWO_PROMOTIONS") then
                local owner = GameEffects.GetModifierOwner(v);
                local owningPlayerId = GameEffects.GetObjectsPlayerId(owner);
                
                if (owningPlayerId == playerId) then
                    -- Add the unit to the management list
                    local playerList = spyPromotingUnits[playerId];
                    
                    if (not playerList) then
                        playerList = {};
                        spyPromotingUnits[playerId] = playerList;
                        
                        -- Check if player is having Catherine's trait
                        local traits = getPlayerTraits(playerId);
                        if (traits["FLYING_SQUADRON_TRAIT"]) then
                            playerList["addOneMore"] = true;
                        end
                    end
                    
                    spyPromotingUnits[playerId][unitId] = true;
                    SPT_CheckSpyPromotion(playerId, unitId);
                    
                    break;
                end
            end
        end
    end
end

function getPlayerTraits(playerId: number)
    local result = {};
    local playerConfig = PlayerConfigurations[playerId];
    
    -- Civ Trait
    local playerCiv = playerConfig:GetCivilizationTypeName();
    for row in GameInfo.CivilizationTraits() do
        if (row.CivilizationType == playerCiv) then
            result[row.TraitType] = true;
        end
    end
    
    -- Leader Trait
    local playerLeader = playerConfig:GetLeaderTypeName();
    for row in GameInfo.LeaderTraits() do
        if (row.LeaderType == playerLeader) then
            result[row.TraitType] = true;
        end
    end
    
    return result;
end

Events.UnitAddedToMap.Add(SPT_UnitCreated);
Events.PlayerTurnActivated.Add(SPT_CheckSpiesPromotion)

Gameplay Script context, because ChangeExperience is only available there:

Code:
function GetUnit(playerId, unitId)
    return Players[playerId]:GetUnits():FindID(unitId);
end

function GrantPromotion(playerId, unitId, experience)
    local unit = GetUnit(playerId, unitId);
    unit:GetExperience():ChangeExperience(experience);
end

ExposedMembers.SPT_GrantPromotion = GrantPromotion;

The `FUTURE_COUNTER_SCIENCE_SPY_GRANT_TWO_PROMOTIONS` modifier is my own modifier created for checking purpose. It does not have any Effect on its own. Here is the code for creating that modifier:

Code:
-- Fake feature (+0% XP), LUA script will take care of it
INSERT INTO Modifiers(ModifierId, ModifierType) VALUES
    ('FUTURE_COUNTER_SCIENCE_SPY_GRANT_TWO_PROMOTIONS', 'MODIFIER_PLAYER_UNITS_ADJUST_UNIT_EXPERIENCE_MODIFIER');
INSERT INTO ModifierArguments(ModifierId, Name, Type, Value) VALUES
    ('FUTURE_COUNTER_SCIENCE_SPY_GRANT_TWO_PROMOTIONS', 'Amount', 'ARGTYPE_IDENTITY', 0);
INSERT INTO PolicyModifiers(PolicyType, ModifierId) VALUES
    ('POLICY_FUTURE_COUNTER_SCIENCE', 'FUTURE_COUNTER_SCIENCE_SPY_GRANT_TWO_PROMOTIONS');

I do see it's really ugly and spaghetti. I hope someone can point out a better solution. Thanks @Zur13 for helping me create this.
 
Back
Top Bottom