[Help]LUA:Give promotion to ARCHER unit according to the Belligerents number

Shaqulli

Chieftain
Joined
Jul 14, 2017
Messages
16
I'm making a Unique Trait through a lua file.I made a function for my new civilization(CIVILIZATION_QIN).The function should have given the ARCHER unit of CIVILIZATION_QIN some certain promotions(I have defined them) according to the number of Major Civs that it is at war with.
But the function doesn't work:confused:.The record in lua.log makeme uneasy.BUt I don't what to do
Code:
MODS\WarStatesOfChina (v 2)\lua/QINTrait.lua:24: attempt to call method 'IsAtWar' (a nil value
.
I have done "InGameUIAddin".
I guess my code is wrong.
Code:
function QINTrait(playerID)

local player = Players[playerID]
local iNumWithWar = 0
local ANTIUNITEDID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_D"].ID
local ANTIUNITECID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_C"].ID
local ANTIUNITEAID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_A"].ID
local ANTIUNITESID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_S"].ID


---------------------Run only when Qin player do turn-----------------------

if not player or not player:IsAlive() or player:GetCivilizationType()~=GameInfoTypes.CIVILIZATION_QIN then
    return
end


------------------Find out the number of enemy of QIN---------------

for _,targetplayer in pairs(Players) do
    if targetplayer and targetplayer:IsAlive() and not targetplayer:IsBarbarian() and targetplayer:IsAtWar(player) then
        iNumWithWar = iNumWithWar + 1
    end
end


-----------------Give the Archer corresponding promotion according to the QIN's enemy number-------------------
    --[[ nothing for 1 enemy
        "PROMOTION_ANTI_UNITE_1" for 2 enemy;
        "PROMOTION_ANTI_UNITE_2" for 3 enemy;
        "PROMOTION_ANTI_UNITE_3" for 4 enemy;
        "PROMOTION_ANTI_UNITE_4" for 5 or more enemy]]
    if (iNumWithWar == 1 or iNumWithWar == 0 ) then
        return
    --[[if the number of enemy of QIN is 2,ARCHER will get PROMOTION_ANTI_UNITE_1]]
    elseif (iNumWithWar == 2) then
        for unit in QINplayer:Units() do
            if unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARCHER then
                if not unit:IsHasPromotion(ANTIUNITEDID) then
                unit:SetHasPromotion(ANTIUNITEDID,true)
                end
                if unit:IsHasPromotion(ANTIUNITEAID) then
                unit:SetHasPromotion(ANTIUNITEAID,false)
                end
                if unit:IsHasPromotion(ANTIUNITECID) then
                unit:SetHasPromotion(ANTIUNITECID,false)
                end
                if unit:IsHasPromotion(ANTIUNITESID) then
                unit:SetHasPromotion(ANTIUNITEDID,false)
                end
            end
        end   
    return
    
    --[[if the number of enemy of QIN is 3,ARCHER will get PROMOTION_ANTI_UNITE_2]]
    elseif iNumWithWar == 3 then
        for unit in QINplayer:Units() do
            if unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARCHER then
                if not unit:IsHasPromotion(ANTIUNITECID) then
                unit:SetHasPromotion(ANTIUNITECID,true)
                end
                if unit:IsHasPromotion(ANTIUNITEAID) then
                unit:SetHasPromotion(ANTIUNITEAID,false)
                end
                if unit:IsHasPromotion(ANTIUNITESID) then
                unit:SetHasPromotion(ANTIUNITECID,false)
                end
                if unit:IsHasPromotion(ANTIUNITEDID) then
                unit:SetHasPromotion(ANTIUNITEDID,false)
                end
            end
        end   
    return
    --[[if the number of enemy of QIN is 4,ARCHER will get PROMOTION_ANTI_UNITE_3]]
    elseif iNumWithWar == 4 then
        for unit in QINplayer:Units() do
            if unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARCHER then
                if not unit:IsHasPromotion(ANTIUNITEAID) then
                unit:SetHasPromotion(ANTIUNITEAID,true)
                end
                if unit:IsHasPromotion(ANTIUNITESID) then
                unit:SetHasPromotion(ANTIUNITEAID,false)
                end
                if unit:IsHasPromotion(ANTIUNITECID) then
                unit:SetHasPromotion(ANTIUNITECID,false)
                end
                if unit:IsHasPromotion(ANTIUNITEDID) then
                unit:SetHasPromotion(ANTIUNITEDID,false)
                end
            end
        end   
    return
    --[[if the number of enemy of QIN is up to 5,ARCHER will get PROMOTION_ANTI_UNITE_4]]
    elseif iNumWithWar == 5 or iNumWithWar > 5 then
        for unit in QINplayer:Units() do
            if unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARCHER then
                if not unit:IsHasPromotion(ANTIUNITESID) then
                unit:SetHasPromotion(ANTIUNITESID,true)
                end
                if unit:IsHasPromotion(ANTIUNITEAID) then
                unit:SetHasPromotion(ANTIUNITEAID,false)
                end
                if unit:IsHasPromotion(ANTIUNITECID) then
                unit:SetHasPromotion(ANTIUNITECID,false)
                end
                if unit:IsHasPromotion(ANTIUNITEDID) then
                unit:SetHasPromotion(ANTIUNITEDID,false)
                end
            end
        end
    end
end

GameEvents.PlayerDoTurn.Add(QINTrait)
 

Attachments

  • QQ截图20170715100704.png
    QQ截图20170715100704.png
    24.5 KB · Views: 167
I hope someone can point out my mistakes and give me some advice,That's very grateful of you.
 
There is no function :IsAtWar for player objects (outside of modded DLLs), so that's why you get 'a nil value'.
Wars (and peace for that matter) are shared across teams. In standard civ games, each team consists of only one player however.
You could use pTeam:IsAtWar(iAnotherTeam) instead, but a way easier way to get the number of wars currently in is to use pTeam:GetAtWarCount(bIgnoreMinors). I don't know if Barbarians are also counted, so that's something you'd have to test yourself.

---

You will also get another error upon fixing your first, and that is that 'QINplayer' will be 'a nil value'. At the start of each unit-iterator block, you use that variable but have never defined it before. Use 'player' instead (as that's how you defined it at the top of the code)

You can also move
Code:
local ANTIUNITEDID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_D"].ID
local ANTIUNITECID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_C"].ID
local ANTIUNITEAID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_A"].ID
local ANTIUNITESID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_S"].ID
outside of your function, as these variables will not change throughout the game. (You could also use 'local ANTIUNITEDID = GameInfoTypes.PROMOTION_ANTI_UNITE_D' instead, which is just shorter to write down)

--
There's also a logical error, and that is that you will grant all archer combat units, so Composite Bowmen and Crossbowmen, the promotions as well. You check for the COMBATclass, and should instead be checking for the UNITclass (or UnitType, but I suggest you use the UnitClass).

--
Lastly, you do not remove the archer promotions when you are at war with one or less players. While that does seem correct in the first place, you will get 'unexpected' bonuses if you are at war with multiple players, and then peace out with them as it doesn't remove the promotions in that case.
 
There is no function :IsAtWar for player objects (outside of modded DLLs), so that's why you get 'a nil value'.
Wars (and peace for that matter) are shared across teams. In standard civ games, each team consists of only one player however.
You could use pTeam:IsAtWar(iAnotherTeam) instead, but a way easier way to get the number of wars currently in is to use pTeam:GetAtWarCount(bIgnoreMinors). I don't know if Barbarians are also counted, so that's something you'd have to test yourself.

---

You will also get another error upon fixing your first, and that is that 'QINplayer' will be 'a nil value'. At the start of each unit-iterator block, you use that variable but have never defined it before. Use 'player' instead (as that's how you defined it at the top of the code)

You can also move
Code:
local ANTIUNITEDID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_D"].ID
local ANTIUNITECID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_C"].ID
local ANTIUNITEAID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_A"].ID
local ANTIUNITESID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_S"].ID
outside of your function, as these variables will not change throughout the game. (You could also use 'local ANTIUNITEDID = GameInfoTypes.PROMOTION_ANTI_UNITE_D' instead, which is just shorter to write down)

--
There's also a logical error, and that is that you will grant all archer combat units, so Composite Bowmen and Crossbowmen, the promotions as well. You check for the COMBATclass, and should instead be checking for the UNITclass (or UnitType, but I suggest you use the UnitClass).

--
Lastly, you do not remove the archer promotions when you are at war with one or less players. While that does seem correct in the first place, you will get 'unexpected' bonuses if you are at war with multiple players, and then peace out with them as it doesn't remove the promotions in that case.
Thank you very much!Your reply exactly resolves my problems!
The
Code:
------------------Find out the number of enemy of QIN---------------

for _,targetplayer in pairs(Players) do
    if targetplayer and targetplayer:IsAlive() and not targetplayer:IsBarbarian() and targetplayer:IsAtWar(player) then
        iNumWithWar = iNumWithWar + 1
    end
end
is converted to
Code:
------------------Find out the number of enemy of QIN---------------
local pteam = Teams[player:GetTeam()]
local iNumWithWar = pteam:GetAtWarCount(true)
Now it seems work coorectly.And I make the function check and remove the promotions when "iNumWithWar'' is less than 2.
It's very nice of you,circumspect and helpful.
 
Oh,I find that my code works not so coorectly
Code:
function AntiUnite(playerID)

local player = Players[playerID]
local ANTIUNITEDID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_D"].ID
local ANTIUNITECID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_C"].ID
local ANTIUNITEAID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_A"].ID
local ANTIUNITESID = GameInfo.UnitPromotions["PROMOTION_ANTI_UNITE_S"].ID
---------------------Run only when Qin player do turn-----------------------

if not player or not player:IsEverAlive() or player:GetCivilizationType()~=GameInfoTypes.CIVILIZATION_QIN then
   return
end
------------------Find out the number of enemy of QIN---------------
local pteam = Teams[player:GetTeam()]
local iNumWithWar = pteam:GetAtWarCount(true)

-----------------Give the Archer corresponding promotion according to the QIN's enemy number-------------------
   --[[ nothing for 1 enemy
       "PROMOTION_ANTI_UNITE_D" for 2 enemy;
       "PROMOTION_ANTI_UNITE_C" for 3 enemy;
       "PROMOTION_ANTI_UNITE_A" for 4 enemy;
       "PROMOTION_ANTI_UNITE_S" for 5 or more enemy]]
   if (iNumWithWar < 2 ) then
       for unit in player:Units() do
           if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARCHER) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_SIEGE) then
               if unit:IsHasPromotion(ANTIUNITEDID) then
               unit:SetHasPromotion(ANTIUNITEDID,false)
               end
               if unit:IsHasPromotion(ANTIUNITEAID) then
               unit:SetHasPromotion(ANTIUNITEAID,false)
               end
               if unit:IsHasPromotion(ANTIUNITECID) then
               unit:SetHasPromotion(ANTIUNITECID,false)
               end
               if unit:IsHasPromotion(ANTIUNITESID) then
               unit:SetHasPromotion(ANTIUNITEDID,false)
               end
           end
       end   
   return
   --[[if the number of enemy of QIN is 2,ARCHER will get PROMOTION_ANTI_UNITE_D]]
   elseif (iNumWithWar == 2) then
       for unit in player:Units() do
           if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARCHER) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_SIEGE) then
               if not unit:IsHasPromotion(ANTIUNITEDID) then
               unit:SetHasPromotion(ANTIUNITEDID,true)
               end
               if unit:IsHasPromotion(ANTIUNITEAID) then
               unit:SetHasPromotion(ANTIUNITEAID,false)
               end
               if unit:IsHasPromotion(ANTIUNITECID) then
               unit:SetHasPromotion(ANTIUNITECID,false)
               end
               if unit:IsHasPromotion(ANTIUNITESID) then
               unit:SetHasPromotion(ANTIUNITEDID,false)
               end
           end
       end   
   return
   
   --[[if the number of enemy of QIN is 3,ARCHER will get PROMOTION_ANTI_UNITE_C]]
   elseif iNumWithWar == 3 then
       for unit in player:Units() do
           if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARCHER) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_SIEGE) then
               if not unit:IsHasPromotion(ANTIUNITECID) then
               unit:SetHasPromotion(ANTIUNITECID,true)
               end
               if unit:IsHasPromotion(ANTIUNITEAID) then
               unit:SetHasPromotion(ANTIUNITEAID,false)
               end
               if unit:IsHasPromotion(ANTIUNITESID) then
               unit:SetHasPromotion(ANTIUNITECID,false)
               end
               if unit:IsHasPromotion(ANTIUNITEDID) then
               unit:SetHasPromotion(ANTIUNITEDID,false)
               end
           end
       end   
   return
   --[[if the number of enemy of QIN is 4,ARCHER will get PROMOTION_ANTI_UNITE_A]]
   elseif iNumWithWar == 4 then
       for unit in player:Units() do
           if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARCHER) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_SIEGE) then
               if not unit:IsHasPromotion(ANTIUNITEAID) then
               unit:SetHasPromotion(ANTIUNITEAID,true)
               end
               if unit:IsHasPromotion(ANTIUNITESID) then
               unit:SetHasPromotion(ANTIUNITEAID,false)
               end
               if unit:IsHasPromotion(ANTIUNITECID) then
               unit:SetHasPromotion(ANTIUNITECID,false)
               end
               if unit:IsHasPromotion(ANTIUNITEDID) then
               unit:SetHasPromotion(ANTIUNITEDID,false)
               end
           end
       end   
   return
   --[[if the number of enemy of QIN is up to 5,ARCHER will get PROMOTION_ANTI_UNITE_S]]
   elseif iNumWithWar == 5 or iNumWithWar > 5 then
       for unit in player:Units() do
           if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARCHER) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_SIEGE) then
               if not unit:IsHasPromotion(ANTIUNITESID) then
               unit:SetHasPromotion(ANTIUNITESID,true)
               end
               if unit:IsHasPromotion(ANTIUNITEAID) then
               unit:SetHasPromotion(ANTIUNITEAID,false)
               end
               if unit:IsHasPromotion(ANTIUNITECID) then
               unit:SetHasPromotion(ANTIUNITECID,false)
               end
               if unit:IsHasPromotion(ANTIUNITEDID) then
               unit:SetHasPromotion(ANTIUNITEDID,false)
               end
           end
       end
   end
end

GameEvents.PlayerDoTurn.Add(AntiUnite)
-------I want to give the promotion to the ''Unitcombat_ARCHER'' and ''Unitcombat_SIEGE'' units.It works right.

--------I need to remove the promotions when '' iNumWithWar'' decrease.
But my ''SetHasPromotion(PromotionID,false)" failed. When at peace,they still have the promotion.
How can I remove the promotion?
 
I'm pretty sure that's because you made a typo
if unit:IsHasPromotion(ANTIUNITESID) then
unit:SetHasPromotion(ANTIUNITEDID,false)
end

EDIT: There seem to be several instances of these variables not matching, though at this point I don't know if that's intentional or not.
 
I'm pretty sure that's because you made a typo
EDIT: There seem to be several instances of these variables not matching, though at this point I don't know if that's intentional or not.
Thanks a lot.I will correct it.
 
I'm pretty sure that's because you made a typo


EDIT: There seem to be several instances of these variables not matching, though at this point I don't know if that's intentional or not.
I have met another problem.
What causes this situation?

Code:
[562488.046] Runtime Error: Assets\DLC\Expansion2\UI\InGame\InGame.lua:1262: attempt to index local 'addinFile' (a nil value)
[562488.046] Runtime Error: Error loading Assets\DLC\Expansion2\UI\InGame\InGame.lua.
Is the code not OK?
Code:
function AttackDeBuff(attPlayerID,
        attUnitID,
        attUnitDamage,
        attFinalUnitDamage,
        attMaxHitPoints,
        defPlayerID,
        defUnitID,
        defUnitDamage,
        defFinalUnitDamage,
        defMaxHitPoints)
----------Defines and status checks
print("Iam working")
   local attPlayer    = Players[attPlayerID]
    if not attPlayer then
       return
    end
   
    local attUnit = attPlayer:GetUnitByID(attUnitID)  
    if not attUnit then
       return
    end
   
    local defPlayer    = Players[defPlayerID]  
    if not defPlayer then
       return
    end
   
    local defUnit = defPlayer:GetUnitByID(defUnitID)  
    if not defUnit then
       return
    end
print ("I find it")
---------PromotionID
    local FrighteningID = GameInfo.UnitPromotions["PROMOTION_FRIGHTENING"].ID
    local FrightenedID = GameInfo.UnitPromotions["PROMOTION_TEMP_FRIGHTENED"].ID
-------Attacking bring enemy debuff
    if defFinalUnitDamage >= 100 then
            print("Defender is dead, no debuff effects!")
            return
    end
    if attUnit:IsHasPromotion(FrighteningID) then
            defUnit:SetMoves(0)
            print ("Cool")
        if not defUnit:IsHasPromotion(FrightenedID) then
               defUnit:SetHasPromotion(FrightenedID, true)
           end
------------------Notification
        if attPlayer:IsHuman() then
            print ("Nice shoot!")
-------------------------------------------------Map XY Grids
            local attX = attUnit:GetX()
            local attY = attUnit:GetY()
            local defX = defUnit:GetX()
            local defY = defUnit:GetY()
            local heading = Locale.ConvertTextKey("TXT_KEY_NOTIFICATION_ENEMY_FARED_SHORT");
            local text = Locale.ConvertTextKey("TXT_KEY_NOTIFICATION_ENEMY_FARED", defUnitName);
            attPlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC , text, heading, defX, defY)
            return
        end
        if defPlayer:IsHuman() then
            print ("So poor you!")
-------------------------------------------------Map XY Grids
            local attX = attUnit:GetX()
            local attY = attUnit:GetY()
            local defX = defUnit:GetX()
            local defY = defUnit:GetY()
            local heading = Locale.ConvertTextKey("TXT_KEY_NOTIFICATION_ARMY_FARED_SHORT");
            local text = Locale.ConvertTextKey("TXT_KEY_NOTIFICATION_ARMY_FARED", defUnitName);
            defPlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC , text, heading, defX, defY)
            return
        end
    else
        return
    end
end
GameEvents.CombatResult.Add(AttackDeBuff)
I use 'print' statement to track the running of functions.
Unfortunately, in my Lua.log,there is no output from these ''print''.
Code:
function UnityBonus(playerID)
local player = Players[playerID]
local UnityBonus1ID = GameInfo.UnitPromotions["PROMOTION_UNITE_BONUS_1"].ID
local UnityBonus2ID = GameInfo.UnitPromotions["PROMOTION_UNITE_BONUS_2"].ID
local UnityBonus3ID = GameInfo.UnitPromotions["PROMOTION_UNITE_BONUS_3"].ID
local UnityBonus4ID = GameInfo.UnitPromotions["PROMOTION_UNITE_BONUS_4"].ID

---------------------Run only when YAN player do turn-----------------------

if not player or not (player:IsEverAlive()) or (player:GetCivilizationType()~=GameInfoTypes.CIVILIZATION_YAN) then
    return
end
print("UnityBonus is working")
local myTeamIndex = player:GetTeam()
local maxNumWar=0
------------------Find out the max number of enemy's enemy---------------
for _, pPlayer in pairs(Players) do
    if pPlayer and pPlayer:IsEverAlive() and not pPlayer:IsBarbarian() then
    local pTeam = Teams[pPlayer:GetTeam()]
    if pTeam:IsAtWar(myTeamIndex)
        iNumWithWar = pteam:GetAtWarCount(true)
        if iNumWithWar > maxNumWar then
            maxNumWar = iNumWithWar
        end
    end
end
print("maxNumWar is "..maxNumWar)
-----------------Give the Melee /Gun and Mountied/Armor units corresponding promotion according to the maxNumWar-------------------
    --[[ nothing for 1
        "PROMOTION_UNITE_BONUS_1" for 2 ;
        "PROMOTION_UNITE_BONUS_2" for 3 ;
        "PROMOTION_UNITE_BONUS_3" for 4 ;
        "PROMOTION_UNITE_BONUS_4" for 5 or more ]]
    if (maxNumWar < 2 ) then
        for unit in player:Units() do
            if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MELEE) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MOUNTED) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_GUN) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARMOR) then
                if unit:IsHasPromotion(UnityBonus1ID) then
                unit:SetHasPromotion(UnityBonus1ID,false)
                end
                if unit:IsHasPromotion(UnityBonus2ID) then
                unit:SetHasPromotion(UnityBonus2ID,false)
                end
                if unit:IsHasPromotion(UnityBonus3ID) then
                unit:SetHasPromotion(UnityBonus3ID,false)
                end
                if unit:IsHasPromotion(UnityBonus4ID) then
                unit:SetHasPromotion(UnityBonus4ID,false)
                end
            end
        end  
    return
   
    elseif (maxNumWar == 2) then
        for unit in player:Units() do
            if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MELEE) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MOUNTED) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_GUN) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARMOR) then
                if  not unit:IsHasPromotion(UnityBonus1ID) then
                unit:SetHasPromotion(UnityBonus1ID,true)
                end
                if unit:IsHasPromotion(UnityBonus2ID) then
                unit:SetHasPromotion(UnityBonus2ID,false)
                end
                if unit:IsHasPromotion(UnityBonus3ID) then
                unit:SetHasPromotion(UnityBonus3ID,false)
                end
                if unit:IsHasPromotion(UnityBonus4ID) then
                unit:SetHasPromotion(UnityBonus4ID,false)
                end
            end
        end  
    return
   
    
    elseif maxNumWar == 3 then
        for unit in player:Units() do
            if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MELEE) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MOUNTED) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_GUN) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARMOR) then
                if unit:IsHasPromotion(UnityBonus1ID) then
                unit:SetHasPromotion(UnityBonus1ID,false)
                end
                if  not unit:IsHasPromotion(UnityBonus2ID) then
                unit:SetHasPromotion(UnityBonus2ID,true)
                end
                if unit:IsHasPromotion(UnityBonus3ID) then
                unit:SetHasPromotion(UnityBonus3ID,false)
                end
                if unit:IsHasPromotion(UnityBonus4ID) then
                unit:SetHasPromotion(UnityBonus4ID,false)
                end
            end
        end  
    return
   
    elseif maxNumWar == 4 then
        for unit in player:Units() do
            if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MELEE) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MOUNTED) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_GUN) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARMOR) then
                if unit:IsHasPromotion(UnityBonus1ID) then
                unit:SetHasPromotion(UnityBonus1ID,false)
                end
                if unit:IsHasPromotion(UnityBonus2ID) then
                unit:SetHasPromotion(UnityBonus2ID,false)
                end
                if  not unit:IsHasPromotion(UnityBonus3ID) then
                unit:SetHasPromotion(UnityBonus3ID,true)
                end
                if unit:IsHasPromotion(UnityBonus4ID) then
                unit:SetHasPromotion(UnityBonus4ID,false)
                end
            end
        end  
    return
   
    elseif iNumWithWar == 5 or iNumWithWar > 5 then
        for unit in player:Units() do
            if (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MELEE) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_MOUNTED) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_GUN) or (unit:GetUnitCombatType() == GameInfoTypes.UNITCOMBAT_ARMOR) then
                if unit:IsHasPromotion(UnityBonus1ID) then
                unit:SetHasPromotion(UnityBonus1ID,false)
                end
                if unit:IsHasPromotion(UnityBonus2ID) then
                unit:SetHasPromotion(UnityBonus2ID,false)
                end
                if unit:IsHasPromotion(UnityBonus3ID) then
                unit:SetHasPromotion(UnityBonus3ID,false)
                end
                if  not unit:IsHasPromotion(UnityBonus4ID) then
                unit:SetHasPromotion(UnityBonus4ID,true)
                end
            end
        end
    end
end

GameEvents.PlayerDoTurn.Add(UnityBonus)
 
Last edited:
I have never seen that before, but I can think of two things right now:
1) I assume you are using a modded DLL as you're using GameEvents.CombatResult. Is that the CP (or CBP) or the VMC DLL? If the latter, you would first have to enable the event using SQL if you haven't done so already. It would probably throw a different kind of error, but it's worth a shot anyway.
2) Maybe you made a typo while giving your file an InGameUIAddin entry

---
The not printing of your Lua files could be related to 3 things:
1) The statements are never reached. I always add one at the top of the file to be sure that the file is loaded correctly, as this is always reached.
2) You have not given your file an InGameUIAddin entry in modbuddy
3) You have not enabled logging! See whoward69's tutorial on how to do that.
 
1) I assume you are using a modded DLL as you're using GameEvents.CombatResult. Is that the CP (or CBP) or the VMC DLL? If the latter, you would first have to enable the event using SQL if you haven't done so already.
I copied the EVENT from other mod which require the VMC.I am going to use the Events.EndCombatSim.Add()http://modiki.civfanatics.com/index.php?title=Events.EndCombatSim_(Civ5_API) instead.
This code is in DLC/Expansion2/UI/InGame/UnityFlagManger.lua.
Code:
function OnCombatEnd( m_AttackerPlayer,
                      m_AttackerUnitID,
                      m_AttackerUnitDamage,
                      m_AttackerFinalUnitDamage,
                      m_AttackerMaxHitPoints,
                      m_DefenderPlayer,
                      m_DefenderUnitID,
                      m_DefenderUnitDamage,
                      m_DefenderFinalUnitDamage,
                      m_DefenderMaxHitPoints )
                     
    local playerTable = g_MasterList[ m_AttackerPlayer ];
    if( playerTable ~= nil )
    then
        local flag = playerTable[ m_AttackerUnitID ];
        if( flag ~= nil )
        then
            flag.m_IsForceHide = false;
            flag:UpdateVisibility();
            if( flag.m_Escort ~= nil ) then
                flag.m_Escort.m_IsForceHide = false;
                flag.m_Escort:UpdateVisibility();
            end
        end
    end
 
    playerTable = g_MasterList[ m_DefenderPlayer ];
    if( playerTable ~= nil )
    then
        local flag = playerTable[ m_DefenderUnitID ];
        if( flag ~= nil )
        then
            flag.m_IsForceHide = false;
            flag:UpdateVisibility();
            if( flag.m_Escort ~= nil ) then
                flag.m_Escort.m_IsForceHide = false;
                flag.m_Escort:UpdateVisibility();
            end
        end
    end        
end
Events.EndCombatSim.Add( OnCombatEnd );
Exactly,my function only need
attPlayerID,
attUnitID,
defPlayerID,
defUnitID.
But do I still need to write those variables that have no use, in theparentheses -- to take a seat?




-------
The not printing of your Lua files could be related to 3 things:
1) The statements are never reached. I always add one at the top of the file to be sure that the file is loaded correctly, as this is always reached.
I enabled my logand give the file InGameUIAddin entry .I will check if there is a typo.
And I will do more test such as delete some statements to see if it works.


EDIT:There is a typo in my InGameUIAddin entry.It belongs to another file,——
temporarily I never call it.So I didn't find it.It makes the InGame.lua return an error and stop loading my rest file.So,my file after it didn't work.
--------I enabled the VMC,then event works alright.
Code:
<CustomModOptions>
<Update>
            <Where Name="EVENTS_RED_TURN"/>
            <Set Value="1"/>
        </Update>
        <Update>
            <Where Name="EVENTS_RED_COMBAT"/>
            <Set Value="1"/>
        </Update>
        <Update>
            <Where Name="EVENTS_RED_COMBAT_MISSION"/>
            <Set Value="1"/>
        </Update>
        <Update>
            <Where Name="EVENTS_RED_COMBAT_ABORT"/>
            <Set Value="1"/>
        </Update>
        <Update>
            <Where Name="EVENTS_RED_COMBAT_RESULT"/>
            <Set Value="1"/>
        </Update>
        <Update>
            <Where Name="EVENTS_RED_COMBAT_ENDED"/>
            <Set Value="1"/>
        </Update>
</CustomModOptions>
only the"
<Update>
<Where Name="EVENTS_RED_COMBAT_RESULT"/>
<Set Value="1"/>
</Update>
"is not enough.
 
Last edited:
I copied the EVENT from other mod which require the VMC.I am going to use the Events.EndCombatSim.Add()http://modiki.civfanatics.com/index.php?title=Events.EndCombatSim_(Civ5_API) instead.
That one has many issues. E.g. it never fires if you're playing in strategic view, and doesn't fire if you don't have vision of the units as the human player. Use VMC's/CP's hooks instead if you really need it.

Exactly,my function only need
attPlayerID,
attUnitID,
defPlayerID,
defUnitID.
But do I still need to write those variables that have no use, in theparentheses -- to take a seat?
You can omit all variables at the end of the 'arguments-list' that you don't need, or you can assign a variable to something like '_'.
E.g. for UnitSetXY(iPlayer,iUnit,iX,iY) when we're not interested in iX and iY
Code:
function myExample(iPlayer,iUnit)

end
GameEvents.UnitSetXY(myExample)

E.g. for UnitSetXY(iPlayer,iUnit,iX,iY) when we're not interested in iUnit and iX
Code:
function myExample(iPlayer,_,_,iY)

end
GameEvents.UnitSetXY(myExample)
or just a combination of those. E.g. for UnitSetXY(iPlayer,iUnit,iX,iY) when we're not interested in iUnit and iY
Code:
function myExample(iPlayer,_,iX)

end
GameEvents.UnitSetXY(myExample)
 
That one has many issues. E.g. it never fires if you're playing in strategic view, and doesn't fire if you don't have vision of the units as the human player. Use VMC's/CP's hooks instead if you really need it.


You can omit all variables at the end of the 'arguments-list' that you don't need, or you can assign a variable to something like '_'.
E.g. for UnitSetXY(iPlayer,iUnit,iX,iY) when we're not interested in iX and iY
Code:
function myExample(iPlayer,iUnit)

end
GameEvents.UnitSetXY(myExample)

E.g. for UnitSetXY(iPlayer,iUnit,iX,iY) when we're not interested in iUnit and iX
Code:
function myExample(iPlayer,_,_,iY)

end
GameEvents.UnitSetXY(myExample)
or just a combination of those. E.g. for UnitSetXY(iPlayer,iUnit,iX,iY) when we're not interested in iUnit and iY
Code:
function myExample(iPlayer,_,iX)

end
GameEvents.UnitSetXY(myExample)
Oh,I see.Thank you very much.
 
Dear Troller0001,Is there any function to adjust diplomacy realtion with all other civs?
Code:
GameEvents.GetScenarioDiploModifier1.Add(function(ePlayer1, ePlayer2)
-- This is what we are trying to achieve
-- if ePlayer1 is France (or Greece) and ePlayer2 is Greece (or France), return -25 otherwise 0 -- We don't want player ids, we need civ ids local eCiv1 = Players[ePlayer1]:GetCivilizationType() local eCiv2 = Players[ePlayer2]:GetCivilizationType()
if ((eCiv1 == GameInfoTypes.CIVILIZATION_FRANCE and eCiv2 == GameInfoTypes.CIVILIZATION_GREECE) or (eCiv1 == GameInfoTypes.CIVILIZATION_GREECE and eCiv2 == GameInfoTypes.CIVILIZATION_FRANCE)) then
--[[print(Players[ePlayer1]:GetName()) print(Players[ePlayer2]:GetName())]] 
return -25 
else
return 0 
end 
end)
I find this.I want to know when the GameEvents.GetScenarioDiploModifier1 will ocuur?Why the int -25 will be passed to diplomacy relation?
 
From what I read somewhere quite some time ago (I can't remember exactly where) the scenario modifiers allow for only 1 mod to use them. E.g. If mod A uses ScenarioDiploModifer1, then mod B also cannot use it.
Any value returned from the event contributes towards a positive relation from civ 1 to civ 2 respectively. In the code above, a '-25' relation is added from France to Greece and vice versa.
Because of Firaxis logic, negative numbers have a positive contribution towards relations. In your case, France and Greece will like each other more easily. I don't know the 'scale' of these numbers though, so I have no idea if '-25' is a small, medium, or big boost in relations.

As you may expect, you can check the scenarios for their use.

VMC/the CP introduces GetDiploModifier, which functions exactly the same as the ScenarioDiploModifier above, but allows for an infinite number of mods to subscribe to it and allows it to be displayed on the diplo screen. More information on it can be found in this post.
 
Top Bottom