[GS] Modifying AI builder behavior

PurpleJulius

Chieftain
Joined
Jul 7, 2025
Messages
1
Hi, I’ve been using p0kiehl’s mod Truly Abundant Resources, which allows strategic resources to be harvested. It’s great, except I’ve noticed the AI will remove resources super often, which can be annoying (especially with city states). Does anyone know how one would go about modifying their behavior so certain resources won’t be harvested (or at least not often)? I’ve tried looking into it, but as someone who’s never done any modding before it’s a little intimidating haha. It seems like maybe I would have to do something with their prioritizations, am I on the right track? Any help is appreciated, thanks!
 
Fighting the AI is always a challenge. You have to get creative.

Create a dummy tech and make it an additional prereq for harvesting resources, but don't make it researchable. Then on the PlayerTurnActivated event, add or remove the tech as needed.

I'm guessing, but it sounds doable. Here's a list of the Lua events, objects, and methods.

➡️ Knowledge Base

There is a pPlayer.PlayerTechs:SetTech(), but I don't know the arguments for it. You'd need to scan through the existing files to find an example.
 
Last edited:
Found this: LeeS
LeeS said:
In lua however we can do
Code:
Player:GetTechs():SetTech(iTech, bHasTechState)
"iTech" integer is the Database Index number for the technology.
“bHasTechState” boolean is to set the status (true/false) as to whether the player keeps or gets the technology.

So
Code:
Players[63]:GetTechs():SetTech(GameInfo.Technologies["TECH_MILITARY_ENGINEERING"].Index, false)

The post is in reference to barbarians, which are player 63. You'd want to use the player interger provided by the PlayerTurnActivated event. So it would look something like...

Code:
function On_PlayerTurnActivated(iPlayer, bFirstTime)
	Players[iPlayer]:GetTechs():SetTech(GameInfo.Technologies["TECH_DUMMY_HARVEST"].Index, true);  -- true or false.
end
Events.PlayerTurnActivated.Add(On_PlayerTurnActivated);
 
That will give you per player per turn control over harvesting, but obviously you'll need to add some conditionals to control who and on what turns they are allowed to harvest. If you look in the knowledge base, you'll see there is a Player:IsMajor(). That will return a true or false, depending on if the player is a major or minor civ. City states are minor civs, so the following will prevent city states from ever harvesting.

Code:
function On_PlayerTurnActivated(iPlayer, bFirstTime)
	if Players[iPlayer]:IsMajor() then
		Players[iPlayer]:GetTechs():SetTech(GameInfo.Technologies["TECH_DUMMY_HARVEST"].Index, true);
	end
end
Events.PlayerTurnActivated.Add(On_PlayerTurnActivated);

The issue at this point, is when do you want to allow or disallow major civs to harvest. It takes the AI a turn or two to get their worker to the resource plot, and it might take more than one turn to harvest it. So harvesting needs to be allowed for a few turns at a time, but give it too much time and it will harvest everything too soon. You need more conditionals!

Looking in the knowledge base, I see a few events that might be related, so I ran a test to see which of those are triggered by harvesting a resource. The only one that did anything was Events.ResourceRemovedFromMap. That event provides the X and Y of the map plot, plus the type of the resource. I tried removing an iron resource and it gave me the X and Y as expected, but for some reason the type was nil.

Back to the knowledge base. There is a Map.GetPlotXY(). It takes 2 integers for the X and Y and returns the Plot object for that location. There is a Plot:GetOwner() which will then tell us who removed the resource. There is also a Game.GetCurrentGameTurn(). Now when a resource is removed, we can keep track of who removed it and on what turn. If you're using my WhysMod Template, then saving that data is easy!

Code:
function On_ResourceRemovedFromMap(iX, iY, iType)
	local pPlot = Map.GetPlotXY(iX, iY);
	local iOwner = pPlot:GetOwner();
	local iTurn = Game.GetCurrentGameTurn();

	-- WhysMod Template function.
	SetSave("player "..tostring(iOwner).." harvested resource", iTurn);

	-- no more harvesting.
	Players[iOwner]:GetTechs():SetTech(GameInfo.Technologies["TECH_DUMMY_HARVEST"].Index, false);
end
Events.ResourceRemovedFromMap.Add(On_ResourceRemovedFromMap);

Now the On_PlayerTurnActivated() function would look something like...

Code:
function On_PlayerTurnActivated(iPlayer, bFirstTime)
	if Players[iPlayer]:IsMajor() then

		-- WhysMod Template function.
		local iTurn = GetSave("player "..tostring(iPlayer).." harvested resource");

		-- can harvest again 25 turns later.
		if iTurn == nil or Game.GetCurrentGameTurn() > iTurn + 25 then
			Players[iPlayer]:GetTechs():SetTech(GameInfo.Technologies["TECH_DUMMY_HARVEST"].Index, true);
		end
	end
end
Events.PlayerTurnActivated.Add(On_PlayerTurnActivated);

I haven't tested this specifically, but it looks about right.
 
Last edited:
Oh darn! Looking at the base game XML, it appears resource harvesting only allows for a single prereq tech. That's a complication for this approach, but not a deal breaker. Create a dummy tech for each of the existing prereq techs (ie: TECH_HARVEST_WITH_POTTERY, TECH_HARVEST_WITH_MINING), then change the harvesting prereqs to the appropriate dummy techs. In the On_PlayerTurnActivated function, look to see if the player has the original prereq before adding the specific dummy tech. That should provide the same functionality, but it would be hardcoded to the existing prereqs.

Hardcoding it is fine, but I believe there is a way to solve that as well if it's important. It's just more steps.
 
Well I decided to keep looking into this and discovered some interesting things about SQL triggers, thanks to whoward69: Circumventing mod load order issues with database triggers. As a result, I now have this mod about 90% completed. I think I'll just go ahead and finish it up for you, then you can remix it if you like.

Now the question is, what are your thoughts on the specifics? Do you want minor civs to be able to harvest? That includes barbarians by default. How many turns should lapse before a civ can harvest again? Do you want the delay to apply to human players as well, or just the AI? Any additional thoughts on the delay conditions? Should it take into account the player's gold amount, or something else?
 
Is the OP still interested in this at all? 🧐

It doesn’t seem so.
 
Back
Top Bottom