• Our friends from AlphaCentauri2.info are in need of technical assistance. If you have experience with the LAMP stack and some hours to spare, please help them out and post here.

Getting started: simple function

Thalassicus

Bytes and Nibblers
Joined
Nov 9, 2005
Messages
11,057
Location
Texas
I've learned some basics of Lua and how to use callbacks to register a function I want executed. I'm having difficulty finding much more information than that, though.

Something that would help is knowing how to do just a very simple function, such as this:

function GivePolicy(player)
GiveFreePolicy(player);
end
Events.PlayerEnteredNewEra.Add(GivePolicy);

What would be the actual code for this? In particular, where can I find an API for the actual names of the italicized parts?
 
With regard to finding the parts in italics, that is the question for most of us. There have been several useful posts that lists discovered events and functions, but the list is far from complete. So far the methods used by most to locate what they need is to either search those lists or to search through existing lua code from the game trying to find keywords that match generally what they are doing. If we are really lucky, Firaxis will release a full Lua API document, but we are probably on our own for a while.

With regard to your specific question, you would want to use Event.SerialEventEraChanged.Add( GivePolicy )


Your GivePolicy function would have a function signature of function GivePolicy( era, player )

era would be the numeric value of which era was just changed to, and player is the player id.

I found the event by searching all lua files in the game directory for 'Era' and found the SetCityEra section in DebugMode.lua. It seems to do what you want, but I haven't tested it. If you only want it to work for a specific player, you'll need to test for that in your code.

However, the closest function for actually giving them a policy is the following:

Code:
Network.SendUpdatePolicies(m_gPolicyID, m_gAdoptingPolicy, true);

But that only seems to function directly on the active player (which is actually what 'player' would be from the Event triggering GivePolicy. m_gPolicyID is the numeric index of the policy to be adopted, m_gAdoptingPolicy is a boolean that I think determines if the policy is actually adopted or not.

Sadly, you'll need to experiment a bit with this, but hopefully someone else has been digging around in how the policy system works. :)

I found the function by searching all lua files in the game directory for 'Policy' and found the code in SocialPolicyPanel.lua.
 
The LUA API has these under Player :

GetHappinessFromPolicies
IsPolicyBranchUnlocked
SetPolicyBranchUnlocked
GetNumPolicyBranchesUnlocked
GetPolicyBranchChosen
GetNumPolicyBranchesAllowed
HasPolicy
SetHasPolicy
GetNextPolicyCost
CanAdoptPolicy
DoAdoptPolicy
CanUnlockPolicyBranch

And the GameCore dll has :
CvPlayer::setHasPolicy(PolicyTypes,bool)
CvPlayer::doAdoptPolicy(PolicyTypes)

I'm not sure about the value to provide for PolicyTypes though .
 
Thanks manar. My guess is that the lua implementation uses the policy id for PolicyTypes. So the code to do what Thalassicus wants would probably be something like:

Code:
function GivePolicy( era, player )
    local mPlayer = Players[player];
    if( mPlayer ~= nil ) then
        mPlayer:SetHasPolicy( <desired policy id>, true );
        mPlayer:DoAdoptPolicy( <desired policy id> );
    end
end
Event.SerialEventEraChanged.Add( GivePolicy )

I'm not sure if there is a function to get the policy id based on the name, but all of the policies are available in the Game.Policies table, so you could write your own function that loops over it until it finds the right match.
 
Thank you for the assistance, that syntax information will help a lot ArgentumStudios. I didn't get involved with python scripting until some time had passed in Civ IV, was the API similarly missing then (until the c++ portion of the sdk was released)?

What I'm specifically trying to do is add the <FreePolicies> attribute of the Oracle to era transitions. It doesn't seem like any of the function names manar listed might apply to this, unfortunately, but I'll experiment.

Incidentally, how did you do the search within Lua files? When I search for "policy" from the Assets directory I only get XML hits. (win7) As a workaround I'm loading all the files in notepad++, but that's a bit cumbersome.
 
You're welcome. When Civ IV was released, the python API was similarly documented (or not...), so there was a lot of experimentation then as well. Though I never really got into Civ IV modding much due to a lack of time. Having the header and source files for the API that were released with the C++ portion of the SDK helps a lot.

As far as searching, I use the Find in Files functionality in ModBuddy and have a saved folder set for the Civ 5 standard assets and then *.xml *.lua and *xml, *.lua file type filters. To set up the saved folder set do the following:

1) in ModBuddy go to Edit -> Find and Replace -> Find in Files
2) In the 'Look in:' section, click on the '...' button
3) Under 'Available Folders' browse to your Civ 5 assets folder (select it, don't double click into it) 4) Click the '>' button to add it to the list of 'Selected Folders'
5) In the 'Folder Set' section type in a name (I named mine Civilization 5 Assets) and click Apply
6) Click 'Ok'

From now on you can just select Civilization 5 Assets from the dropdown in the Find in Files dialog.

You can filter based on different file types by typing different patterns (which will be saved in the dropdown for future use) in the 'Look at these file types:' section. As I said I use the following filters:

*.lua
*.xml
*.lua, *.xml
 
Aha, had never tried VS's tools in that regard... the IDE is so massive it's difficult to really experiment with it all! (well, easier to manage with it stripped down to just Civ needs)

Thank you, this will save me some time compared to win7's normal search... and when doing things with large packages in VS too. :)
 
This code does not appear to work: Specifically I am using:

Code:
function GivePolicy( era, player )
    local mPlayer = Players[player];
    if( mPlayer ~= nil ) then
        mPlayer:DoAdoptPolicy( Policy_0 );
        mPlayer:SetHasPolicy( Policy_0, true );
    end
end
Event.SerialEventEraChanged.Add( GivePolicy )

I have attempted various iterations of this code, such as using the file name of the policy, using small caps for p, using <> around the policy, not using the _ , ensuring I had enough policy points to make the selection, taking out the era portion of the function.. and sadly none of these resulted in the policy being selected. What am I doing wrong here?
 
My guess would be that you are not providing a valid ID in the Policy_0 variable. What have you set Policy_0 to? It should likely be set to a number between 0 and 59, which is currently the last ID in the table.
 
I set it to zero and still nothing. Oy.. you had me all excited too!
Hmm, the only other thing I can think of is to try setting it to 1 as a test. Perhaps it's one of those "1-based" arrays.
 
This is starting to drive me batty - and no, changing it to one had no effect =(. Perhaps someone could take a look at this and let me know what is going wrong. I suspect I'm missing something simple.
 

Attachments

That zip doesn't include anything but the solution file.
 
Here then. Other people have had success unpacking this.. though I'm not sure how. I just didn't want to include the gamerules.xml. I didn't realize the solution file wouldn't work =x
 

Attachments

Evalis, did you get your script to work?

I've also worked out a simple script, but it appears to never actually get "applied" (it's supposed to add an event handler).

Civ4 script modding was definately easier.

Edit: Here's the snippet I can't get to work. I even tried to (just for testing purposes) paste it into one of the game's lua files that are guaranteed to be loaded - it just won't work.
Code:
function MyOnImprovementCreated (HPosX, HPosY, CultureType, ContinentType, PlayerType, engineImprovementTypeDoNotUse, ImprovementType, engineResourceTypeDoNotUse, RawResourceType, ImprovementEra, ImprovementState)	
	local iX, iY = ToGridFromHex( HPosX, HPosY );
	local pPlot = Map.GetPlot(iX, iY);

	if (ImprovementType == ImprovementTypes.IMPROVEMENT_FORESTATION) then
                pPlot:SetImprovementType(ImprovementTypes.NO_IMPROVEMENT);
		pPlot:SetFeatureType(FeatureTypes.FEATURE_FOREST, -1);
	end	
end
Events.SerialEventImprovementCreated.Add( MyOnImprovementCreated );
_____
rezaf
 
@ Rezaf

Through my own Lua modding, I discovered that you can't call data on the initial function from a function in a different file. You must get that data via lines of code in the same Lua file. I simple copy/paste lines that pertain specifically to getting data that I need.

Code:
function MyOnImprovementCreated ([B]HPosX, HPosY, CultureType, ContinentType, PlayerType, engineImprovementTypeDoNotUse, ImprovementType, engineResourceTypeDoNotUse, RawResourceType, ImprovementEra, ImprovementState[/B])

Everything in the parenthesis needs to be deleted and re-discovered in the file you're using.

EDIT: Also don't forget to put the Lua reference in the InGame.xml in your own mod directory.
 
Back
Top Bottom