How Would I Code This Lua

(Just want to warn you that this is the first of what will probably dozens of questions.)

I've worked a bit and come up with this:
Code:
function RiverOfBlood()
	local user = Game.GetActivePlayer()
	for city in player:Cities() do
			local city = playerCap:GetPopulation()
			if cityPop >= 3 then
				city:SetPopulation((playerPop - 2), true)
			elseif cityPop == 2 then
				city:SetPopulation((playerPop - 1), true)
			end
    end

        for i = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
           local pPlayer = Players[i]
           if pPlayer:IsEverAlive() then
           pPlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, "A player has cast River of Blood, increasing the population of their cities and decreasing the population of all others!", "A player has cast River of Blood!")
           end
        end
end
Firstly, where do I add the civ requirement? (I just noticed the irony - I randomly chose Egypt as an example for a 'River of Blood' spell. ;)) Next, how do I trigger a lua code in Firetuner? Lastly (for now) at what words do I need to put an 'end'? I know I have to do it for each 'if'.
 
Firstly, where do I add the civ requirement? (I just noticed the irony - I randomly chose Egypt as an example for a 'River of Blood' spell. ;)) Next, how do I trigger a lua code in Firetuner? Lastly (for now) at what words do I need to put an 'end'? I know I have to do it for each 'if'.

This will help you a lot with minor mistakes.

Code:
if	user:GetCivilizationType() == GameInfoTypes["CIVILIZATION_EGYPT"] then
 
This will help you a lot with minor mistakes.

Code:
if	user:GetCivilizationType() == GameInfoTypes["CIVILIZATION_EGYPT"] then

Code:
function RiverOfBlood()
	local user = Game.GetActivePlayer()
	    if	user:GetCivilizationType() == GameInfoTypes["CIVILIZATION_EGYPT"] then
	for city in player:Cities() do
			local city = playerCap:GetPopulation()
			if cityPop >= 3 then
				city:SetPopulation((playerPop - 2), true)
			elseif cityPop == 2 then
				city:SetPopulation((playerPop - 1), true)
			end
		end
    end

        for i = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
           local pPlayer = Players[i]
           if pPlayer:IsEverAlive() then
           pPlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, "A player has cast River of Blood, increasing the population of their cities and decreasing the population of all others!", "A player has cast River of Blood!")
           end
        end
end

Did I put the Egypt part in the right place?
I clicked on the link and looked at those functions and I still don't don't know how to trigger a function with Firetuner.
 
Straighten out your indenting. The computer doesn't care, but it will help you understand the program and where to put ends. It's always:

Code:
function FunctionName(args)
	--indent code because it is all within the "function" block
end
Code:
if [I]something[/I] then
	--indent code because it is all within the "if" block
elseif [I]something else[/I] then
	--indent code because it is all within the "elseif" block
else
	--indent code because it is all within the "else" block
end

--The elseif and else blocks above are optional
Code:
for [I]something [/I]do
	--indent code because it is all within the "for" block
end
Code:
while [I]something [/I]do
	--indent code because it is all within the "while" block
end
There are others that I can't think of now...

By the way, this is why learning any programming language opens up all programs for you. The logic is very similar and the differences are mostly just a few rules. In C++ those blocks above would be contained between "{" and "}" without any "then" or "do" or "end", and the somethings would be in parentheses.

You're still not looking at your code for the meaning of the words. You have "player". This is a variable name. But you have never told the computer what to put in that variable. (I gave some examples above for calling this function with iPlayer as argument, and using that integer to assign player object to a variable called "player".)

Code:
	for city in player:Cities() do
			local city = playerCap:GetPopulation()
			if cityPop >= 3 then
Again, stop copying and pasting. It will take you 1000000 years to write a program that way. The for loop is running once for every city owned by player. "city" is the variable that holds the city object. In the next line, you want to get the population of that city. Don't call that value "city"! Call it "cityPopulation". So line two is:
Code:
local cityPopulation = city:GetPopulation()
LOOK AT THAT AND UNDERSTAND IT!!! Don't just copy it! (sorry for hyperventalating there -- just trying to help ;))
The next line needs to use the variable name that you used in line 2.
 
You're still not looking at your code for the meaning of the words. You have "player". This is a variable name. But you have never told the computer what to put in that variable. (I gave some examples above for calling this function with iPlayer as argument, and using that integer to assign player object to a variable called "player".)

Code:
	for city in player:Cities() do
			local city = playerCap:GetPopulation()
			if cityPop >= 3 then
Again, stop copying and pasting. It will take you 1000000 years to write a program that way. The for loop is running once for every city owned by player. "city" is the variable that holds the city object. In the next line, you want to get the population of that city. Don't call that value "city"! Call it "cityPopulation". So line two is:
Code:
local cityPopulation = city:GetPopulation()
LOOK AT THAT AND UNDERSTAND IT!!! Don't just copy it! (sorry for hyperventalating there -- just trying to help ;))

I put city there bec. you told me to in the last post on page 1. I'm not just copying, I'm trying to figure things out but it's really hard:cry:
Pazyryk seems to be offline, so could someone else criticize my (hopefully) improved code?
Code:
function RiverOfBlood()
	local player = Players[iPlayer]
	if	iPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_EGYPT"] then
	    for city in iPlayer:Cities() do
	        local cityPopulation = city:GetPopulation()
			if cityPopulation >= 3 then
				cityPopulation:SetPopulation((playerPop - 2), true)
			    elseif cityPopulation == 2 then
				    city:SetPopulation((playerPop - 1), true)
				end
			end
		end
    end

        for i = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
           local pPlayer = Players[i]
           if pPlayer:IsEverAlive() then
               pPlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, "A player has cast River of Blood, increasing the population of their cities and decreasing the population of all others!", "A player has cast River of Blood!")
           end
        end
end
bane_, I downloaded Notebook and its a big help for formatting. Thanks;)
And could someone please tell me how to trigger the code in Firetuner so I can test the codes on my ownand not have to post every time I want to know if it'll work?
 
Getting closer...

Code:
function RiverOfBlood()
	local player = Players[iPlayer]
	if	iPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_EGYPT"] then
	    for city in iPlayer:Cities() do

iPlayer is never defined here. Line #2 cannot work because iPlayer has no value. Line #2 expects iPlayer to have an integer value.

Assuming you add code to give iPlayer an integer value, then these two methods won't work:
Code:
iPlayer:GetCivilizationType()
iPlayer:Cities()
Don't ever try to use methods on an integer. And don't ever use a name like "iSomething" unless the variable contains an integer. It should be player there instead of iPlayer.

You also need to iterate through all players. The code bane_ gave you iterated over city states only. But you dropped that so you aren't iterating over any players anymore.

To iterate through all major players, use:
Code:
for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
	local player = Players[iPlayer]
	if player and player:IsAlive() then
		--code
	end
end
To iterate through all civs including both major and minor civs (and barbs), use MAX_CIV_PLAYERS instead of MAX_MAJOR_CIVS in the code above.

Note that all variable are defined! The value if iPlayer is set in the for loop. The value of player is set in line #2. Line #3 makes sure that the player exists and that they are alive. What you should do inside this loop is test if iPlayer is Egypt with an "if - else - end" logic. If the player is Egypt, add 2 pop. Else, remove two (testing to make sure they are big enoug, which bane_ was doing correctly)


You would call this function from the Fire Tuner the same way you will from your mod code:
Code:
RiverOfBlood()


Also: Hate to nag, but your indenting is still messed up. The computer doesn't care. But it makes it a lot harder for me to spot errors.
 
Getting closer...

Code:
function RiverOfBlood()
	local player = Players[iPlayer]
	if	iPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_EGYPT"] then
	    for city in iPlayer:Cities() do

iPlayer is never defined here. Line #2 cannot work because iPlayer has no value. Line #2 expects iPlayer to have an integer value.

Assuming you add code to give iPlayer an integer value, then these two methods won't work:
Code:
iPlayer:GetCivilizationType()
iPlayer:Cities()
Don't ever try to use methods on an integer. And don't ever use a name like "iSomething" unless the variable contains an integer. It should be player there instead of iPlayer.

You also need to iterate through all players. The code bane_ gave you iterated over city states only. But you dropped that so you aren't iterating over any players anymore.

To iterate through all major players, use:
Code:
for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
	local player = Players[iPlayer]
	if player and player:IsAlive() then
		--code
	end
end
To iterate through all civs including both major and minor civs (and barbs), use MAX_CIV_PLAYERS instead of MAX_MAJOR_CIVS in the code above.

Note that all variable are defined! The value if iPlayer is set in the for loop. The value of player is set in line #2. Line #3 makes sure that the player exists and that they are alive. What you should do inside this loop is test if iPlayer is Egypt with an "if - else - end" logic. If the player is Egypt, add 2 pop. Else, remove two (testing to make sure they are big enoug, which bane_ was doing correctly)


You would call this function from the Fire Tuner the same way you will from your mod code:
Code:
RiverOfBlood()


Also: Hate to nag, but your indenting is still messed up. The computer doesn't care. But it makes it a lot harder for me to spot errors.

Pazyzrk, where did you learn programming?
 
I think you are still struggling with some basic concepts like what is a variable and what is a function. I wish I knew a good tutorial level reference for Lua. The link I provided above is where I learned Lua. I suggest you just sit down and read the first 5 chapters. You won't understand all of it, but hopefully 50% of it. Then try some simple code like:

Code:
print("loading my code...")
function RiverOfBlood()
 	print ("someone called function RiverOfBlood")
end

If that works and you can see the output from both print statements, then you are ready to make this function actually do something.
 
I think you are still struggling with some basic concepts like what is a variable and what is a function. I wish I knew a good tutorial level reference for Lua. The link I provided above is where I learned Lua. I suggest you just sit down and read the first 5 chapters. You won't understand all of it, but hopefully 50% of it. Then try some simple code like:

Code:
print("loading my code...")
function RiverOfBlood()
 	print ("someone called function RiverOfBlood")
end

If that works and you can see the output from both print statements, then you are ready to make this function actually do something.

I have begun studying it, but I see it is Version 2.3, and the current version is 5. something. Does this matter?
 
Back
Top Bottom