How to check if a civilian is in a city?

JFD

Kathigitarkh
Joined
Oct 19, 2010
Messages
9,132
Location
The Kingdom of New Zealand
I've had a go, but can't figure out how to check if a Worker is stationed in a city. A worker can't garrison, so I can't use GetGarrisonedUnit(), so I imagine I might need to check if the Worker is in the same plot as a city, but for that I'm unsure how to get it done. I'd appreciate some help on this. Thanks.

Also, I struggle to understand how to check if a specific civ has researched a specific tech/belongs to a specific team and I'm not able to find any existing examples on the forums.
 
Code:
for iUnit in Players[playerID]:Units() do
	if iUnit:GetUnitType() == GameInfoTypes.UNIT_WORKER then
		local iPlot = iUnit:GetPlot();
		if iPlot:GetPlotCity() ~= nil then
			[COLOR="YellowGreen"]--WHAT YOU WANT TO DO[/COLOR]

Code:
local pPlayer = Players[playerID];
local pTeam = Teams[pPlayer:GetTeam()];
	if	pTeam:IsHasTech(techID) then
pPlayer:GetTeam() is integer. IsHasTech requires Team from table (strange string if you want to print it).
 
Do you need to find if a specific worker is in any city (ie you're starting from a known worker unit), or if a city has a worker in it (ie you're starting from a known city), or just find any/all workers that are in a city (ie you're just starting with a known player).

The code above does the last, there are more direct/efficient ways to do either of the other two.

The first is pUnit:GetPlot():IsCity()

The second requires iterating the units in the city plot (with GetNumUnits() and GetUnit(iIndex)) after you've got the plot with pCity:Plot(), which will be faster than iterating all the player's units
 
I am not sure, but GetPlotCity() might work on every plot owned by city (just remembered about that).

If I am right, use < function plot:IsCity() > (should be working, though I have never used it):
Code:
for iUnit in Players[playerID]:Units() do
	if iUnit:GetUnitType() == GameInfoTypes.UNIT_WORKER then
		local iPlot = iUnit:GetPlot();
		if iPlot:IsCity() then
			[COLOR="YellowGreen"]--WHAT YOU WANT TO DO[/COLOR]

Sorry about that.
 
Code:
for iCity in Players[playerID]:Cities() do
	for i=0, iCity:Plot():GetNumUnits() - 1 do
		if iPlot:GetUnit(i):GetUnitType() == GameInfoTypes.UNIT_WORKER then
			[COLOR="Green"]--Change production in iCity[/COLOR]
Are you triggering it on PlayerDoTurn?
 
iCity in the Firaxis way of naming things would be a city ID, pCity would be a better name. Also you don't set iPlot (again should be pPlot) before using it within the loop

Code:
for pCity in Players[playerID]:Cities() do
  local pPlot = pCity:Plot()

  for i=0, pPlot():GetNumUnits() - 1 do
    if (pPlot:GetUnit(i):GetUnitType() == GameInfoTypes.UNIT_WORKER) then
      --Change production in pCity

      -- Unless you want to give a bonus for every worker in a city (players can always use a mod to change the stacking limits)
      break;
    end
  end
end
 
Do what whoward posted, I am tired today.

However, If you are using city:ChangeProduction() you will encounter similar situations:
<Example> Your city has 50/80 production, 25 production per turn, let's say your trait gives 10 production.
Next turn your city will have 85/80 needed production, but will not finish building/unit. It will need one extra turn.

Since, I have to fix it for my mod anyway, I would be able to send you whole code (probably not the most efficient, I am primitive programmer, but working and tested) by tomorrow, if you can wait.
 
Do what whoward posted, I am tired today.

However, If you are using city:ChangeProduction() you will encounter similar situations:
<Example> Your city has 50/80 production, 25 production per turn, let's say your trait gives 10 production.
Next turn your city will have 85/80 needed production, but will not finish building/unit. It will need one extra turn.

Since, I have to fix it for my mod anyway, I would be able to send you whole code (probably not the most efficient, I am primitive programmer, but working and tested) by tomorrow, if you can wait.

Yes, I can wait. I would appreciate it if you did that, thanks.
 
Ok, so I will made <Extra X production if worker is in city for Y civilization>. You will have to update X and Y only.

Have a nice day.
 
iCity in the Firaxis way of naming things would be a city ID, pCity would be a better name. Also you don't set iPlot (again should be pPlot) before using it within the loop

Code:
for pCity in Players[playerID]:Cities() do
  local pPlot = pCity:Plot()

  for i=0, pPlot():GetNumUnits() - 1 do
    if (pPlot:GetUnit(i):GetUnitType() == GameInfoTypes.UNIT_WORKER) then
      --Change production in pCity

      -- Unless you want to give a bonus for every worker in a city (players can always use a mod to change the stacking limits)
      break;
    end
  end
end

I'm unable to get it working. I have written the code as below and the logs keep returning the error: "Lenin Trait.lua:19: attempt to index local 'Players' (a number value)." Line 19 is "for pCity in Players[playerID]:Cities() do" (there is another part of the trait which is working fine, hence the line number.)

This is without trying to restrict it to the specific civ yet.

Code:
GameEvents.PlayerDoTurn.Add(function(iPlayer)
for pCity in Players[playerID]:Cities() do
  local pPlot = pCity:Plot()
  for i=0, pPlot():GetNumUnits() - 1 do
    if (pPlot:GetUnit(i):GetUnitType() == GameInfoTypes.UNIT_WORKER) then
      pCity:ChangeProduction(3)
      break;
    end
  end
end
end)

But I can simply wait for LastSword's full code. Thank you both for the help.
 
Code:
GameEvents.PlayerDoTurn.Add(function([B][COLOR="Red"]iPlayer[/COLOR][/B])
for pCity in Players[[B][COLOR="Red"]playerID[/COLOR][/B]]:Cities() do

Pick a naming convention and stick with it (unfortunately Firaxis don't follow this rule so it's not surprising copy/paste mistakes creep in everywhere)

The bits in red refer to the same thing, so should either both be iPlayer, or both be playerID (personally I would favour iPlayer, but Firaxis tend to use playerID)
 
Code:
JFDPrePlayerID = Game.GetActivePlayer();

GameEvents.PlayerDoTurn.Add(function(iPlayer)
local pPlayer = Players[JFDPrePlayerID];
	if pPlayer:GetCivilizationType() == [COLOR="Red"]GameInfoTypes.CIVILIZATION_KINGDOM_OF_JERUSALEM_LS_MOD[/COLOR] then
		for pCity in pPlayer:Cities() do
			local pPlot = pCity:Plot();
			for i = 0, pPlot:GetNumUnits() - 1 do
				if (pPlot:GetUnit(i):GetUnitType() == GameInfoTypes.UNIT_WORKER) then
					pCity:ChangeProduction([COLOR="red"]10[/COLOR]);
					break;
				end
			end
		end
	end
JFDPrePlayerID = iPlayer;
end)
Works perfectly :).
 
Back
Top Bottom