Giving techs & research points with LUA

DragonBlood87

Chieftain
Joined
Jan 3, 2009
Messages
82
Location
Georgia, U.S.A.
Does anyone know how (or even if it is possible) to give a disabled tech to a player through LUA? Or research points towards a disabled tech?

I've tried to work it out on my own, but I'm not having much luck. I've come to the conclusion that you apparently need to enable the tech for the player before you can give it to them, but I just can't figure out a method of doing so... and even if there was a way, it looks like it would enable it for everyone else, too.

I would have loved to use this as a way to block techs until criteria were met (e.g., have to get iron before you can get Iron Working, or something similar). :(
 
Does anyone know how (or even if it is possible) to give a disabled tech to a player through LUA?

Yes, you can, exactly the same way you'd give any other tech. My mod does exactly that, when a civ builds the spaceship they get a special disabled tech (instead of the game ending). Disabled techs can't be acquired through normal research, research agreements, or "free tech" policies/wonders/great scientists, but you can give them through Lua just fine.
 
Yes, you can, exactly the same way you'd give any other tech. My mod does exactly that, when a civ builds the spaceship they get a special disabled tech (instead of the game ending). Disabled techs can't be acquired through normal research, research agreements, or "free tech" policies/wonders/great scientists, but you can give them through Lua just fine.
Well, I guess I'll just have to fiddle with it some more then; I must have been doing something wrong last night (understandable since it was so late at night when I started trying).
 
I made a test script to give the human player Optics as a test, but I can't get it working. Can anyone spot what's wrong with it?

Spoiler :
Code:
function Test()
	local aPlayer = Players[Game.GetActivePlayer()]

	if aPlayer:IsHuman() then
		print("Player is human.")
		
		local aTeam = Teams[aPlayer:GetTeam()]
		
		if not aTeam:GetTeamTechs():HasTech(12) then
			print("Giving tech.")
			aTeam:SetHasTech(12, true)
		else
			print("Tech already given.")
		end
	else
		print("Player is not human.")
	end
end

Events.ActivePlayerTurnStart.Add( Test )

I've tested each part in FireTuner, and everything works in there... but the script won't execute itself (the prints never even show up in FireTuner), and I'm stumped at this point.

I think what I really need is a basic guide for Lua modding that is specific to how you would do non-UI scripts in Civ 5, but everything I'm finding is either general Lua information (which doesn't always help much in figuring out how to do things for Civ 5, like hooking into events) or is about UI modding. =/
 
I made a test script to give the human player Optics as a test, but I can't get it working. Can anyone spot what's wrong with it?

A couple things.

First of all, nitpick, but there's no reason to test ActivePlayer AND IsHuman, because they mean the same thing. The "Active Player" means the person whose machine is hosting the game, which automatically rules out the AIs, Barbarians, etc. Active Player doesn't mean the same thing as Current Player.

Second, this part:
Code:
if not aTeam:GetTeamTechs():HasTech(12) then
			print("Giving tech.")
			aTeam:SetHasTech(12, true)

That IF is broken; you can't have two colons like that. So you'd need to split it to
Code:
aTechs = aTeam:GetTeamTechs()
if not aTechs:HasTech(12) then
to do what you'd intended there. But there's no need to screw around with the TeamTechs block at all, because the Teams block already has an IsHasTech function that duplicates that particular function (handy, huh?). So just do
Code:
if( not aTeam:IsHasTech(12) ) then
and you're done. Also, I'm assuming "12" is the right number for that particular tech, but the fact that you weren't getting the print statement means that that wasn't the problem.

I think what I really need is a basic guide for Lua modding that is specific to how you would do non-UI scripts in Civ 5

I'd say the best way to do this is to look at other people's work. So download a mod that has plenty of Lua in it and see how other people have done things. My mod has a decent amount of Lua in it, but there are far more complex ones out there.
 
The reason there is no full Lua guide, is that you would more or less need to write a guide for the entire language. Unlike XML, which most users only ever touch the <GameData> end of, Lua is far more freeform. In fact, a lot of the Lua being used write now are "hack" approaches that ideally will not be needed once we have full SDK
 
The reason there is no full Lua guide, is that you would more or less need to write a guide for the entire language. Unlike XML, which most users only ever touch the <GameData> end of, Lua is far more freeform. In fact, a lot of the Lua being used write now are "hack" approaches that ideally will not be needed once we have full SDK

Oh, I'm not suggesting that there should be full documentation of everything possible with Lua... I'm enough of a programmer to know that that would be absurd (I'm new to Lua, not to programming). However, it would be nice to have a Beginner's Guide to Lua Programming in Civ or some such, sort of like this one that was done for Python modding in Civ 4. It can be rough trying to pick up a new language just by looking over working code, particularly since a lot of the scripts available to study are a bit on the complex end for just trying to learn the basic concepts. Can you imagine trying to learn C++ just by looking over source code where the programmers didn't add any documentation for things they considered common knowledge? ;)

The double-colons-on-if-statements thing is a great example of what I am referring to: there is no way I would have ever picked up on that just looking over other people's scripts. I probably would have eventually realized it was wrong looking over the general Lua guide I'm reading (assuming it isn't a limitation of Civ's implementation, rather than the language), but I would have gone through a lot of hair-pulling before then (particularly since FireTuner's Lua console seems to accept it just fine =/ ).
 
Actually, you can use colons in this way.

All a colon does is this: foo:bar(args) = foo.bar(foo, args) and they do work after function calls and in whatever variety you need them. Not all functions need to be passed a reference of their object to work, however, especially those implemented in C++ (Game, UI, etc.)
 
All a colon does is this: foo:bar(args) = foo.bar(foo, args) and they do work after function calls and in whatever variety you need them.

I'd just worry about order of operations. If you write "A:B:C", does that mean operate A:B and then take the resulting structure, D, and do D:C (which is what he's trying here and why I suggested splitting it into two steps)? Or could it mean operate B:C first and then apply it to A? (While I'm not sure there are any examples of that latter category in Civ5, the question is whether there could EVER be an example of that sort of thing within Lua as a whole.)

Regardless, there's no reason to load the TeamTechs block at all, since as I said before, there's an IsHasTech field within the Teams structure and I can confirm that it works just fine in my own mod.
 
I'd just worry about order of operations. If you write "A:B:C", does that mean operate A:B and then take the resulting structure, D, and do D:C (which is what he's trying here and why I suggested splitting it into two steps)? Or could it mean operate B:C first and then apply it to A? (While I'm not sure there are any examples of that latter category in Civ5, the question is whether there could EVER be an example of that sort of thing within Lua as a whole.)

Regardless, there's no reason to load the TeamTechs block at all, since as I said before, there's an IsHasTech field within the Teams structure and I can confirm that it works just fine in my own mod.

Order is left-to-right. A:B():C() is exactly the same as D = A:B(); D:C(). In fact, both snippets compile to (almost) exactly the same code if D is a local variable

There's no reason in this case, I agree, but the question does come up in a lot of cases and sometimes you just don't want to split your code :)

Edit: For example, I often do something like UI.GetHeadSelectedUnit():GetPlot():GetX() or something in FireTuner, and would be annoyed having to create a global variable for it every time
 
I also have not been able to grant locked or disabled techs (nor even unlocked techs) with this method. Here's where I've gotten so far (I'm granting tech after policy choice)

Code:
function OnPolicyAdopted (playerID, policyID)
	if (IsUnion(playerID) and policyID == GameInfo.Policies["POLICY_RAILROAD"].ID) then
	print("Checking for policy")
		local pTech = GameInfo.Technologies["TECH_NS_RAILROAD"].ID
		local pPlayer = Players[IsUnion(playerID)]
		local pTeam = Teams[pPlayer:GetTeam()]
		if ( not pTeam:IsHasTech(pTech) ) then
			pTeam:SetHasTech(pTech)
			print("Granting new technology")
		end
	end
end
GameEvents.PlayerAdoptPolicy.Add(OnPolicyAdopted);

Suggestions on where I've gone wrong?
 
pTeam:SetHasTech(int, boolean)

It's a little confusing that you use "pTech" as a name for an ID, an integer, but only to humans (the compiler doesn't mind).
 
Back
Top Bottom