question about settlers

I would like to extend the following lua code to all specialists as condition: merchant, scientist, writer, artist and great musician, not only engineer. Any ideas how could be modified, please?

Code:
-- Only continue if the unit is a great engineer
	if(unit:GetUnitClassType() == GameInfoTypes["UNITCLASS_ENGINEER"] and not player:IsMinorCiv() and not player:IsBarbarian() and plot:IsCity()) then

If I understand correctly, that could look probably as:

Code:
if(unit:GetUnitClassType() == GameInfoTypes["UNITCLASS_ENGINEER"] or 
unit:GetUnitClassType() == GameInfoTypes["UNITCLASS_MERCHANT"] or
unit:GetUnitClassType() == GameInfoTypes["UNITCLASS_WRITER"]or
unit:GetUnitClassType() == GameInfoTypes["UNITCLASS_SCIENTIST"]or
unit:GetUnitClassType() == GameInfoTypes["UNITCLASS_ARTIST"]or
unit:GetUnitClassType() == GameInfoTypes["UNITCLASS_MUSICIAN"]and not player:IsMinorCiv() and not player:IsBarbarian() and plot:IsCity()) then

Please correct me :)
 
Due to operator precedence, you'll need to wrap all the or'ed bits in parenthesis, eg

X and not A and not B and not C

needs to become

(X or Y or Z) and not A and not B and not C

You can also save yourself a few characters

GameInfoTypes["UNITCLASS_ENGINEER"]

can be written as

GameInfoTypes.UNITCLASS_ENGINEER
 
I see (kinda). So if I need the function to process Engineers, merchants, writers and scientists and not only engineers like previous code, should be like this (paranthesis at start of conditions and end)?

(if(unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_ENGINEER or
unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_MERCHANT or
unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_WRITER or
unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_SCIENTIST)
and not player:IsMinorCiv() and not player:IsBarbarian() and plot:IsCity()) then

I skip code tag because the forum makes it in fact harder to read, no?
 
I see, thanks!

Also do you have any idea why this function will stop working if I replace the missionary class by engineer (or any else beside the two originally mentioned):

Code:
function OrdainedPriesthood(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
	local player = Players[playerID];
	local unit = player:GetUnitByID(unitID);
	local policyID = GameInfoTypes["POLICY_FREE_RELIGION"];
	local plot = unit:GetPlot();

	-- Only if the player has the policy and this is missionary/inquisitor
	if(player:HasPolicy(policyID) and not player:IsPolicyBlocked(policyID) and plot:IsCity() and (unit:GetUnitClassType() == GameInfoTypes["UNITCLASS_MISSIONARY"] or unit:GetUnitClassType() == GameInfoTypes["UNITCLASS_INQUISITOR"])) then
		local city = plot:GetPlotCity();

		city:ChangePopulation(1, true);

		-- Send a notification to the player
		local header = Locale.ConvertTextKey("TXT_KEY_NEW_ORDAINED_PRIESTHOOD_HEADER");
		local text = Locale.ConvertTextKey("TXT_KEY_NEW_ORDAINED_PRIESTHOOD_BODY", city:GetName());
		player:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, text, header);
	end
end
LuaEvents.SerialEventUnitCreatedGood.Add(OrdainedPriesthood);

In what the missionary class is different from merchant or engineer? is about military or?
 
Guys, please help a doomed soul, I am struggling with this since a week and have no idea what's wrong, it looks supernatural to me :confused::

This function works perfectly, it adds one citizen if one prophet is born or bought. but as soon as I change its class to Engineer, scientist or all others, nothing happens. The class is okay, WTH is going, tried hundreds of possibilities, stil only prophet is working.

--------------------------------------
function OrdainedPriesthood(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
local player = Players[playerID];
local unit = player:GetUnitByID(unitID);
local policyID = GameInfoTypes["POLICY_TRADITION_FINISHER"];
local plot = unit:GetPlot();

-- -- Only give the birthplace if the player has the policy and this is a great person spawned in a city
if(player:HasPolicy(policyID) and not player:IsPolicyBlocked(policyID) and unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_PROPHET) then
-- Get the city
local city = plot:GetPlotCity();

city:ChangePopulation(1, true);
--------------------------------------------
 
Scientists, Artists, Engineers, etc., often do not actually spawn within a city unless they are bought there using faith. In such cases where they spawn next to a city, local city = plot:GetPlotCity(); is going to return "nil" into variable city. If you are using faith to buy a great engineer within a city, though, and nothing is happening so far as the pop increase, then it is not obvious to me what is wrong with the code. Missionaries and Inquisitors don't spawn 'naturally', and so are always acquired from within the city view -- even where a wonder (for example) spawns a Missionary (Borobudur) or Inquisitor I can't think of an instance where they did not appear within the city instead of next to it. I can't remember ever seeing a Great Prophet spawning outside of a city either as a general rule.

I would use IGE to force-spawn directly a Great Engineer within a city and see if the code works in this case. If so, there is nothing wrong with the code, it is the spawn-plot of the Engineer that is the problem.

[edit]
Your earlier version of the code had this requirement (post #6): and plot:IsCity().
This would have the effect of not making the rest of the code run when the unit did not spawn on a city, and so would give identical results (ie, nothing happens) if the unit does not spawn within a city tile
 
yes I am running it with IGE (does not have prophet unit though). I got an error in lua.log saying:

2.5 Ordained_Priesthood.lua:11: ']' expected near ')'

So I suppose there is some error but I can't catch it, this is the elseif version where I try to mass all conditions in same function (could be about "end"? not sure I got them all to work:

------------------------------------
function OrdainedPriesthood(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
local player = Players[playerID];
local unit = player:GetUnitByID(unitID);
local plot = unit:GetPlot();

-- -- Only if the player has the policy and this is a great person spawned in a city
if(player:HasPolicy(GameInfoTypes.POLICY_TRADITION_FINISHER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_TRADITION_FINISHER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_PROPHET)) then

-- Get the city
local city = plot:GetPlotCity();
city:ChangePopulation(1, true);

elseif(player:HasPolicy(GameInfoTypes.POLICY_ASTHETICS_FINISHER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_ASTHETICS_FINISHER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_ARTIST)) then

-- Get the city
local city = plot:GetPlotCity();
city:ChangePopulation(1, true);

elseif(player:HasPolicy(GameInfoTypes.POLICY_HONOR_FINISHER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_HONOR_FINISHER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_ENGINEER)) then

-- Get the city
local city = plot:GetPlotCity();
city:ChangePopulation(1, true);

end

-- Send a notification to the player
local header = Locale.ConvertTextKey("TXT_KEY_NEW_ORDAINED_PRIESTHOOD_HEADER");
local text = Locale.ConvertTextKey("TXT_KEY_NEW_ORDAINED_PRIESTHOOD_BODY", city:GetName());
player:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, text, header);

end
LuaEvents.SerialEventUnitCreatedGood.Add(OrdainedPriesthood);

--------------------------------
 
Ordained_Priesthood.lua:11: ']' expected near ')'
In lua the number shown on the error message is generally refering you to the line number within the code where the error is originating from. Usually from that sort of an error I would expect to see an '[' somewhere without a matching ']', but I don't see those anywhere. Is what you are quoting the entire code from the file?

Also,
Code:
 blocks

Also also, try placing a space between 'if' and anything that follows and the same with 'elseif' -- it shouldn't ought to make a difference but it will be easier to read, and may actually make a difference.

[edit]
This part of your code will also be problematical:
[code]-- Send a notification to the player
local header = Locale.ConvertTextKey("TXT_KEY_NEW_ORDAINED_PRIESTHOOD_HEADER");
local text = Locale.ConvertTextKey("TXT_KEY_NEW_ORDAINED_PRIESTHOOD_BODY", city:GetName());
player:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, text, header);
Because variable city is defined and used within the "if then elseif then end" block of code, and will not be recognized by lua as having a value other than "nil" by the time the line defining local text = is executed.
 
Your code works fine for me as this:
Code:
function OrdainedPriesthood(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
	local player = Players[playerID];
	local unit = player:GetUnitByID(unitID); 
	local plot = unit:GetPlot();

	-- -- Only if the player has the policy and this is a great person spawned in a city
	if (player:HasPolicy(GameInfoTypes.POLICY_TRADITION_FINISHER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_TRADITION_FINISHER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_PROPHET)) then 

		-- Get the city
		local city = plot:GetPlotCity(); 
		city:ChangePopulation(1, true);

	elseif (player:HasPolicy(GameInfoTypes.POLICY_ASTHETICS_FINISHER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_ASTHETICS_FINISHER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_ARTIST)) then 

		-- Get the city
		local city = plot:GetPlotCity(); 
		city:ChangePopulation(1, true);

	elseif (player:HasPolicy(GameInfoTypes.POLICY_HONOR_FINISHER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_HONOR_FINISHER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_ENGINEER)) then 

		-- Get the city
		local city = plot:GetPlotCity(); 
		city:ChangePopulation(1, true);

	end

	-- Send a notification to the player
	--local header = Locale.ConvertTextKey("TXT_KEY_NEW_ORDAINED_PRIEST HOOD_HEADER");
	--local text = Locale.ConvertTextKey("TXT_KEY_NEW_ORDAINED_PRIEST HOOD_BODY", city:GetName());
	--player:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, text, header);

end
LuaEvents.SerialEventUnitCreatedGood.Add(OrdainedPriesthood);
Note that I commented out the three lines for the notification because of the issue mentioned in my last post. And it only works when the unit spawns within a city. And since Engineers, Scientists, Artists, etc., tend to spawn naturally outside cities, there is a pretty hefty bias for the code to do nothing for those units.

The other reason we like code blocks is this keeps the forum from adding spacing at odd places in the middle of a chunk of programming code, so we can highlight, copy, paste into a test mod and run the code if we can't see the error. When not placed in code blocks, the text of the code as presented by the forum software is not 'pure' (those odd placed extra spaces) and it makes it hard for us to try it on our end.

The space I added between the 'if's and 'elseif's and the next character does not seem to actually matter functionally but I at least find it a little easier to read the code.
 
Your code works fine for me as this:

No, it does not work for me, great persons spawn in city, no pop increase or message. I spent the last 10 hours to change things, then several minutes it takes to open game, because we can't work on modbuddy in same time, super practical. Then it does not work, back to change one sign, then again several minutes to get in, this is a nightmare:crazyeye:

So what can I do to get one citizen in capital when a great people spawn? I tried everything, nothing seems to work, even lua.log show me errors that are NOT in that script, I am confused.
 
SerialEventUnitCreatedGood is not part of the base game's code. Do you have Machiavelli's UnitCreatedGood system running as part of your mod? If not, this is your problem.

Better yet, attach the mod itself. There has to be some kind of an error you are making elsewhere because your code actually does work. Commenting out the three lines as I did is necessary.

And for small changes like this it is not necessary to go back into ModBuddy. Just open the lua file in Notepad. Do this for the mod that is in the My Games/Sid Meier's Civilization 5/MODS folder. Troubleshoot and fix the code directly in the copy of the mod the game is actually using. Once changes are complete that fix a trouble, then copy the corrected file into the ModBuddy Project and paste the corrected file right over the top of the bad file of the same name that is in ModBuddy.
 
Sure I have his Shared folder with that createunit function and all. The funny thing is that none of Machiavelli mods work in my game, without any modification. All his things where engineers should give this or that on born, nothing, nada. I checked other mods installed, there is nothing which conflicts. Lua.log now is clean, no error.


And no, changing syntax in Mods folder does not work, the game will instantly read from modbuddy when reload and will delete my changes. Or I didn't get how it works, but until now this is what happened. Anyway, what this saves as time? You still have to go menu, then load again the mods, this is exactly same time as restarting game. From game to menu, it takes up to one minute, I don't understand how can be so badly optimized. Mods should be discarded instantly, most of them have only a few files with short codes. + machiavelli told me to check in firetuner, but the bugger refuses to connect, always disconnected.

Edit: found a lot of stupid errors I made in other files, thanks whoward for modtools.jar. Now going to correct them all then retest.
 
Okay, after I fixed all errors, this has a new look. Lua is working now, the only backside is that it seems I can't put "adopt policy" as condition (TRADITION_OPENER, etc), it has to be one policy from list. Do you know why? I like having those births bonuses on adopting the required branch, not somewhere inside.

Code:
function GreatEngineerBorn_GivePopulation(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible)
	local player = Players[playerID];
	local unit = player:GetUnitByID(unitID);
	local plot = unit:GetPlot();
	local city = plot:GetPlotCity();

	-- Only continue if the unit is a specialist
	if (player:HasPolicy(GameInfoTypes.POLICY_TRADITION_OPENER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_TRADITION_OPENER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_ENGINEER and plot:IsCity())) then
		local bonusPop = 1;
		city:ChangePopulation(bonusPop, true);

        elseif (player:HasPolicy(GameInfoTypes.POLICY_LIBERTY_OPENER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_LIBERTY_OPENER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_WRITER and plot:IsCity())) then
		local bonusPop = 1;
		city:ChangePopulation(bonusPop, true);

        elseif (player:HasPolicy(GameInfoTypes.POLICY_HONOR_OPENER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_HONOR_OPENER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_GREAT_GENERAL and plot:IsCity())) then
		local bonusPop = 1;
		city:ChangePopulation(bonusPop, true);

        elseif (player:HasPolicy(GameInfoTypes.POLICY_PIETY_OPENER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_PIETY_OPENER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_PROPHET and plot:IsCity())) then
		local bonusPop = 1;
		city:ChangePopulation(bonusPop, true);

        elseif (player:HasPolicy(GameInfoTypes.POLICY_AESTHETICS_OPENER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_AESTHETICS_OPENER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_ARTIST and plot:IsCity())) then
		local bonusPop = 1;
		city:ChangePopulation(bonusPop, true);

        elseif (player:HasPolicy(GameInfoTypes.POLICY_COMMERCE_OPENER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_COMMERCE_OPENER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_MERCHANT and plot:IsCity())) then
		local bonusPop = 1;
		city:ChangePopulation(bonusPop, true);

        elseif (player:HasPolicy(GameInfoTypes.POLICY_RATIONALISM_OPENER) and not player:IsPolicyBlocked(GameInfoTypes.POLICY_RATIONALISM_OPENER) and (unit:GetUnitClassType() == GameInfoTypes.UNITCLASS_SCIENTIST and plot:IsCity())) then
		local bonusPop = 1;
		city:ChangePopulation(bonusPop, true);


		-- Send a notification to the player
		local header = Locale.ConvertTextKey("TXT_KEY_TITANS_ENGINEER_POPULATION_ON_BIRTH_HEADER", tostring(bonusPop), city:GetName());
		local text = Locale.ConvertTextKey("TXT_KEY_TITANS_ENGINEER_POPULATION_ON_BIRTH_BODY", tostring(bonusPop), city:GetName(), unit:GetName());

		player:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, text, header);
	end
end
LuaEvents.SerialEventUnitCreatedGood.Add(GreatEngineerBorn_GivePopulation);
 
Okay, after I fixed all errors, this has a new look. Lua is working now, the only backside is that it seems I can't put "adopt policy" as condition (TRADITION_OPENER, etc), it has to be one policy from list. Do you know why? I like having those births bonuses on adopting the required branch, not somewhere inside.

I don't really understand what you mean for the part I highlighted.

player:HasPolicy(PolicyID)
  • Answers true or false for whether or not "player" has the specified policy from the game table Policies
  • POLICY_BRANCH_LIBERTY for example is not a member of table Policies
  • If using a form of GameInfoTypes.POLICY_TRADITION_OPENER to specify the ID# of the desired policy, the text entered after GameInfoTypes. must be a valid policy name from the table Policies. The Policy-Name used can be one of those provided in the base-game, or one you add to the game as part of your mod, but it must match exactly with one of the designations of <Type> that appear within table <Policies>.
    • So you cannot use "TRADITION_OPENER". It has to be "POLICY_TRADITION_OPENER" because this is what is registered in the game's XML

--------------------------------------------------------------

I have no earthly Idea why Machiavelli's code is "not working" other than to say they are meant for the most part as code-snippet templates for mod-makers and not meant so far as I recall to be fully functional code on their own. His SerialEventUnitCreatedGood system is meant to act as an additional (and functionaly better) event hook to the game's standard SerialEventUnitCreated event hook. His system for SerialEventUnitCreatedGood as he provided does not actually in and of itself create any real in-game changes -- you have to add your follow-on code (such as you are using) in order for his SerialEventUnitCreatedGood system to do anything.

-------------------------------------------------------------------
And no, changing syntax in Mods folder does not work, the game will instantly read from modbuddy when reload and will delete my changes.
This is not normal behavior. If you have directed ModBuddy to save all your work in the game's MODS folder, this is not a good idea, and is likely the culprit for this behavior. You should not be seeing the ModBuddy "Project" folders such as "Packages" or "Build" anywhere within the game's MODS folder.

I have my ModBuddy Project files all located in C:\Users\[UserName]\Documents\Firaxis ModBuddy\
  • So if I have a Project called "(BNW) CoreMod", the working files that ModBuddy uses for that project will be stored in C:\Users\[UserName]\Documents\Firaxis ModBuddy\(BNW) CoreMod\(BNW) CoreMod
  • When I Build the mod in ModBuddy, an independant copy of the mod is sent to C:\Users\[UserName]\Documents\My Games\Sid Meier's Civilization 5\MODS\(BNW) CoreMod. The XML, SQL, and LUA files within this independant copy of the mod can be edited, changed, redrafted, etc. This will have no effect on the copy of the files located in the folder C:\Users\[UserName]\Documents\Firaxis ModBuddy\(BNW) CoreMod\(BNW) CoreMod, nor will any changes made to the copy of the files located at C:\Users\[UserName]\Documents\Firaxis ModBuddy\(BNW) CoreMod\(BNW) CoreMod effect in any way the files located at C:\Users\[UserName]\Documents\My Games\Sid Meier's Civilization 5\MODS\(BNW) CoreMod until and unless I open ModBuddy and redo the "Build" function.
 
If you want to use the policy branch types, and not check for a specific policy opener, you can always use pPlayer:IsPolicyBranchUnlocked()
 
I hate when forum does not let delete posts, as I am always impatient asking if something does not work, but then I return work and I eventually find the errors. In reality, there were a lot of typo errors in my xml files, which your modjar found so I could fix (like incomplete tags here and there, due to intense copy/pasting for yields, improvements etc). Now all is fine and working like a charm, I will release the Reforms mod for OCC game in a week or so, after I am done polishing details, adding buildings upon branch completions and things like that.

About Tradition opener, I only used the short abbreviation in post, if you check my code, it has the correct syntax. But that one is not working in the birth script, all finisher or opener policies do not work. As soon as I pick another in the branch, is ok. It works in my other scripts xml, just in the lua it does not recognize them.


Also a note: IGE is not perfect for testing, I suppose it does not read modded data so it gives incorrect scripts results.
 
It did (does) work for me, but when testing I always use the method of giving myself huge amounts of culture with IGE, and then closing IGE and using the game's normal Social Policies menu to select all the ones I need active to check my lua code.

If you use IGE to directly select the policy or only to select the finisher, but not all the prerequisite policies, this may be why it does not seem to work. For the finisher policies especially this may be why the game does not see the player as "having" the policy.

I have seen for example that the CityConstructed event does not fire when you use IGE to directly give yourself a wonder, for example. There may be similar issues with selecting policies directly from within IGE.

Process I use for testing an lua that is looking for player:HasPolicy(PolicyID)
  1. Open IGE and give myself something like 20,000 culture
  2. Close IGE
  3. Open the Social Policy selection menu and pick the policy(ies) I need to get to the one I need for my lua
  4. Make NEXT TURN or whatever other action I need to force the lua to execute.
    • So for your code I opened IGE once more and made IGE give me a Great Engineer in my capitall city, then made IGE give me one next to but not in my capital city.
You can use Live Tuner to do all the same things I do in IGE, but I am just not as well-versed in where all the menu items are in Live Tuner.
 
Back
Top Bottom