Give Tech to Civ on specific turn

Formulapower

Warlord
Joined
Nov 5, 2007
Messages
148
I am trying to give a single civ a specific tech on a specific turn. I have tried everything I can think of but still get nothing to work. Can any one advise/help?
 
Code:
GameEvents.PlayerDoTurn.Add(
function(iPlayer)
	local pPlayer = Players[iPlayer]
	if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_CIVNAMEGOESHERE) then
		if (Game.GetGameTurn() == x) then
			Teams[pPlayer:GetTeam()]:SetHasTech(GameInfoTypes.TECH_TECHNAMEGOESHERE, true)
		end
	end
end)
Insert the correct names of the civilization and tech type into the code and replace x with a positive integer value. Done.
 
Note that AW's code will not take into account / handle advanced starts. This is because advanced starts don't start you off at turn 0, and that code will only fire on the one turn it passes whatever 'x' is.

If you will only be giving an early tech such that any advanced start would already provide the tech, then there shouldn't be any issue. However, if you were intending to give a later tech on a specific turn early on, then you can change the "==" to ">=", although then it would fire every turn thereafter.

If you were intending instead to provide the tech on a specific number of turns after game start (no matter the starting point) then you can use Game.GetElapsedGameTurns() instead of Game.GetGameTurn().
 
although then it would fire every turn thereafter.

You can solve this by putting this line in:
GameEvents.PlayerDoTurn.Remove(functionname)

And putting a name on this function, like this:

Code:
function CustomFunction(iPlayer)
	local pPlayer = Players[iPlayer]
	if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_CIVNAMEGOESHERE) then
		if (Game.GetGameTurn() == x) then
			Teams[pPlayer:GetTeam()]:SetHasTech(GameInfoTypes.TECH_TECHNAMEGOESHERE, true)
		end
	end
	GameEvents.PlayerDoTurn.Remove(CustomFunction)
end
GameEvents.PlayerDoTurn.Add(CustomFunction)

It is not save-game friendly though.
 
The problem is that not only would it not be savegame friendly, it would also only fire for the first player that matches that particular Civ, meaning any other players also playing that Civ (AI or otherwise) would not get the tech for free, since the function has been removed by the time PlayerDoTurn runs their functions.
 
Or, instead of removing the function, couldn't you simply add in a global variable check?
Code:
[COLOR="blue"][B]bTechGiven = false[/B][/COLOR]
GameEvents.PlayerDoTurn.Add(
function(iPlayer)
	local pPlayer = Players[iPlayer]
	if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_CIVNAMEGOESHERE) then
		if (Game.GetGameTurn() == x) [COLOR="blue"][B]and not bTechGiven[/B][/COLOR] then
			Teams[pPlayer:GetTeam()]:SetHasTech(GameInfoTypes.TECH_TECHNAMEGOESHERE, true)
			[COLOR="Blue"][B]bTechGiven = true[/B][/COLOR]
		end
	end
end)
Or would that global variable reassignment still take effect for all players?
 
The way you have it set as a global, it would only fire once for the first player, at least until the script is reloaded. Setting a variable check can work if it's set inside the function though, as then each time the function runs it resets the counter.

However, doing it this way is superfluous because the game will still have to check each turn whether the player already has the tech or not (and if it does, it shouldn't do anything anyway.) Ideally you want to save the fact that the player has received the tech, but that goes into persistent data territory, and I'm not sure the OP wants to go that route.

There is one last thing you could do that would be a compromise between yours and bane_'s codes:
The function (which has to be named, and not anonymous) will run either on a specific turn, or after a number of elapsed turns, depending on the need of the OP. However, there will be an additional elseif clause which checks whether or not "Game.GetGameTurn() > x" or "Game.GetElapsedGameTurns() > x", and if it is, then do the GameEvents.PlayerDoTurn.Remove(FunctionName) line.

This would allow the code to continue running for all instances of the Civ on the specific turn it needs to run, then on the next turn, it will find that the turn count has passed, and remove itself. This should be fine because OP's intention appears to be to give his Civ the specific tech on a specific turn, so every instance of his Civ should be eligible for the tech at the same time/turn.

Edit:
With all that said, although I would prefer this code that would only run when necessary and not otherwise, I don't think one extra small PlayerDoTurn function of this size running every turn would be all that much overhead.
 
And also something to consider = Player's chosen game speed: Quick, Standard, Epic, Marathon.

Game.GetGameTurn() and I'm assuming Game.GetElapsedGameTurns() are not adjusted based on a player's chosen game speed.

So unless something is done within the function to compensate for Player's chosen game speed, all those extra (or fewer in the casse of Quick) turns would be tacked on to the end of the normal number of turns that occur in Standard speed. This paragraph is my clumbsy way of trying to say that on a game that only has 330 turns, you'd never get the function to run if the selected turn number were turn # 350. If the selected turn numer were turn #100, that would be one-fifth of the way through a Standard-Speed game, but only one-fifteenth of the way through a Marathon-Speed game.
 
Turn counters are never "adjusted" for game speed; turn 1 is turn 1.
However, what you are trying to say is that a specific turn number may not mean the same thing as a percentage of game played in terms of how useful such a freebie is.

Without knowing more information from the OP, it's impossible to say which method is a better approach, but it definitely is something to think about -- whether you want something to be given specifically at, say, turn 50, or specifically once "10% of the game's turns have elapsed."
 
The problem is that not only would it not be savegame friendly, it would also only fire for the first player that matches that particular Civ, meaning any other players also playing that Civ (AI or otherwise) would not get the tech for free, since the function has been removed by the time PlayerDoTurn runs their functions.

I thought that was the idea. :blush: (this new blush is terrible. :\)
 
Thanks for all the info. I will try applying this info as soon as I get some time.

To clarify a couple things, this is for a mod that is a specific map/scenario so there will be only one game speed and I want the this to happen both when the specific civ is player or AI controlled.
 
Back
Top Bottom