C++/Lua Request Thread

Well then. I've found a couple functions that seem to work PERFECTLY for stealing Great Works! Namely, City:ClearGreatWorks() and, mostly actually, City:SetBuildingGreatWork(int:iBuildingClass, int:iSlot, int:iGreatWorkIndex). If you do something like the following:
Code:
pCity:SetBuildingGreatWork(iClassOne,iSlot,iWork)
pOtherCity:SetBuildingGreatWork(iClassTwo,iOtherSlot,-1)
The first line will essentially make a duplicate of the indexed GW, and the second line will clear the GW from its slot completely! The duplicate can be made in your own city, and the second line can clear a GW from another player's city, so, unless there are some unforseen issues, they seem to work fine! I've searched the forum, and there's no mention of these functions. Has no one used them? Are there some problems with their use that discourages people from using them? Or have I just found my golden ticket?
 
this keeps returning false even though I have this building in my city:

if City:IsHasBuilding(GameInfoTypes.BUILDING_HMGOVCITY) then

Any idea why?
 
yes:

Code:
    <BuildingClasses>
    <Row>
        <Type>BUILDINGCLASS_SFC</Type>
        <DefaultBuilding>BUILDING_SFC</DefaultBuilding>
        <Description>TXT_KEY_HMTHING</Description>
        <MaxPlayerInstances>1</MaxPlayerInstances>
    </Row>
        <Row>
            <Type>BUILDINGCLASS_HMGOVCITY</Type>
            <DefaultBuilding>BUILDING_HMGOVCITY</DefaultBuilding>
            <MaxPlayerInstances>3</MaxPlayerInstances>
        </Row>
    </BuildingClasses>
    <Buildings>
    <Row>
            <Type>BUILDING_HMGOVCITY</Type>
        <BuildingClass>BUILDINGCLASS_HMGOVCITY</BuildingClass>
        <Cost>-1</Cost>
        <PrereqTech/>
        <Description>TXT_KEY_BUILDING_HINGF</Description>
        <Civilopedia>TXT_KEY_BUILDING_HINGF2</Civilopedia>
        <Strategy>TXT_KEY_BUILDING_HINGF2</Strategy>
        <ArtDefineTag>COLESSEUM</ArtDefineTag>
        <UnhappinessModifier>0</UnhappinessModifier>
        <MinAreaSize>-1</MinAreaSize>
        <HurryCostModifier>-1</HurryCostModifier>
        <NeverCapture>true</NeverCapture>
        <NukeImmune>true</NukeImmune>
        <IconAtlas>SHARED_CIV_COLOR_ATLAS</IconAtlas>
        <PortraitIndex>0</PortraitIndex>
    </Row>
--another row is defined after this one

Also, I setup the trait to give it for free in cities, I'm hoping after you get 3 the game won't spawn any more.

I know this part is working, as I can see the building in the City View.
 
Last edited:
[ code ] and [ /code ] without the extra spaces will create a code block which is much easier to read.

What is the lua code?

better yet, what is the latest version of the mod. The earlier version you posted on that other thread asking about the "annexing" issue does not show the building you are referring to,
 
I updated it since then, trying to fix this issue.

So, here's the code for the function that is not working right:

Code:
function PrivateCity(iPlayer)
    local pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == iCiv) then
    if (pPlayer:IsAlive()) then
    local intcount=-1
  for City in pPlayer:Cities() do
  local popchange=0
                  --local unitdata=GameInfo.Units[unittype]


               
  if City:IsHasBuilding(GameInfoTypes.BUILDING_HMGOVCITY) then
  City:SetPuppet(0)
  else
    intcount=intcount+1
  City:SetPuppet(1)
  City:SetProductionAutomated(true);
  if City:GetPopulation()>citypop[intcount] then
  citypop[intcount]=City:GetPopulation()
  City:ChangeProduction(City:GetPopulation()*5)
  if pPlayer:IsHuman() then
  pPlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC,"You've recived a "..(City:GetPopulation()*5).." production bonus in the private city of "..City:GetName(),"Production Bonus!", -1);
  end end
    end
    end
    end end
end
 
How are you determining that the code is getting false from
Code:
City:IsHasBuilding(GameInfoTypes.BUILDING_HMGOVCITY)

what do you get if you stick this into the code:
Code:
print("GameInfoTypes.BUILDING_HMGOVCITY gives " .. tostring(GameInfoTypes.BUILDING_HMGOVCITY))

without the mod itself as you currently have it to make a test on it is impossible for me to see what is going wrong.
 
if you run this
Code:
if 1 == true then
 print("true == 1")
else
 print("true =/= 1")
end
if 0 == false then
 print("false == 0")
else
 print("false =/= 0")
end
on the lua demo page @ https://www.lua.org/cgi-bin/demo you get the following
Code:
true =/= 1
false =/= 0
The command
Code:
if City:IsHasBuilding(GameInfoTypes.BUILDING_HMGOVCITY) then
is in fact working properly. The problem is that stating this:

City:SetPuppet(0)​

is actually interpretted by lua as being the same as stating

City:SetPuppet()​

which defaults to setting the city as being a puppet. City:SetPuppet(1) will have the same effect as setting City:SetPuppet(0) . Both will be interpretted as if you had stated City:SetPuppet(true).

Code:
print("GameInfoTypes.BUILDING_HMGOVCITY gives " .. tostring(GameInfoTypes.BUILDING_HMGOVCITY))
function PrivateCity(iPlayer)
 local pPlayer = Players[iPlayer]
 if (pPlayer:GetCivilizationType() == iCiv) then
  if (pPlayer:IsAlive()) then
   local intcount=-1
   for City in pPlayer:Cities() do
    local popchange=0
      --local unitdata=GameInfo.Units[unittype]


  
    if City:IsHasBuilding(GameInfoTypes.BUILDING_HMGOVCITY) then
     print("City of " .. City:GetName() .. " has BUILDING_HMGOVCITY")
     City:SetPuppet(false)
    else
     print("City of " .. City:GetName() .. " does NOT have BUILDING_HMGOVCITY")
     intcount=intcount+1
     City:SetPuppet(true)
     City:SetProductionAutomated(true);
     if City:GetPopulation()>citypop[intcount] then
      citypop[intcount]=City:GetPopulation()
      City:ChangeProduction(City:GetPopulation()*5)
      if pPlayer:IsHuman() then
       pPlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC,"You've recived a "..(City:GetPopulation()*5).." production bonus in the private city of "..City:GetName(),"Production Bonus!", -1);
      end
     end
    end
   end
  end
 end
end
This alteration of the code not only causes the game to print the Building ID# into the game's lua log, but it also prints debugging confirmation that the line

if City:IsHasBuilding(GameInfoTypes.BUILDING_HMGOVCITY) then

has been evaluated in the way expected, and it also fixes the method to use boolean values as the method requires. When the lua wiki documentation says boolean, it means boolean for lua.

'1' and '0' will not be evaluated within lua 5.1 to "true" and "false".
 
I'm currently trying to get one of my Civs to have a UA similar to that used in the Pridelands Civ, except in this case, it is supposed to spawn Great Scientists instead of Great Musicians, but I seem to be missing something in my .Lua to prevent it from working. Here's the code in question:
Code:
local CortexCiv = GameInfoTypes.CIVILIZATION_HK_DR_CORTEXS_ANIMAL_EMPIRE--Civ ID;
local GscienceID = GameInfoTypes.SPECIALIST_SCIENTIST

AnimalTab = {}
AnimalTab[GameInfoTypes.RESOURCE_BISON] = true
AnimalTab[GameInfoTypes.RESOURCE_COW] = true
AnimalTab[GameInfoTypes.RESOURCE_DEER] = true
AnimalTab[GameInfoTypes.RESOURCE_FUR] = true
AnimalTab[GameInfoTypes.RESOURCE_HORSE] = true
AnimalTab[GameInfoTypes.RESOURCE_IVORY] = true
AnimalTab[GameInfoTypes.RESOURCE_SHEEP] = true
AnimalTab[GameInfoTypes.RESOURCE_TRUFFLES] = true

GameEvents.PlayerDoTurn.Add(function(iPlayer)
        if Players[iPlayer]:GetCivilizationType() == CortexCiv then
                ScienceBoost = 0;
                local TeamID =  Players[iPlayer]:GetTeam();
                    for i = 0, iCity:GetNumCityPlots() -1 do
                            if iCity:GetCityIndexPlot(i) ~= nil then
                                    local iPlot = iCity:GetCityIndexPlot(i);
                                    if iCity:IsWorkingPlot(iPlot) then
                                            local sRes = iPlot:GetResourceType(TeamID);
                                            if sRes ~= -1 then
                                                    if IsScienceRes(sRes) then
                                                            ScienceBoost = ScienceBoost + 1;
                                                    end
                                            end
                                    end
                            end
                    end
                if ScienceBoost > 0 then
                        local cCity = Players[iPlayer]:GetCapitalCity();
                          cCity:ChangeSpecialistGreatPersonProgressTimes100(GscienceID, (ScienceBoost * 100))
                        end
                end
end)

function IsScienceRes(sRes)
        for iRes, bool in pairs(AnimalTab) do
                if iRes == sRes then
                        return true;
                end
        end
        return false;
end
I've probably removed something important when I was stripping away the parts I didn't need. Any thoughts?
 
I'm currently trying to get one of my Civs to have a UA similar to that used in the Pridelands Civ, except in this case, it is supposed to spawn Great Scientists instead of Great Musicians, but I seem to be missing something in my .Lua to prevent it from working. Here's the code in question:
Code:
local CortexCiv = GameInfoTypes.CIVILIZATION_HK_DR_CORTEXS_ANIMAL_EMPIRE--Civ ID;
local GscienceID = GameInfoTypes.SPECIALIST_SCIENTIST

AnimalTab = {}
AnimalTab[GameInfoTypes.RESOURCE_BISON] = true
AnimalTab[GameInfoTypes.RESOURCE_COW] = true
AnimalTab[GameInfoTypes.RESOURCE_DEER] = true
AnimalTab[GameInfoTypes.RESOURCE_FUR] = true
AnimalTab[GameInfoTypes.RESOURCE_HORSE] = true
AnimalTab[GameInfoTypes.RESOURCE_IVORY] = true
AnimalTab[GameInfoTypes.RESOURCE_SHEEP] = true
AnimalTab[GameInfoTypes.RESOURCE_TRUFFLES] = true

GameEvents.PlayerDoTurn.Add(function(iPlayer)
        if Players[iPlayer]:GetCivilizationType() == CortexCiv then
                ScienceBoost = 0;
                local TeamID =  Players[iPlayer]:GetTeam();
                    for i = 0, iCity:GetNumCityPlots() -1 do
                            if iCity:GetCityIndexPlot(i) ~= nil then
                                    local iPlot = iCity:GetCityIndexPlot(i);
                                    if iCity:IsWorkingPlot(iPlot) then
                                            local sRes = iPlot:GetResourceType(TeamID);
                                            if sRes ~= -1 then
                                                    if IsScienceRes(sRes) then
                                                            ScienceBoost = ScienceBoost + 1;
                                                    end
                                            end
                                    end
                            end
                    end
                if ScienceBoost > 0 then
                        local cCity = Players[iPlayer]:GetCapitalCity();
                          cCity:ChangeSpecialistGreatPersonProgressTimes100(GscienceID, (ScienceBoost * 100))
                        end
                end
end)

function IsScienceRes(sRes)
        for iRes, bool in pairs(AnimalTab) do
                if iRes == sRes then
                        return true;
                end
        end
        return false;
end
I've probably removed something important when I was stripping away the parts I didn't need. Any thoughts?
Check the lua-logs (either in notepad or while the code is actually executing real time with Firaxis FireTuner (a run-time lua console).
This will throw an error: "for i = 0, iCity:GetNumCityPlots() -1 do"
Firstly, :GetNumCityPlots() requires a pointer object. Now, I'm assuming you are trying it with a City ID since your variable is called iCity (the i in iCity would stand for integer in that case, according to Hungarian Notation)
Secondly, this variable was never defined, meaning that you will get a NullPointerException in the logs!

The same goes for iCity:IsWorkingPlot(iPlot), iCity should be a pointer object, not an ID. iPlot should also be a pointer, and not an ID.
 
Ah, so I did delete something important then. I'll make another run-through of the code to see if I can find what I got rid of that I shouldn't have.
 
I tried using the tag CulturePerTechResearched tag in the Policies table to make a UA for one of my Civs, but that wound up not doing anything (I'm disappointed to find how many features that don't do anything Firaxis left in), so I tried making that with buildings instead. It worked, but as +1~+80 additional Culture per turn is quite powerful, especially over 330~500 turns, I decided to work that down to 0.25. BUT as the game won't recognize Culture in anything less than a 1.0 integer, I need an .Lua code that provides a Dummybuilding in the leader's Capital for every 4 technologies they've discovered (amounting to the much more sensible +20 Culture per turn by endgame). Naturally, also I need this code to work with multiple copies of the same leader.

If anyone would be willing to rig this up for me, I'd be very grateful.
 
Hi all,

I am trying to create a scenario involving only units (no cities at all) with the victory conditions of either eliminate all enemy units or elimination of a specific enemy unit (kind of like if you killed the enemy's general, the army disbands). I haven't touched lua before and after looking at some of the tutorials, I was still completely lost.

If there is a way to implement this through lua, I would like some guidance.
Thank you.
 
Hi all,

I am trying to create a scenario involving only units (no cities at all) with the victory conditions of either eliminate all enemy units or elimination of a specific enemy unit (kind of like if you killed the enemy's general, the army disbands). I haven't touched lua before and after looking at some of the tutorials, I was still completely lost.

If there is a way to implement this through lua, I would like some guidance.
Thank you.
Korea receives a trait in the "Samurai Invasion of Korea"-scenario which makes it so that it can never be eliminated from the game (meaning that the civ survives with no cities whatsoever!). Implementing this trait requires XML (or SQL if you prefer that) only!
(IIRC there is a bug though that if you try to find the World Congress with 0 cities the game will CTD, though I guess that won't be applicable in a scenario)
Now, I'm not sure how to make a player win a victory, though I guess that the scenario's might offer a solution to that

Regarding the specific 'General', you can just give it a special promotion (E.g. 'Almighty Commander - When this unit dies you lose the game'), and you detect its death using the UnitPrekill GameEvent. You'll still be able to read it's promotions, strength, etc. that way (just don't try to change any of those in that event since that will cause a CTD!). Once you know that the unit with the special promotion has died, push the victory for the other player.

You can use GetMilitaryMight to check the 'strength of the army', which will be 0 if you don't have any units left! (This is used in the 'Demographics' of the main game as well)

Here's some simple sample code (for a general idea):
Code:
function CheckMilitarySize(iPlayer)
    local pPlayer = Players[iPlayer];
    if pPlayer:GetMilitaryMight() == 0 then
     --push the victory condition for the other player here
   end
end

GameEvents.PlayerDoTurn.Add(CheckMilitarySize)

local iGeneralPromotion = GameInfoTypes.PROMOTION_IM_THE_ALLMIGHTY_COMMANDER;

function CheckGeneralDeath(iPlayer,iUnit)
     local pPlayer = Players[iPlayer];
     local pUnit = pPlayer:GetUnitByID(iUnit);
     if pUnit:IsHasPromotion(iGeneralPromotion) then
          --push the victory condition for the other player here
     end
end

GameEvents.UnitPrekill.Add(CheckGeneralDeath)

Personally, I think the best way to starting out with a new coding language is looking at applications of that language (in this case, at other mods or the Firaxis Scenarios!) and to check how certain things were achieved. Trying things out yourself also helps a lot too. (All of this is said from personal experience; Even though I'm not a lua-master (and will probably not become one soon), I'm getting better at it every day!)
 
I tried using the tag CulturePerTechResearched tag in the Policies table to make a UA for one of my Civs, but that wound up not doing anything (I'm disappointed to find how many features that don't do anything Firaxis left in), so I tried making that with buildings instead. It worked, but as +1~+80 additional Culture per turn is quite powerful, especially over 330~500 turns, I decided to work that down to 0.25. BUT as the game won't recognize Culture in anything less than a 1.0 integer, I need an .Lua code that provides a Dummybuilding in the leader's Capital for every 4 technologies they've discovered (amounting to the much more sensible +20 Culture per turn by endgame). Naturally, also I need this code to work with multiple copies of the same leader.

If anyone would be willing to rig this up for me, I'd be very grateful.
If you made it work for 1 dummy building per technology, then changing it to 1 dummy building for 4 techs shouldn't be that difficult:
Assuming that the amount of dummy buildings given to a specific city is equal to a value of how many techs a player has, you can divide that value by 4.
This way, instead of dividing the yield by 4 (which results in decimal numbers), you just give 4 times as less dummies, which is pretty much what you want. ;)
 
Thank you Troller0001, you are a life saver! I will try this out as soon as I can!
I have looked at scenarios but I can't find most of them :(:( since they are hidden in the most awkward places!

Regardless, thank you very much!
 
Thank you Troller0001, you are a life saver! I will try this out as soon as I can!
I have looked at scenarios but I can't find most of them :(:( since they are hidden in the most awkward places!

Regardless, thank you very much!
The location depends on the Scenario (since several of them came with the big G&K or BNW DLC).
Anyhow, this is the location of the Mongol Scenario (or well, for the lua for it at least, which is what's important for you): C:\Program Files (x86)\Steam\steamapps\common\Sid Meier's Civilization V\Assets\DLC\DLC_01. (this Scenario seems to be the most appropriate)
I've peeked a quick look into the lua and this is what I found (CivsAlive.lua):
Code:
function TestVictory()
    -- Game over?
    local iRemainingToDestroy, iTurnsRemaining = GetVictoryValues();
    if (iRemainingToDestroy < 1) then
        Game.SetWinner(Game.GetActiveTeam(), GameInfo.Victories["VICTORY_DOMINATION"].ID);
        GameEvents.GameCoreTestVictory.Remove(TestVictory);
    elseif (iTurnsRemaining < 1) then
        Game.SetGameState(GameplayGameStateTypes.GAMESTATE_OVER);
        GameEvents.GameCoreTestVictory.Remove(TestVictory);
    end
end
GameEvents.GameCoreTestVictory.Add(TestVictory);
Where you lose if you run out of time, and you win if you destroy a specific number of civs.

Good Luck ;)
 
Top Bottom