C++/Lua Request Thread

-EDIT-
I've now solved my problem and a fully working FaithFromDyingUnits routine. It is limited in scope, only providing Faith from land units that are not unique to other civilizations (adding in compatibility for the possible thousands of unique units of other civilizations, or heck, even just the ones from the base game and expansions, does not sound fun).

I may decide to post a modified version of the code later for use by other users, but right now I'd rather just enjoy the fruits of my labors.

-OLD-
Alright, let's try this once more. Still trying to get the "Units provide Faith from Dying" thing working, and now I've tweaked a code that formerly provided Specialist points in the Capital from killing enemy units. I'm trying to tweak it so it will simply provide Faith to a chosen Civilization when their units die, and I know that this code can work for what I need it to, I just don't have the proper knowledge to fully realize it. If anyone could help me tweak it to get the results I'm looking for, that'd be fantastic.

Code here:
Code:
include("FLuaVector.lua")
include( "ModTools.lua" );

local defUnitID;
function GetVoPDeadUnit(player, unitID)
   defUnitID = unitID;
   return false;
end
GameEvents.CanSaveUnit.Add(GetVoPDeadUnit);

function FaithFromDyingUnit(attPlayerID,defPlayerID,defUnitTypeID)
    local attPlayer    = Players[attPlayerID];
    local defPlayer    = Players[defPlayerID];
    local defUnit    = defPlayer:GetUnitByID(defUnitID);
    if defPlayer:GetCivilizationType() ~= GameInfoTypes.CIVILIZATION_AMERICA then return end
    local fyModifier = 0;
    local fy = 0;
    local tempCount = 0;
    local maxCount = 0;
    local fyType = "YIELD_FAITH";
    local fyYield = GameInfo.Yields["YIELD_FAITH"];
    local fyID = fyYield.ID;

    if not defUnit then
      print("FaithFromDyingUnitNodefUnit!");
      return;
    end
  
    local fyPlayer = defPlayer:GetCivilizationType();--local fyCity = defPlayer:GetCapitalCity();
    local HexPos = ToHexFromGrid(Vector2( defUnit:GetX(), defUnit:GetY()));
    if not defUnit:IsCombatUnit() then
        print("FaithFromDyingUNitNotCombatUnit!");
       return;
    end
    if not IsMajorCiv(defPlayer) or not IsMajorCiv(attPlayer) then return;
    end
  
    print("FaithFromDyingUnitStartCalculate");
  
    local fyModifier = 50;
    if fyModifier == 0 then
       return;
    end
    local defCombat = defUnit:GetBaseCombatStrength();
    fy = defCombat*fyModifier;   
    --for pPlayer in defPlayer:CivilizationType() do
        for tempYield in  GameInfo.Yields() do
           local tempType = tempYield.Type;
           if tempType == "YIELD_FAITH" then
              local tempID = tempYield.ID;
              tempCount =player:GetFaith(tempID);
              print("FaithFromDyingUnitFaith="..tempCount);
              if tempCount > maxCount then
                 maxCount = tempCount;
                 fyType = tempType;
                 fyID = tempID;
                 fyPlayer = pPlayer;--fyCity = pCity;
              end
           end
        end      
    --end
print("FaithFromDyingUnitAddFaith");
local rand = Game.Rand(100,"Faith From Dying Promotion");
if fyPlayer then--if fyCity then
    fyPlayer:ChangeFaith(fyID,fy);--fyCity:ChangeFaith(fyID,fy);
end
print("FaithFromDyingUnitComplete");
local popupstr = "+".. math.floor(fy/100).." [ICON_PEACE]" ;
Events.AddPopupTextEvent(HexToWorld(HexPos),popupstr, 2);
end

GameEvents.UnitKilledInCombat.Add(FaithFromDyingUnit);
And just to be safe and for reference, here's the original code I modified the above code from:
Code:
include("FLuaVector.lua")
include( "ModTools.lua" );

local defUnitID;
function GetVoPDeadUnit(player, unitID)
   defUnitID = unitID;
   return false;
end
GameEvents.CanSaveUnit.Add(GetVoPDeadUnit);

function AwardGreatPersonPoint(attPlayerID,defPlayerID,defUnitTypeID)
    local attPlayer    = Players[attPlayerID];
    local defPlayer    = Players[defPlayerID];
    local defUnit    = defPlayer:GetUnitByID(defUnitID);
    if attPlayer:GetCivilizationType() ~= GameInfoTypes.CIVILIZATION_AMERICA then return end
    local gpModifier = 0;
    local gp = 0;
    local tempCount = 0;
    local maxCount = 0;
    local gpType = "SPECIALIST_SCIENTIST";
    local gpSpecialist = GameInfo.Specialists["SPECIALIST_SCIENTIST"];
    local gpID = gpSpecialist.ID;

    if not defUnit then
      print("AwardCombatGPPNodefUnit!");
      return;
    end
  
    local gpCity = attPlayer:GetCapitalCity();
    local HexPos = ToHexFromGrid(Vector2( defUnit:GetX(), defUnit:GetY()));
    if not defUnit:IsCombatUnit() then    --Uncombat units do not count.
        print("AwardCombatGPPNotCombatUnit!");
       return;
    end
    if not IsMajorCiv(defPlayer) or not IsMajorCiv(attPlayer) then return;  -- City-States and Barbarian do not count;
    end
  
    print("AwardCombatGPPStartCalculate");
  
    --local Trait = GetPlayerTrait(attPlayer);
    local gpModifier = 50; --local gpModifier = Trait.CombatGPP;
    if gpModifier == 0 then
       return;
    end
    local defCombat = defUnit:GetBaseCombatStrength();
    gp = defCombat*gpModifier;   
    for pCity in attPlayer:Cities() do
        for tempSpecialist in  GameInfo.Specialists() do
           local tempType = tempSpecialist.Type;
           if tempType == "SPECIALIST_SCIENTIST" then
              local tempID = tempSpecialist.ID;
              tempCount =pCity:GetSpecialistGreatPersonProgress(tempID);
              print("AwardCombatGPPSpecialistGPP="..tempCount);
              if tempCount > maxCount then
                 maxCount = tempCount;
                 gpType = tempType;
                 gpID = tempID;
                 gpCity = pCity;
              end
           end
        end      
    end
print("AwardCombatGPPAddGPP");
local TextType=" ";
local name = gpCity:GetName();
if gpType ==  "SPECIALIST_SCIENTIST" then
   TextType = TextType..Locale.ConvertTextKey("TXT_KEY_COMBAT_GREAT_SCIENTIST_POINT");
end
local Fin=" ";
Fin = Fin..Locale.ConvertTextKey("TXT_KEY_IN");
local rand = Game.Rand(100,"Great Scientist Points Promotion");
if gpCity then
    gpCity:ChangeSpecialistGreatPersonProgressTimes100(gpID,gp);
end
print("AwardCombatGPPComplete");
local popupstr = "[COLOR:255:87:155:255]+".. math.floor(gp/100).."[ENDCOLOR] [ICON_GREAT_PEOPLE] " ..TextType..Fin.." "..name.."." ;
Events.AddPopupTextEvent(HexToWorld(HexPos),popupstr, 2);
end

GameEvents.UnitKilledInCombat.Add(AwardGreatPersonPoint); --Now works in quick combat mode.
I've taken bits and pieces of different codes and seen them work to varying degrees of success, but I just know that this particular one hides the secrets to what I desire. I just need this particular code problem solved, and I can probably stop spamming this thread with requests as my other, early posts are mute at this point.
 
Last edited:
Can I trigger a save from LUA? Similar to an autosave - I just want it to happen with no action from me and preferably with no message displayed.

The reason is that the game crashes sometimes, usually on the barbs turn or an AI turn, and I have to replay the turn. It happens often enough that I would like to do something to reduce the impact. What I want to do is to automatically save the game at the end of my turn before the other players turn. I can use the ActivePlayerTurnEnd event to identify the correct time to save, but have not found a method to make the save.

Any help or thoughts appreciated.

Update: I found the quicksave() routine (don't know how I missed it before) and called that from the ActivePlayerTurnEnd event. If sort of worked, but on loading the saved game, there were sometimes some odd side effects, so I guess that event is actually too late for what I want.
 
Last edited:
I want to add a trait that If my diplomats are in the other Capitals, the other Civs get 10% Tourism Pressure.
So, I made a lua code, but I don't know what should I do next. Please help me.

Code:
local catherinetrait    =    GameInfoTypes["BUILDING_CATHERINE_FRANCE_TRAIT2"]
function CatherineTourism(playerID)
    local pPlayer = Players[playerID]
    if pPlayer:GetCivilizationType() == catherine and pPlayer:IsAlive() then
        local iSurveillanceSpy = 0
        for i,v in pairs(pPlayer:GetEspionageSpies()) do
            if v.IsDiplomat then
        end
    end
end
 
I want to add a trait that If my diplomats are in the other Capitals, the other Civs get 10% Tourism Pressure.
So, I made a lua code, but I don't know what should I do next. Please help me.

Code:
local catherinetrait    =    GameInfoTypes["BUILDING_CATHERINE_FRANCE_TRAIT2"]
function CatherineTourism(playerID)
    local pPlayer = Players[playerID]
    if pPlayer:GetCivilizationType() == catherine and pPlayer:IsAlive() then
        local iSurveillanceSpy = 0
        for i,v in pairs(pPlayer:GetEspionageSpies()) do
            if v.IsDiplomat then
        end
    end
end
(pActivePlayer:IsMyDiplomatVisitingThem(iPlayer))

Although, I don't know how to add tourism separately to each civ after this.
 
I want to boost science by producing per turn when my scientist appear. But, my code doesn't work. Please help me.


Code:
if pUnit:GetUnitClassType() == unitClassGreatScientistID then
            local teamID = pPlayer:GetTeam()
            local pTeam = Teams[teamID]
            local TurnScience = pPlayer:GetScience()
            local pTechs = pTeam:GetTeamTechs()
            pTechs:ChangeResearchProgress(pTechs, TurnScience, pPlayer)
        end
 
I want to boost science by producing per turn when my scientist appear. But, my code doesn't work. Please help me.


Code:
if pUnit:GetUnitClassType() == unitClassGreatScientistID then
            local teamID = pPlayer:GetTeam()
            local pTeam = Teams[teamID]
            local TurnScience = pPlayer:GetScience()
            local pTechs = pTeam:GetTeamTechs()
            pTechs:ChangeResearchProgress(pTechs, TurnScience, pPlayer)
        end
This can't be all. There's no GameEvent to initiate the code.
 
N
Well, there is a GameEvent under the code. It is omitted during copy and paste. So, it isn't a problem.
No omitting. I want the rest of the code. You may have not even used the right GameEvent or function identifier.
 
N

No omitting. I want the rest of the code. You may have not even used the right GameEvent or function identifier.

Code:
local JeongJo    =    GameInfoTypes["CIVILIZATION_JEONGJO"]
local unitClassGreatScientistID      = GameInfoTypes["UNITCLASS_SCIENTIST"]
function JeongJoGreatPeople(playerID, unitID, teamID)
 local pPlayer = Players[playerID]
 if pPlayer:GetCivilizationType() == JeongJo and pPlayer:IsAlive() then
  local pUnit = pPlayer:GetUnitByID(unitID)
  if pUnit:GetUnitClassType() == unitClassGreatScientistID then
   local teamID = pPlayer:GetTeam()
   local pTeam = Teams[teamID]
   local TurnScience = pPlayer:GetScience()
   local pTechs = pTeam:GetTeamTechs()
   pTechs:ChangeResearchProgress(pTechs, TurnScience, pPlayer)
  end
 end
end

Events.SerialEventUnitCreated.Add(JeongJoGreatPeople)
 
Try this.
Code:
local JeongJo    =    GameInfoTypes["CIVILIZATION_JEONGJO"]
local unitClassGreatScientistID      = GameInfoTypes["UNITCLASS_SCIENTIST"]
function JeongJoGreatPeople(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
    local pPlayer = Players[playerID]
    if pPlayer:GetCivilizationType() == JeongJo and pPlayer:IsAlive() then
        local pUnit = pPlayer:GetUnitByID(unitID)
        if (pUnit:IsDead() or pUnit:GetUnitClassType() ~= unitClassGreatScientistID) then
            return
        end
        local iTurnScience = pPlayer:GetScience()
        local pTeamTechs = Teams[pPlayer:GetTeam()]:GetTeamTechs()
        pTeamTechs:ChangeResearchProgress(pPlayer:GetCurrentResearch(), iTurnScience, pPlayer:GetID())
    end
end
Events.SerialEventUnitCreated.Add(JeongJoGreatPeople)
 
Try this.
Code:
local JeongJo    =    GameInfoTypes["CIVILIZATION_JEONGJO"]
local unitClassGreatScientistID      = GameInfoTypes["UNITCLASS_SCIENTIST"]
function JeongJoGreatPeople(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
    local pPlayer = Players[playerID]
    if pPlayer:GetCivilizationType() == JeongJo and pPlayer:IsAlive() then
        local pUnit = pPlayer:GetUnitByID(unitID)
        if (pUnit:IsDead() or pUnit:GetUnitClassType() ~= unitClassGreatScientistID) then
            return
        end
        local iTurnScience = pPlayer:GetScience()
        local pTeamTechs = Teams[pPlayer:GetTeam()]:GetTeamTechs()
        pTeamTechs:ChangeResearchProgress(pPlayer:GetCurrentResearch(), iTurnScience, pPlayer:GetID())
    end
end
Events.SerialEventUnitCreated.Add(JeongJoGreatPeople)
He should use Machiavelli's version of SerialEventUnitCreated though, as the normal SerialEventUnitCreated will fire when the player reloads the game, embarks the unit, or upgrades it (though the latter will not be a problem with the Scientist)
LINK: Machiavelli's SerialEventUnitCreatedGood
 
He should use Machiavelli's version of SerialEventUnitCreated though, as the normal SerialEventUnitCreated will fire when the player reloads the game, embarks the unit, or upgrades it (though the latter will not be a problem with the Scientist)
LINK: Machiavelli's SerialEventUnitCreatedGood
The only thing that Machiavelli adds is a failsafe to ensure no duplicate unit code. I can just add one line and make one simple adjustment to ensure that the great scientist that was originally born isn't just re-made into the same coding again.
Code:
local JeongJo    =    GameInfoTypes["CIVILIZATION_JEONGJO"]
local unitClassGreatScientistID      = GameInfoTypes["UNITCLASS_SCIENTIST"]
function JeongJoGreatPeople(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
    local pPlayer = Players[playerID]
    if pPlayer:GetCivilizationType() == JeongJo and pPlayer:IsAlive() then
        local pUnit = pPlayer:GetUnitByID(unitID)
        if (pUnit:IsDead() or pUnit:GetUnitClassType() ~= unitClassGreatScientistID or pUnit:IsHasPromotion(whateverthisstupidcodeis)) then
            return
        end
        pUnit:SetHasPromotion(whateverthisstupidcodeis, true)
        local iTurnScience = pPlayer:GetScience()
        local pTeamTechs = Teams[pPlayer:GetTeam()]:GetTeamTechs()
        pTeamTechs:ChangeResearchProgress(pPlayer:GetCurrentResearch(), iTurnScience, pPlayer:GetID())
    end
end
Events.SerialEventUnitCreated.Add(JeongJoGreatPeople)
 
The only thing that Machiavelli adds is a failsafe to ensure no duplicate unit code. I can just add one line and make one simple adjustment to ensure that the great scientist that was originally born isn't just re-made into the same coding again.
Code:
local JeongJo    =    GameInfoTypes["CIVILIZATION_JEONGJO"]
local unitClassGreatScientistID      = GameInfoTypes["UNITCLASS_SCIENTIST"]
function JeongJoGreatPeople(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
    local pPlayer = Players[playerID]
    if pPlayer:GetCivilizationType() == JeongJo and pPlayer:IsAlive() then
        local pUnit = pPlayer:GetUnitByID(unitID)
        if (pUnit:IsDead() or pUnit:GetUnitClassType() ~= unitClassGreatScientistID or pUnit:IsHasPromotion(whateverthisstupidcodeis)) then
            return
        end
        pUnit:SetHasPromotion(whateverthisstupidcodeis, true)
        local iTurnScience = pPlayer:GetScience()
        local pTeamTechs = Teams[pPlayer:GetTeam()]:GetTeamTechs()
        pTeamTechs:ChangeResearchProgress(pPlayer:GetCurrentResearch(), iTurnScience, pPlayer:GetID())
    end
end
Events.SerialEventUnitCreated.Add(JeongJoGreatPeople)

Thank you. Well, I have another question. Can I spread tourism when my Musician birth by lua?
 
Thank you. Well, I have another question. Can I spread tourism when my Musician birth by lua?
I don't think Tourism is a yield in BNW, thus you can't just add Tourism naturally via Lua. I mod mainly within CP DLL now, so I don't know.
 
There is this code from the Futurism Tenet in BNW. (+250 Tourism to all Civilizations when a Great Writer, Artist or Musician is born)
So just give your civ a dummy policy which has the same effect, but with your desired amount of tourism and instead only add it for the Musician unitclass.
Code:
<Policy_TourismOnUnitCreation>
        <Row>
            <PolicyType>POLICY_FUTURISM</PolicyType>
            <UnitClassType>UNITCLASS_WRITER</UnitClassType>
            <Tourism>250</Tourism>
        </Row>
        <Row>
            <PolicyType>POLICY_FUTURISM</PolicyType>
            <UnitClassType>UNITCLASS_ARTIST</UnitClassType>
            <Tourism>250</Tourism>
        </Row>
        <Row>
            <PolicyType>POLICY_FUTURISM</PolicyType>
            <UnitClassType>UNITCLASS_MUSICIAN</UnitClassType>
            <Tourism>250</Tourism>
        </Row>
    </Policy_TourismOnUnitCreation>
 
There is this code from the Futurism Tenet in BNW. (+250 Tourism to all Civilizations when a Great Writer, Artist or Musician is born)
So just give your civ a dummy policy which has the same effect, but with your desired amount of tourism and instead only add it for the Musician unitclass.
Code:
<Policy_TourismOnUnitCreation>
        <Row>
            <PolicyType>POLICY_FUTURISM</PolicyType>
            <UnitClassType>UNITCLASS_WRITER</UnitClassType>
            <Tourism>250</Tourism>
        </Row>
        <Row>
            <PolicyType>POLICY_FUTURISM</PolicyType>
            <UnitClassType>UNITCLASS_ARTIST</UnitClassType>
            <Tourism>250</Tourism>
        </Row>
        <Row>
            <PolicyType>POLICY_FUTURISM</PolicyType>
            <UnitClassType>UNITCLASS_MUSICIAN</UnitClassType>
            <Tourism>250</Tourism>
        </Row>
    </Policy_TourismOnUnitCreation>

Thank you!
Can I give bonuses by the number of policies and kinds of them that I have adopt when my specific building is in the city?
 
Thank you!
Can I give bonuses by the number of policies and kinds of them that I have adopt when my specific building is in the city?
I don't think I get what you mean... Do you want the effect to only appear when a Musician is spawned in a city with a specific building? If yes, you'd need a different approach than the dummy policies.
 
I don't think I get what you mean... Do you want the effect to only appear when a Musician is spawned in a city with a specific building? If yes, you'd need a different approach than the dummy policies.

Not musician. I mean that for example, Can I get bonuses by kind of policies and the number of them when I have built Gyujanggak(Unique Building)?
 
To get tourism bonuses, I made the code. But It doesn't work well. I want that if the number of policies that I have adopt is 30 or more and less than 40, I get 5 tourism, and If it is 40 or more, I get 10.

Code:
local JeongJoDummy = GameInfoTypes["BUILDING_JEONGJO_DUMMY"]
local JeongJoDummy2 = GameInfoTypes["BUILDING_JEONGJO_DUMMY2"]
local JeongJoDummy3 = GameInfoTypes["BUILDING_JEONGJO_DUMMY3"]
local JeongJoDummy4 = GameInfoTypes["BUILDING_JEONGJO_DUMMY4"]
local GyujanggakID = GameInfoTypes["BUILDING_GYUJANGGAK"]
function JeongJoGyujanggak(playerID, policyID)
    local pPlayer = Players[playerID]
    if pPlayer:GetCivilizationType() == JeongJo and pPlayer:IsAlive() then
        for pCity in pPlayer:Cities() do
            if pCity:IsHasBuilding(GyujanggakID) then
                local NumberOfPolicies = pPlayer:GetNumPolicies()
                if NumberOfPolicies >= 5 and NumberOfPolicies < 10 then
                    pCity:SetNumRealBuilding(JeongJoDummy, 1)
                end
                if NumberOfPolicies >= 10 and NumberOfPolicies < 15 then
                    pCity:SetNumRealBuilding(JeongJoDummy, 1)
                    pCity:SetNumRealBuilding(JeongJoDummy2, 1)
                end
                if NumberOfPolicies >= 15 and NumberOfPolicies < 20 then
                    pCity:SetNumRealBuilding(JeongJoDummy, 1)
                    pCity:SetNumRealBuilding(JeongJoDummy2, 2)
                end
                if NumberOfPolicies >= 20 and NumberOfPolicies < 25 then
                    pCity:SetNumRealBuilding(JeongJoDummy, 1)
                    pCity:SetNumRealBuilding(JeongJoDummy2, 2)
                    pCity:SetNumRealBuilding(JeongJoDummy3, 1)
                end
                if NumberOfPolicies >= 25 and NumberOfPolicies < 30 then
                    pCity:SetNumRealBuilding(JeongJoDummy, 2)
                    pCity:SetNumRealBuilding(JeongJoDummy2, 3)
                    pCity:SetNumRealBuilding(JeongJoDummy3, 1)
                end
                if NumberOfPolicies >= 30 and NumberOfPolicies < 40 then
                    pCity:SetNumRealBuilding(JeongJoDummy, 2)
                    pCity:SetNumRealBuilding(JeongJoDummy2, 3)
                    pCity:SetNumRealBuilding(JeongJoDummy3, 1)
                    pCity:SetNumRealBuilding(JeongJoDummy4, 1)
                end
                if NumberOfPolicies >= 40 then
                    pCity:SetNumRealBuilding(JeongJoDummy, 3)
                    pCity:SetNumRealBuilding(JeongJoDummy2, 4)
                    pCity:SetNumRealBuilding(JeongJoDummy3, 1)
                    pCity:SetNumRealBuilding(JeongJoDummy4, 0)
                    pCity:SetNumRealBuilding(JeongJoDummy5, 1)
                end
            end
        end
    end
end

JeongJoDummy4 produces 5 tourism and JeongJoDummy5 does 10.
 
You forgot to hook up a (Game)Event to your function, so it never runs.
Try adding
Code:
GameEvents.PlayerDoTurn.Add(JeongJoGyujanggak)

Adding one or more print()'s to the code allows you to spot these kinds of mistakes way easier when you open up the Lua.log.

--
I'm assuming that JeongJoDummy, JeongJoDummy2, and JeongJoDummy3 do not provide tourism as you add multiple copies of those while tourism doesn't stack.
 
Top Bottom