C++/Lua Request Thread

Code:
local iYourTeam
local iYourCiv = GameInfoTypes.CIVILIZATION_yourCiv -- your civ
local iDramaTech = GameInfoTypes.TECH_DRAMA
local iGRratePlus40policy = GameInfoTypes.POLICY_GRratePlus40 -- dummy policy that uses GreatWriterRateModifier column
local pYourPlayer

local function onTeamTechResearched(iTeam, iTech, iChange)
	if iTech == iDramaTech and iTeam == iYourTeam then
		print('great writer rate before', pYourPlayer:GetGreatWriterRateModifier())
		pYourPlayer:SetNumFreePolicies(1)
		pYourPlayer:SetNumFreePolicies(0)
		pYourPlayer:SetHasPolicy(iGRratePlus40policy, true)
		local pCapitalCity = pYourPlayer:GetCapitalCity()
		pYourPlayer:InitUnit(GameInfoTypes.UNIT_WRITER, pCapitalCity:GetX(), pCapitalCity:GetY())
		GameEvents.TeamTechResearched.Remove( onTeamTechResearched )
		print('great writer rate after', pYourPlayer:GetGreatWriterRateModifier())
	end
end

for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
	local pPlayer = Players[iPlayer]
	if pPlayer:IsEverAlive() and pPlayer:GetCivilizationType() == iYourCiv then
		iYourTeam = pPlayer:GetTeam()
		pYourPlayer = pPlayer
		GameEvents.TeamTechResearched.Add( onTeamTechResearched )
        break
    end
end
 
Did it really work? I noticed and fixed a couple of typos. Now it should work. And I added 2 print commands that will tell you your great writer rate before and after drama is researched. To see lua log use live tuner or open lua.log in %USERPROFILE%\Documents\my games\Sid Meier's Civilization 5\Logs. Or you can use ingame editor to add to your city a building that generates great writer points and see the effect in the game.
 
Yeah I used the IGE to quickly test it out - the Great writer spawned, although as I said, no Idea if the bonus worked.

Thanks again for this, it is much appreciated. I'll test it out soon :D

Record Great Writer Progress
Click Next Turn
Record Great Writer Progress
 
@Harkodos,

I would use:
Code:
local iAmerica = GameInfoTypes.CIVILIZATION_AMERICA
local bTriggerGoldenAge = true
local bAddGoldenAgeProgressPoints = false
local iGoldenAgeProgressPointsToAdd = 100

local function OnCityCaptureComplete(iOldOwner, bIsCapital, iPlotX, iPlotY, iNewOwner, iOldPop, bConquest, iGreatWorkCount)
	local pNewOwner = Players[iNewOwner]
	if pNewOwner:GetCivilizationType() == iAmerica then
		local pCity = Map.GetPlot(iPlotX, iPlotY):GetPlotCity()
		if pCity ~= nil then
			if pCity:GetOriginalOwner() ~= iOldOwner then
				if bTriggerGoldenAge then
					pNewOwner:ChangeGoldenAgeTurns(pNewOwner:GetGoldenAgeLength())
				end
				if bAddGoldenAgeProgressPoints then
					pNewOwner:ChangeGoldenAgeProgressMeter(iGoldenAgeProgressPointsToAdd)
				end
			end
		end
	end
end

for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
	local pPlayer = Players[iPlayer]
	if pPlayer:IsEverAlive() and pPlayer:GetCivilizationType() == iAmerica then
		GameEvents.CityCaptureComplete.Add(OnCityCaptureComplete)
		break
	end
end
print("Golden Age Points from capturing conquered cities loaded to the end")
These new variables allow you to decide if:
  1. you want a golden age to be started (or extended) via variable bTriggerGoldenAge
    • note that the code does nothing to try to keep the Golden Age Points "Cost" of the next natural golden age from being increased.
  2. you want a to add points to the golden age progress meter via variable bAddGoldenAgeProgressPoints
    • You specify how many golden age progress points to add via variable iGoldenAgeProgressPointsToAdd
You can have both effects occuring at the same time. IE, you can both start a golden age and add points to the meter for the next naturally-occuring golden age.
Sorry it took me so long to provide feedback for this. I works wonderfully, thank you! I do like the options provided for having either Golden Age Points or just triggering a Golden Age outright. Very nice touch.

Now I have yet another matter with which I need resolving:

Like before, I have code that works for one player but not for multiple copies of the same player. This time however the code I'm using triggers when Declaring Friendship with another player. What's supposed to happen is that the other player receives a unique dummybuilding in their Capital which gives them differing effects. Here's the code in question: (which was kindly provided by qqqbbb)
Code:
local iAmerica = GameInfoTypes.CIVILIZATION_AMERICA
local 	iWashington
local 	pWashington
local iDummyBuilding = GameInfoTypes.BUILDING_AMERICA_FRIENDSHIP_DUMMYBUILDING

local function OnPlayerDoTurn(iPlayer)
	local pPlayer = Players[iPlayer]
	if pPlayer:IsAlive() and pPlayer:GetDoFCounter(iWashington) == 1 then
		local pTheirCapital = pPlayer:GetCapitalCity()
		pTheirCapital :SetNumRealBuilding(iDummyBuilding , 1)
	end
end

for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
	local pPlayer = Players[iPlayer]
	if pPlayer:GetCivilizationType() == iAmerica then
		iWashington = iPlayer
		pWashington = pPlayer
		GameEvents.PlayerDoTurn.Add ( OnPlayerDoTurn )
		break
	end
end
I'll also provide the rest of the code just to be safe.
 

Attachments

  • Harkodos' The Aku Empire (BNW).zip
    13.1 KB · Views: 21
Right now, iWashtington is set whenever the first Washington is found, meaning that Washington #2 will not give any effects. Though there might be better ways of solving this than the following method, this one works too:

Code:
local iAmerica = GameInfoTypes.CIVILIZATION_AMERICA
local 	tWashingtonIDs = {}
[S]local 	pWashington[/S]
local iDummyBuilding = GameInfoTypes.BUILDING_AMERICA_FRIENDSHIP_DUMMYBUILDING
local bWashingtonWasFound = false

local function OnPlayerDoTurn(iPlayer)
	local pPlayer = Players[iPlayer]
	if pPlayer:IsAlive() then
                for iWashington,_ in pairs(tWashingtonIDs) do --loop through our tWashingtonIDs table
                     if pPlayer:GetDoFCounter(iWashington) == 1 then	     
                          local pTheirCapital = pPlayer:GetCapitalCity()
		          pTheirCapital :SetNumRealBuilding(iDummyBuilding , 1)
                     end
                end
	end
end

for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
	local pPlayer = Players[iPlayer]
	if pPlayer:GetCivilizationType() == iAmerica then
		tWashingtonIDs[iPlayer] = iPlayer --store the ID of this Washington in the tWashingtonIDs-table
		[S]pWashington = pPlayer[/S] --we're never using pWashington, so there's no need for saving that pointer. And if we would ever need it, we can always derive it from iWashington
                bWashingtonWasFound = true
		[S]GameEvents.PlayerDoTurn.Add ( OnPlayerDoTurn )[/S]
		[S]break[/S]
	end
end

if bWashingtonWasFound then
     GameEvents.PlayerDoTurn.Add ( OnPlayerDoTurn )
end

With this, the building does not stack for multiple DoF's with multiple Washingtons; It'll always provide 1 Dummy Building if you have a DoF with one or more Washingtons (I don't know what the intentions of the dummy were, so I left it that way)


EDIT: I made a typo somewhere so if someone copied this already please use the version that is now visible
EDIT2: Some more changes were made in regards to whoward's comment below
 
PlayerDoTurn.Add needs taking outside the loop and only calling if you find a Washington (so you'll need a Boolean variable to track this), otherwise you install the event handler multiple times - which'll cause issues
 
Thanks for the correction Whoward! (Changes were made and posted in post #629)
 
Ok, so I've tested it again and basically the Great Writer spawns, which is good. But the bonus never kicks in, I've looked both in game and in the lua. Does VFS have to be set to true? It's false right now, maybe that is why?

Was I supposed to replace any parts of the code with anything?

For lua files VFS should be set to true only when you replace a vanilla lua file. Something must be wrong with your dummy policy.
 
whoward69's what ModBuddy setting for what file types tutorial

An lua file will also be set as VFS=true if the contents of the file is "included" within another lua file. (Or if the lua-file is a map-script, but not many of us deal in mapscripts).

-------------------------------------------------------------------

Also, will not this evaluate to "true" only on the turn before the DOF expires ?
Code:
if pPlayer:GetDoFCounter(iWashington) == 1 then
 
Also, will not this evaluate to "true" only on the turn before the DOF expires ?
Code:
if pPlayer:GetDoFCounter(iWashington) == 1 then

Nope, pPlayer:GetDoFCounter(iDoFCiv) returns the number of turns that pPlayer has had the DoF with iDoFCiv. (So if I sign a DoF in turn 10, running this function in turn 12 would return 2). I don't know if this number resets upon re-signing the DoF after it has expired (though I would assume it does).


--------------------

Annoying Firaxis' misleading names; this is not the first time that this has happened!
 
Ah, so like this:

Code:
<Column name="GreatWriterRateModifier" type="integer" default="0"/>

In the "CIV5Policies.xml" file then? Or is it in the trait xml for my mod?

Because I just put that code into the first one and it now doesn't let me use IGE...

It looks like you have no idea what you are doing. You should read some basic modding tutorial.
 
Right now, iWashtington is set whenever the first Washington is found, meaning that Washington #2 will not give any effects. Though there might be better ways of solving this than the following method, this one works too:

Code:
local iAmerica = GameInfoTypes.CIVILIZATION_AMERICA
local 	tWashingtonIDs = {}
[S]local 	pWashington[/S]
local iDummyBuilding = GameInfoTypes.BUILDING_AMERICA_FRIENDSHIP_DUMMYBUILDING
local bWashingtonWasFound = false

local function OnPlayerDoTurn(iPlayer)
	local pPlayer = Players[iPlayer]
	if pPlayer:IsAlive() then
                for iWashington,_ in pairs(tWashingtonIDs) do --loop through our tWashingtonIDs table
                     if pPlayer:GetDoFCounter(iWashington) == 1 then	     
                          local pTheirCapital = pPlayer:GetCapitalCity()
		          pTheirCapital :SetNumRealBuilding(iDummyBuilding , 1)
                     end
                end
	end
end

for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
	local pPlayer = Players[iPlayer]
	if pPlayer:GetCivilizationType() == iAmerica then
		tWashingtonIDs[iPlayer] = iPlayer --store the ID of this Washington in the tWashingtonIDs-table
		[S]pWashington = pPlayer[/S] --we're never using pWashington, so there's no need for saving that pointer. And if we would ever need it, we can always derive it from iWashington
                bWashingtonWasFound = true
		[S]GameEvents.PlayerDoTurn.Add ( OnPlayerDoTurn )[/S]
		[S]break[/S]
	end
end

if bWashingtonWasFound then
     GameEvents.PlayerDoTurn.Add ( OnPlayerDoTurn )
end

With this, the building does not stack for multiple DoF's with multiple Washingtons; It'll always provide 1 Dummy Building if you have a DoF with one or more Washingtons (I don't know what the intentions of the dummy were, so I left it that way)


EDIT: I made a typo somewhere so if someone copied this already please use the version that is now visible
EDIT2: Some more changes were made in regards to whoward's comment below
Hmmm. Let's argue for the sake of making it so multiple copies of the same Civ aren't redundant because their unique ability will only trigger for one of them, that instead the ability allows the Dummybuildings to stack for each copy of the Civ in play.

I plan to use this code for at least 2 different Civilizations. For the first Civ, multiple copies, especially if it's the only Civ in game is redundant from the start because their UA already makes the effects of the Dummybuilding moot (unless there's at least 1 different Civ, in which case they'll be hurting somethin' fierce), but for the second one I'd feel that their UA stacking repeatedly would be important. In either case, I don't want to half-a$$ it, so I'd like it if the Dummybuildings could indeed stack with one another for multiple Declarations of Friendship.
 
It looks like you have no idea what you are doing. You should read some basic modding tutorial.

I have no idea when it comes to Lua, and I've googled how to make a new policy and found nothing.

EDIT: Ok, so this is what I've put together (Based on this: http://forums.civfanatics.com/showthread.php?t=565625):

Code:
<Policies>
		<Row>
			<Type>POLICY_GRratePlus50</Type>
			<Description>Modifies the spawn rate of great writers</Description>
                        <GreatWriterRateModifier>50</GreatWriterRateModifier>
			<PortraitIndex>25</PortraitIndex>
			<IconAtlas>POLICY_ATLAS</IconAtlas>
			<IconAtlasAchieved>POLICY_A_ATLAS</IconAtlasAchieved>
		</Row>
	</Policies>

I've put this in both the trait xml and a new xml on its own, neither of them worked (In the new one, i loaded it into the properties as you would the leader or trait xml btw). What have I done wrong? I think I'm quite close to doing it. Oh and I changed the bonus from 40 to 50, hence the policy name - it wasn't an error :)
 
I have no idea when it comes to Lua, and I've googled how to make a new policy and found nothing.

EDIT: Ok, so this is what I've put together (Based on this: http://forums.civfanatics.com/showthread.php?t=565625):

Code:
<Policies>
		<Row>
			<Type>POLICY_GRratePlus50</Type>
			<Description>Modifies the spawn rate of great writers</Description>
			<PortraitIndex>25</PortraitIndex>
			<IconAtlas>POLICY_ATLAS</IconAtlas>
			<IconAtlasAchieved>POLICY_A_ATLAS</IconAtlasAchieved>
		</Row>
	</Policies>

I've put this in both the trait xml and a new xml on its own, neither of them worked (In the new one, i loaded it into the properties as you would the leader or trait xml btw). What have I done wrong? I think I'm quite close to doing it.
I believe I shall chime in for this one. I've programmed lots of Civs that require Policies at this point, so I should be good to help.

Make an .Lua file, name it whatever you like and use this code (which I've borrowed from some other Civilizations, most by OTiger, but seems to work wonders for me):
Code:
function NameOfYourCivilizationPolicyOpener(player)
	print("Thanks to JFD for this script")
	for playerID, player in pairs(Players) do
		local player = Players[playerID];
		if player:GetCivilizationType() == GameInfoTypes["CIVILIZATION_NAMEOFYOURCIVILIZATION"] then
			if not player:HasPolicy(GameInfoTypes["POLICY_GREAT_WRITER_UA"]) then
				-- player:SetPolicyBranchUnlocked(GameInfoTypes["POLICY_BRANCH_LIBERTY"], true)[COLOR="Blue"]This doesn't seem to do anything as-is, but I just usually leave it in just to be safe.[/COLOR]
				player:SetNumFreePolicies(1)
				player:SetNumFreePolicies(0)
				player:SetHasPolicy(GameInfoTypes["POLICY_GREAT_WRITER_UA"], true)	
			end
		end
	end 
end
Events.SequenceGameInitComplete.Add(NameOfYourCivilizationPolicyOpener)
Then create an .XML document and use this code:
Code:
        <Policies>
		<Row>
			<Type>POLICY_GREAT_WRITER_UA</Type>
			<Description>TXT_KEY_POLICY_GREAT_WRITER_UA_DESC</Description>
			<GreatWriterRateModifier>40</GreatWriterRateModifier>
		</Row>
	</Policies>
	<Language_en_US>
		<Row Tag="TXT_KEY_POLICY_GREAT_WRITER_UA_DESC">
			<Text>Great Writer Spawn Modifier</Text>
		</Row>
	</Language_en_US>
Then you can simply trigger a Great Writer spawning upon the discovery of a Tech in the Traits Table.
Example:
Code:
        <Traits>
                <Row>
			<Type>TRAIT_GREAT_WRITER</Type>
			<Description>TXT_KEY_TRAIT_GREAT_WRITER_DESC</Description>
			<ShortDescription>TXT_KEY_TRAIT_GREAT_WRITER_SHORT</ShortDescription>
			<FreeUnit>UNITCLASS_WRITER</FreeUnit>
			<FreeUnitPrereqTech>TECH_DRAMA</FreeUnitPrereqTech>
			<PrereqTech>TECH_DRAMA</PrereqTech>
		</Row>
        </Traits>
        <Language_en_US>
		<Row Tag="TXT_KEY_TRAIT_GREAT_WRITER_DESC">
			<Text>[COLOR="Blue"]Use whatever text you like here to describe your Civilization's UA.[/COLOR]</Text>
		</Row>
		<Row Tag="TXT_KEY_TRAIT_GREAT_WRITER_SHORT">
			<Text>Great Writer UA Name</Text>
		</Row>
	</Language_en_US>
The +1 Culture from Farms can also be done in the Traits table in .XML.
Behold:
Code:
        <Trait_ImprovementYieldChanges>
		<Row>
			<TraitType>TRAIT_GREAT_WRITER</TraitType>
			<ImprovementType>IMPROVEMENT_FARM</ImprovementType>
			<YieldType>YIELD_CULTURE</YieldType>
			<Yield>1</Yield>
		</Row>
	</Trait_ImprovementYieldChanges>
That should just about do what you want. Hope that's helpful.
 
Spoiler :
Okay this might be my bad for not conveying it well enough. Change this:
Code:
        <Policies>
		<Row>
			<Type>POLICY_GREAT_WRITER_UA</Type>
			<Description>TXT_KEY_POLICY_GREAT_WRITER_UA_DESC</Description>
			<GreatWriterRateModifier>50</GreatWriterRateModifier>
		</Row>
	</Policies>
	<Language_en_US>
		<Row Tag="TXT_KEY_POLICY_GREAT_WRITER_UA_DESC">
			<Text>Great Writer Spawn Modifier</Text>
		</Row>
	</Language_en_US>
To this:
Code:
        <Policies>
		<Row>
			<Type>POLICY_GRratePlus50</Type>
			<Description>TXT_KEY_POLICY_GRratePlus50_DESC</Description>
			<GreatWriterRateModifier>50</GreatWriterRateModifier>
		</Row>
	</Policies>
	<Language_en_US>
		<Row Tag="TXT_KEY_POLICY_GRratePlus50_DESC">
			<Text>Great Writer Spawn Modifier</Text>
		</Row>
	</Language_en_US>
That should do it. Sorry, guess I figured you'd be able to pick up on what to name your Policy.
-[EDIT]- Disregard everything in the Spoiler.

I found out your problem. Turns out you forgot to set the .Lua file as an InGameUIAddin in the Properties Tab. Do that and it should work.
 
I utilised the "get an extra X unit when you build that unit" lua that LeeS kindly put together for me, with a slight problem...whenever, for example, a slinger is built, it builds the duplicate slinger...great so far...except the duplicate slinger builds another, then another and within a second, the map is filled with slingers! Any way to make it build one duplicate of itself?

Code:
-- LusitaniUA
-- Author: LeeS
-- DateCreated: 8/26/2016 12:38:30 PM
--------------------------------------------------------------
local iRequiredCivilization = GameInfoTypes.CIVILIZATION_LUSITANI
local tUnitsToDuplicate = { [GameInfoTypes.UNIT_SLINGER] = GameInfoTypes.UNIT_SLINGER, [GameInfoTypes.UNIT_HEAVY_SLINGER] = GameInfoTypes.UNIT_HEAVY_SLINGER, [GameInfoTypes.UNIT_IBERIAN_SLINGER] = GameInfoTypes.UNIT_IBERIAN_SLINGER }

function DuplicateUnitsToBeSpawned(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
	local pPlayer = Players[playerID]
	local pUnit = pPlayer:GetUnitByID(unitID)
	if(pPlayer == nil or
		not pPlayer:IsAlive() or
		pUnit == nil or
		pUnit:IsDead()) then
		return
	end
	if pPlayer:GetCivilizationType() ~= iRequiredCivilization then return end
	if tUnitsToDuplicate[pUnit:GetUnitType()] then
		local pNewUnit = pPlayer:InitUnit(tUnitsToDuplicate[pUnit:GetUnitType()], pUnit:GetX(), pUnit:GetY())
		pNewUnit:JumpToNearestValidPlot()
	end
end
LuaEvents.SerialEventUnitCreatedGood.Add(DuplicateUnitsToBeSpawned)
 
Code:
-- LusitaniUA
-- Author: LeeS
-- DateCreated: 8/26/2016 12:38:30 PM
--------------------------------------------------------------
local iRequiredCivilization = GameInfoTypes.CIVILIZATION_LUSITANI
local tUnitsToDuplicate = { [GameInfoTypes.UNIT_SLINGER] = GameInfoTypes.UNIT_SLINGER, [GameInfoTypes.UNIT_HEAVY_SLINGER] = GameInfoTypes.UNIT_HEAVY_SLINGER, [GameInfoTypes.UNIT_IBERIAN_SLINGER] = GameInfoTypes.UNIT_IBERIAN_SLINGER }

[B][COLOR="red"]local noReentry = false[/COLOR][/B]

function DuplicateUnitsToBeSpawned(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
	local pPlayer = Players[playerID]
	local pUnit = pPlayer:GetUnitByID(unitID)
	if(pPlayer == nil or
		not pPlayer:IsAlive() or
		pUnit == nil or
		pUnit:IsDead()) then
		return
	end
	if pPlayer:GetCivilizationType() ~= iRequiredCivilization then return end

	[B][COLOR="red"]if noReentry return
	noReentry = true[/COLOR][/B]

	if tUnitsToDuplicate[pUnit:GetUnitType()] then
		local pNewUnit = pPlayer:InitUnit(tUnitsToDuplicate[pUnit:GetUnitType()], pUnit:GetX(), pUnit:GetY())
		pNewUnit:JumpToNearestValidPlot()
	end

	[B][COLOR="Red"]noReentry = false[/COLOR][/B]
end
LuaEvents.SerialEventUnitCreatedGood.Add(DuplicateUnitsToBeSpawned)
 
Oops. Sorry, Rob. I didn't think of that problem. I should have, tho, since I ran into that very issue a couple of times when experimenting with the early versions of Great General Names.

I may have to run the non-William version just for the lols, tho.

But I think it needs to be:
Code:
-- LusitaniUA
-- Author: LeeS
-- DateCreated: 8/26/2016 12:38:30 PM
--------------------------------------------------------------
local iRequiredCivilization = GameInfoTypes.CIVILIZATION_LUSITANI
local tUnitsToDuplicate = { [GameInfoTypes.UNIT_SLINGER] = GameInfoTypes.UNIT_SLINGER, [GameInfoTypes.UNIT_HEAVY_SLINGER] = GameInfoTypes.UNIT_HEAVY_SLINGER, [GameInfoTypes.UNIT_IBERIAN_SLINGER] = GameInfoTypes.UNIT_IBERIAN_SLINGER }

[COLOR="Red"]local noReentry = false[/COLOR]

function DuplicateUnitsToBeSpawned(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
	local pPlayer = Players[playerID]
	local pUnit = pPlayer:GetUnitByID(unitID)
	if(pPlayer == nil or
		not pPlayer:IsAlive() or
		pUnit == nil or
		pUnit:IsDead()) then
		return
	end
	if pPlayer:GetCivilizationType() ~= iRequiredCivilization then return end


	if tUnitsToDuplicate[pUnit:GetUnitType()] then
		[COLOR="red"]if noReentry then
			noReentry = false
			return
		end
		noReentry = true[/COLOR]
		local pNewUnit = pPlayer:InitUnit(tUnitsToDuplicate[pUnit:GetUnitType()], pUnit:GetX(), pUnit:GetY())
		pNewUnit:JumpToNearestValidPlot()
		[COLOR="Red"]return[/COLOR]
	end
	[COLOR="red"]noReentry = false[/COLOR]

end
LuaEvents.SerialEventUnitCreatedGood.Add(DuplicateUnitsToBeSpawned)
 
Yours will work fine until you duplicate the InitUnit() method in the final if block, but the typical pattern for non-entry is as I gave
 
Top Bottom