If Culture Level is higher / lower - function

None of these 3 code samples didn't worked.

Maybe you can do this simple code of printing on your own, test if it works for you and if it do, zip it and give me? I just wonder in case if something that works for you - won't work for me...

Because really, how such simple thing don't want to work for me, that's not fun -_-

This way we will be able to understand at least the source of the problem
 
But do not try to run all at the same time in the same file or even across multiple files each with one of those in it because any little mistake in one will drive you crazy figuring out why it does not work.

Note that this is not quite true -- multiple entry points like this can, and do, work. However, this should only be done in certain, more advanced scenarios.

For reference, check out Vice Virtuoso's Wish for the World mod, which has multiple entry points like this for several Lua files which he needs to do different things. I believe he passes data back and forth via LuaEvents, though, since it can "speak" across contexts.

In either case, this suggestion applies here on the basis of logic -- if you are testing something, don't go crazy and fire off a half dozen things all at once, especially when you're unsure of how these multiple entry points will interact with each other.

Have said all that, here's the bigger issue, now that we have access to your mod's modinfo file:

Code:
  <EntryPoints>
    <EntryPoint [B][COLOR="Red"]type="MapScript" [/COLOR][/B]file="Culture.lua">
      <Name>1</Name>
      <Description>1</Description>
    </EntryPoint>
    <EntryPoint [B][COLOR="Red"]type="MapScript"[/COLOR][/B] file="War Units.lua">
      <Name>2</Name>
      <Description>2</Description>
    </EntryPoint>
    <EntryPoint [B][COLOR="Red"]type="MapScript"[/COLOR][/B] file="Test.lua">
      <Name>3</Name>
      <Description>3</Description>
    </EntryPoint>
    <EntryPoint [B][COLOR="Red"]type="MapScript"[/COLOR][/B] file="Test2.lua">
      <Name>4</Name>
      <Description>4</Description>
    </EntryPoint>
    <EntryPoint [B][COLOR="Red"]type="MapScript"[/COLOR][/B] file="Test3.lua">
      <Name>5</Name>
      <Description>5</Description>
    </EntryPoint>
    <EntryPoint [B][COLOR="Red"]type="MapScript"[/COLOR][/B] file="Test4.lua">
      <Name>6</Name>
      <Description>6</Description>
    </EntryPoint>
  </EntryPoints>

Lua files should not be set as MapScripts! In order to run these files the way we want them to, Lua files must be added as InGameUIAddin instead.

I also have no idea why you've imported 'War Units.xml' into VFS, but I'll assume you're creating a UI element, since there is a matching War Units.lua file in there.

Edit:
Furthermore, you have various critical errors in your new Lua files. I assume you've edited them out of desperation, and are somewhat panicky right now, but calm down and think carefully at what you are writing:

Test.lua
Code:
-- Test
-- Author: Dartmor
-- DateCreated: 5/27/2015 3:59:05 AM
--------------------------------------------------------------
function [COLOR="Red"]Test[/COLOR]
print ("MAGIC!!! IT WORK1!!!")
end

[COLOR="Red"]GameEvent[/COLOR].PlayerDoTurn.Add(Test)
The first issue here is as I stated in a previous reply here -- your function name must contain parentheses, or Lua will run into an error: function Test()
The second issue is that GameEvent does not exist -- it is GameEvents!

Test2.lua
Code:
-- Test2
-- Author: Dartmor
-- DateCreated: 5/27/2015 5:33:07 AM
--------------------------------------------------------------
function Test()
print ("MAGIC!!!MAKE IT WORK2!!!")
end

[COLOR="Red"]GameEvent[/COLOR].PlayerDoTurn.Add(Test);
This one has the function properly named, and it would work, if not for the fact that once again GameEvent doesn't exist. See above.

Test3.lua
Code:
-- Test3
-- Author: Dartmor
-- DateCreated: 5/27/2015 5:34:51 AM
--------------------------------------------------------------
function Test()
print ("MAGIC!!!MAKE IT WORK3!!!")
end

[COLOR="Red"]GameEvent[/COLOR].PlayerDoTurn.Add(Test)
Besides a number being changed, this is exactly the same code as before, with the same error.

Test4.lua
Code:
-- Lua Script1
-- Author: Dartmor
-- DateCreated: 5/27/2015 5:35:27 AM
--------------------------------------------------------------
GameEvents.PlayerDoTurn.Add(
	[COLOR="Red"]function WarStateChangedHandler()[/COLOR]
	print("MAGIC!!! IT WORK4!!!!")
end)

function WarStateChangedHandler()
	print("something ought to happen here4")
end
This one is slightly different. This time you've managed to call the GameEvents handler properly, but the directive given to it is malformed and will run into an error.
When you define a new function for PlayerDoTurn in this way, you either tell it to run some other function, or you define a new anonymous one. It seems like you've gotten confused and tried to do both here, which will confuse Lua even more than you.

Either remove the word function, thus telling PlayerDoTurn to run a function called WarStateChangedHandler (and remove the parenthesis there -- they are necessary when you define a function, or if you need to call a function with specific arguments to be passed into it. PlayerDoTurn already provides its own argument (iPlayer) so this is unnecessary) or remove WarStateChangedHandler() to define a new anonymous function -- function(iPlayer).
 
I've read something about adding as InGameUIAddin, but when i tried it - it didn't showed me available lua to add. While MapScript did. So i just thought it was the right one...

Update:
If it's what i think it is, then it works
[230972.568] \Users\Dartmor\Documents\My Games\Sid Meier's Civilization 5\MODS\Advanced Culture (v 1)\Test2: MAGIC! MAKE IT WORK!!!!

I feel myself dumb :D I should have payed more attention to that post i've seen about InGameUIAddin somewhere. But because lua were not shown automatically ( you need to write name manually ) i thought something like "hey i dont like it, this is not logical if it don't show up!"
And MapScript was so nice and welcome with it's automatic list of lua files available :((

Thanks a lot... I hope i will figure out the rest faster
 
I just hope my mode will be good, to pay out our common efforts here :D

And now i really need to watch some stacraft 2 casts, play some counter-strike and eat something sweet lol
 
ok, I added edits to my last post, but it was ninja'd anyway.

My comment about not trying to run all that stuff at once was directed to this test-out stuff. Bad idea idea to be trying to run multiple different contents when you are still trying to figure out what you are doing wrong in getting one to work properly.

You might want to look at my Post #20, as it addresses troubles in you XML file and contains a link to a tutorial on the methods required for "activating" in ModBuddy every type of file.
 
Code:
local pPlayer = Players[iPlayer]
local pTeamId = pPlayer:GetTeam()

Ok, this way i guess i am 1) defining the CURRENT player ( human or AI ) with "iPlayer", right?
2) And then getting Team of that CURRENT player, right?
But how i can get local of pPlayer's current enemy?
Well, i am going certainly dig some documents, i am just asking in case if i don't find by myself

All i want is - any player ( human or ai ) who is at war, triggers function, that increases amount of free military units
so even when 2 ai ( without human ) civs are fighting, it work for them too
 
Theoretically, yes, that code would find the Player object and the associated Team ID of that player.

However, iPlayer is not defined in your code snippet, and will cause that assignment to fail, which then cascades into the GetTeam() method failing.

It really depends on which game method or game event hook you're using, as it entirely depends on what arguments are available for you to use in your functions. At the most basic level, you can theoretically loop through all players in the game and check whether or not they are at war with the chosen player, but that's fairly resource-intensive to do.

Finally, your use of pTeamId is misleading, in terms of usage of Hungarian Notation. The typical usage of the 'p' prefix is meant to indicate a pointer, although since that's not accurate in this game either, it refers to a game object. pTeamId would indicate a game object related to a specific team, but pPlayer:GetTeam() returns an integer, not the game object! To get the latter, you would need to additionally query the Teams table, just like you did with the Players table -- Teams[teamID].
 
Code:
local iActivePlayer = Players[Game.GetActivePlayer()];
local iTeamId = iActivePlayer:GetTeam();

Ok, i got it. Do i actually need those ";" ? Or it's optional?

By the way. Can i simply delete from "Events.WarStateChanged.Add(function( team1, team2, bool war)" - "team1" and "team2" and make function only to check if current active civilization has simply changed from peace to war ( no matter with who )?
This way i will not need to check enemy, because status has been changed anyway for 2 civilizations and it should be triggered for both of them in their turn

And i am still not sure how to change available number of free military units. If i can't do that through lua ( because there is no such thing listed in modiki ) and i can't run XML from lua, how?
Although i see "Player.ChangeGoldPerUnitTimes100" here, i hope it's what i think it is

I have an idea that i will try out
 
There's still a slight issue with your Hungarian Notation -- iActivePlayer is not actually an integer in this case, because you've assigned it a value within the Players table, thus turning it into the player game object, and in this case, would be referred to as pActivePlayer. If you don't quite understand the differences, it might be easier for you to discard it entirely and come up with your own naming convention. The important thing is that it is consistent and won't cause confusion for anyone reading your code.

As far as the semicolons go, they are unnecessary in Lua, although it doesn't hurt anything to leave them in. Semicolons may be useful if you want to stick multiple Lua commands on one line, but I find it's easier to read and organize if I simply give them each their own line.

Be careful about removing arguments from a function.
Yes, you can do so, but it won't work in the way you seem to be expecting them to.

Functions, when defined with arguments to accept, must accept those arguments in the order given. For example, I have a function in my Holo Civ used to determine specific things about a plot, the simplest one being the plot owner:
Code:
local function PlotOwner(pPlot, iPlayer)
As you can see, I have defined my function to accept two arguments: pPlot, and iPlayer. When I call this function, I must give it these two pieces of information in this exact order. If I don't, Lua will complain and give me an error. If I give it more than the two pieces of information, it'll take the first two, and ignore the rest because it's not set up to interpret anything beyond the first two arguments.

Similarly, when a function is set to return a specific set of values, it will always return those values in the same order as defined in the return statement!

This means that when the game returns arguments to your function to use via Events.WarStateChanged it will always return information for team1, team2, and bWar in this exact order. It is up to your function to interpret these pieces of information.

Normally, your function would be set up to retrieve all three pieces of information. However, if you decide you only want the value of bWar and you remove team1 and team2 from your function's list of "input arguments," this is where you run into issues.

Recall that I just said that a function will give you information in the exact order that was given. It doesn't care, and neither does Lua, what you call these pieces of information. This means that your new function, if set up like this:
Code:
function(bWar) ...
What will actually happen is that since bWar is occupying the "first" argument slot, bWar contains the value for team1! It doesn't matter if you called it iLikeCats, all that would mean is that then iLikeCats would have the value of team1.

In summary, you can choose to ignore specific returned values, but only for values at the end! If you only wanted the value of team1, then all you'd need to do, since it is the first value returned, is to make sure your function accepts value #1. #2 and #3 would then be ignored and lost with no consequence because you didn't want to use them. However, if you wanted only value #2, then you would need a "dummy" variable to accept value #1 (and simply not use it) and then have your real variable take the data for value #2.

WarStateChanged also fires twice, I believe, since it needs to fire once for each player involved in a new war.

I am not entirely sure how to change free military units, since that area is a bit tricky, and Firaxis never needed to do so with the stock Civs, so their unit and maintenance related methods are all global. If it's going to be a static number of free units (without restriction on which types) then you can try to go for a dummy policy which mimics Volunteer Army.
 
1) Oh that's a good idea, i will work on it :)

I actually found: Nationalism
Reduces Unit gold Gold Maintenance costs by 33%.

I guess decreasing gold maintenance can work instead of increasing supply, that will be, for example, normal from the start.

2) Currently i am trying to understand some examples of code i've seen in internet. Like "local civ = GameInfo.Civilizations[player:GetCivilizationType()];" from http://forums.2k.com/showthread.php?228861-How-to-change-the-name-of-a-civilization-in-LUA
I don't understand it, but does it get acces to XML files with "GameInfo.Civilizations" or what?
I dont' get it, but for example based on http://modiki.civfanatics.com/index.php/CivilizationType_(Civ5_Type)
you can actually do something with XML... at least maybe use XML names/types

3) And i have an idea. Can i simply make something like
Code:
GameEvents.PlayerDoTurn.Add(function(bwar)
	print("works")
        local iPlayer=Players[Game.GetActivePlayer()]
              if iPlayer /goes to war or is at war/ then
                      code here
              end
end)

This way i don't have to make dummies, and as a bonus, it will work only until player is at war. And when war ends, units support will return to normal by itself.
But i will anyway need comparison of 2 civs who declare war to each other, to compare Culture Level...


4) As far as i underand i have to:
1. Use Events.WarStateChanged and make dummies /or/ use my idea above
2. Somehow get accets to xml as i mentioned above /or/ use nationalism

Or i can try to change difficulty through lua when war comes, and along with changing difficulty - number of supplied units will change too...

5) But i will need to lower AI's gold income, or he will simply maintain huge army because of large gold amount/income. And that's what i am fighting against. I wanted to simply reduce basic supply to a low number and then increase it in time of war, but if it's not possible in any ways, i guess modifying gold maintenance and AI's gold income should work too

6) It's so sad i can't modify supply! Because of that Player will simply stack military units right before war, increasing gold maintenance, and when war begins - gold maintenance will be lower, but he will have huge army. And i don't want it.
They key reason to make this modification is to change war type from "huge wave on huge wave" to more tactical-like combat with small waves. And civ who will be more effective, will loose less units and will increase army numbers to push and overcome enemy.

7) But i guess i can make Gold Maintenance of military units VERY HIGH, so that player will be forced to stick with small free army until war is declared.

The more i do, the more i want to do. >.<

UPDATE:
8) Ok, i think this worked
Code:
GameEvents.PlayerDoTurn.Add(function(iActivePlayer, bWar)
	print("Test works")
	local iActivePlayer = Players[Game.GetActivePlayer()]
	iActivePlayer:SetHasPolicy(GameInfo.Policies["POLICY_NATIONALISM"].ID, true)
end)
9) But i think i saw number of 4 policies in stats... Couldn't see Policy itself, because i've started in Ancient Era. So i am not sure, but normally 2 units costs 0.5 each, and now it was 0.33 for 3 units. So i guess it works.

10) And i will be able to modify number of free gold units through XML, i know how to. But not sure how to change this number depending on number of cities. I don't want player to be stuck at 10 free units when he already has 20 cities :D And because Gold Maintenance will be very high, he will have problems to have extra units in peace time.

11) So the main question at the moment is how to find Civilization with which Active Player is at war, at least to be able to compare Culture Levels or find alternative path for that.
 
For the PlayerDoTurn "event", only one piece of information is passed to the function, the integer number of the current player from the Players table.

So your use of "bWar" does not hurt anything but neither does it add anything.

Also, you already have the integer number of the current player as soon as a PlayerDoTurn function is activated, so there is no reason to go look for that information from Game.GetActivePlayer(). Again, doing so does not hurt anything but neither does it really add anything. So for your code:

Code:
GameEvents.PlayerDoTurn.Add(function([color="blue"]iActivePlayer[/color][color="red"], bWar[/color])
	print("Test works")
	local [color="green"]p[/color]ActivePlayer = Players[[color="blue"]iActivePlayer[/color]]
	[color="green"]p[/color]ActivePlayer:SetHasPolicy(GameInfo.Policies["POLICY_NATIONALISM"].ID, true)
end)

Red = uneeded
Blue = integer # of the current player from the Players table.
Green = alteration to conform to hungarian notation norms

Also, there are a couple of other things that are generally good to do in order to avoid crash failures of the game from code problems (the blue parts):
Code:
GameEvents.PlayerDoTurn.Add(function(iActivePlayer)
	print("Test works")
	local pActivePlayer = Players[iActivePlayer]
	[color="blue"]if pActivePlayer:IsAlive() then[/color]
		pActivePlayer:SetHasPolicy(GameInfo.Policies["POLICY_NATIONALISM"].ID, true)
	[color="blue"]end[/color]
end)
 
And how to check if ActivePlayer is at state of war or not? something like
Code:
if pActivePlayer:[B]atWar?[/B]() then
		pActivePlayer:SetHasPolicy(GameInfo.Policies["POLICY_NATIONALISM"].ID, true)
	end

I am trying to find something but no succes so far.

I am not sure, but i've found "Player.IsProxyWarActiveForMajor" that was added with BNW
I want to try it. Should it be?
Code:
if pActivePlayer:IsProxyWarActiveForMajor() then
		pActivePlayer:SetHasPolicy(GameInfo.Policies["POLICY_NATIONALISM"].ID, true)
	end
 
War states are all accessed via the Team a Player belongs to, and not directly from the Player itself. (Thank you Firaxis for this extra bit of confusing anti-intuitive complexity). So 1st you have to translate from Player to the Team the Player belongs to:
Code:
local iActivePlayersTeam = pActivePlayer:GetTeam()
And then you can use the "Teams" methods shown here: Team Info

I have not tried this one Team At War Count, but in order to get the number of other teams pActivePlayer is as war with (not counting City-States), it looks like you would need:
Code:
local iNumberTeamsWarWith = Teams[iActivePlayersTeam]:GetAtWarCount(true)
If this is zero, they are not at war with any other major players. If greater than zero, then you can look to sort out which other team (and players within those teams) they are at war with.

Player Info
API changes in Brave New World
BNW Patch Version 1.0.3.276 New Lua Hooks

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

This is something I've been playing around with that causes all major players to declare war on each other if (a) 75 turns have been played and (b) the major players have met. I am using it in something I am experimenting with/developing for a future possible project. Minor Civs (City-States) are not effected, and the human player never declares the war, it is always done by the AI player.

It isn't directly exactly what you are looking for but shows an example of how to manipulate Players/Teams and whether or not they are at War.
Spoiler :
Code:
gLockedWarImmunityTurns = 75

----------------------------------------------------------------------------------------------------------------------------------
--After the turn # specified for gLockedWarImmunityTurns, all major players become locked in perpetual war with one another
----------------------------------------------------------------------------------------------------------------------------------
function EveryoneHatesEveryone(iPlayer)
	if Game.GetGameTurn() <= gLockedWarImmunityTurns then return end
	local pPlayer = Players[iPlayer]
	if not pPlayer:IsAlive() then return end
	if pPlayer:IsHuman() then return end
	if pPlayer:IsMinorCiv() then return end
	local iPlayersTeam = pPlayer:GetTeam()
	for iMajPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
		if Players[iMajPlayer] ~= pPlayer then
			local pOtherPlayer = Players[iMajPlayer]
			if not pOtherPlayer:IsMinorCiv() then
				if pOtherPlayer:IsAlive() then
					local iOtherPlayerTeam = pOtherPlayer:GetTeam()
					if Teams[iPlayersTeam]:IsHasMet(iOtherPlayerTeam) then
						if Teams[iPlayersTeam]:CanDeclareWar(iOtherPlayerTeam) then
							Teams[iPlayersTeam]:DeclareWar(iOtherPlayerTeam)
							Teams[iPlayersTeam]:SetPermanentWarPeace(iOtherPlayerTeam, true)
						else print("Teams[iPlayersTeam]:CanDeclareWar(iOtherPlayerTeam) returned false")
							print("iPlayer value was " .. iPlayer .. " for " ..GameInfo.Civilizations[Players[iPlayer]:GetCivilizationType()].Type .. " and iPlayersTeam value was " .. iPlayersTeam)
							print("iMajPlayer value was " .. iMajPlayer .. " for " ..GameInfo.Civilizations[Players[iMajPlayer]:GetCivilizationType()].Type .. " and iOtherPlayerTeam value was " .. iOtherPlayerTeam)
							print("Teams[iPlayersTeam]:IsAtWar(iOtherPlayerTeam) was " .. tostring(Teams[iPlayersTeam]:IsAtWar(iOtherPlayerTeam)))
						end
					end
				end
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(EveryoneHatesEveryone)
There are also several print statements you wouldn't need that I am using to capture data depending on whether I get a true or a false from Teams[iPlayersTeam]:CanDeclareWar(iOtherPlayerTeam)
 
Thanks, will dive into reading. If i manage to use it, it will be almost done :)
At least for these 2 minor modifications.

Thanks for the update, it will help a lot!

Update: SOLVED

Ok, i am a bit confused.

Code:
-- Lua Script2
-- Author: Dartmor
-- DateCreated: 5/26/2015 9:14:45 AM
--------------------------------------------------------------
GameEvents.PlayerDoTurn.Add(function()
local pActivePlayer = Players[Game.GetActivePlayer()]
print("works fine")
local pActivePlayersTeam = pActivePlayer:GetTeam()
	[B]if pActivePlayersTeam.getAtWarCount(true) > 0 then[/B]
	print("Receives Nationalism")
	pActivePlayer:SetHasPolicy(GameInfo.Policies["POLICY_NATIONALISM"].ID, true)
print ("In time of war number of free military units is increased")
	end
end)

[326470.000] \Users\Dartmor\Documents\My Games\Sid Meier's Civilization 5\MODS\Advanced Culture (v 1)\War Units: works fine
[326470.000] Runtime Error: C:\Users\Dartmor\Documents\My Games\Sid Meier's Civilization 5\MODS\Advanced Culture (v 1)\War Units.lua:9: attempt to index local 'pActivePlayersTeam' (a number value)

Idea based on http://forums.civfanatics.com/archive/index.php/t-476785.html
I know i am missing some parts like ":" or "then" or "return true/false", but i am not sure where to place them ( and which ones )
or maybe i should write "Teams[pActivePlayersTeam]:GetAtWarCount(true)" instead of "pActivePlayersTeam", or ":" instead of "." in "pActivePlayersTeam.getAtWarCount(true)"

Update:

I think it some kind of worked finally. When i declared war, i received
[331075.742] \Users\Dartmor\Documents\My Games\Sid Meier's Civilization 5\MODS\Advanced Culture (v 1)\War Units: Receives Nationalism

I am using
Code:
GameEvents.PlayerDoTurn.Add(function()
local pActivePlayer = Players[Game.GetActivePlayer()]
print("works fine")
local pActivePlayersTeam = pActivePlayer:GetTeam()
	if Teams[pActivePlayersTeam]:GetAtWarCount(true) > 0 then
	print("Receives Nationalism")
	pActivePlayer:SetHasPolicy(GameInfo.Policies["POLICY_NATIONALISM"].ID, true)
	end
end)

Now i need to be sure that i do receive policy. How to print() gold unit maintenance?
I want to increase gold maintenance for units, so that player will stick only to gold free military units number.
I know there is
<Row Name="INITIAL_GOLD_PER_UNIT_TIMES_100">
<Value>50</Value>
</Row>
<Row Name="INITIAL_FREE_OUTSIDE_UNITS">
<Value>3</Value>
</Row>
<Row Name="INITIAL_OUTSIDE_UNIT_GOLD_PERCENT">
<Value>0</Value>
</Row>
<Row Name="UNIT_MAINTENANCE_GAME_MULTIPLIER">
<Value>8</Value>
</Row>
<Row Name="UNIT_MAINTENANCE_GAME_EXPONENT_DIVISOR">
<Value>7</Value>
</Row>

But how to change UNIT_MAINTENANCE_GAME_MULTIPLIER/UNIT_MAINTENANCE_GAME_EXPONENT_DIVISOR to get something like 5 gold per unit?

And is there a way to increase gold free units? I wanted to create building/wonder that does it, but didn't found such option as "gold free units" for buildings/wonders.
Maybe i can change Handicap for GoldFreeUnits through lua right in the game, when players builds a new city for example?
 
Back
Top Bottom