You're not understanding how "hooks" for Civ5, and variables and functions work whether for Civ5 or just standard lua usable in any program that makes use of lua.
This definition
Code:
void Events.WarStateChanged(TeamID team1, TeamID team2, bool war)
from the page I linked you to earlier is specific to a civ5 implementation and means the following:
- "void" means that any function subscribed to this game event does not return any value to the gamecore for processing by the game's core execution code
- "Events.WarStateChanged" specifies a type of event (often referred to as a "hook") that fires information from the gamecore to any function in lua that is "subscribed" to "listen" (ie, is "hooked") to the event. Firaxis pre-determines under what game-conditions each specific event will fire (ie, what triggers it) and what data is passed as arguments to any lua function that is hooked to each specific event. There can theoretically be an infinite number of different functions all running in the same or different mods which are "hooked" to "listen" to any single pre-defined event.
- "(TeamID team1, TeamID team2, bool war)" tells you what arguments are passed from the gamecore to any lua function "hooked" to the event, and what type of data will be passed.
- TeamID team1, tells us that the 1st argument will be sent data for the team ID number of the 1st player team. Since team IDs are always integer values this will therefore be an integer type of data.
- TeamID team2, tells us that the 2nd argument will be sent data for the team ID number of the 2nd player team. Since team IDs are always integer values this will therefore be an integer type of data.
- bool war tells us that the 3rd argument will be sent data for whether or not the change in war-state was a declaration of war, and that boolean true or false will be passed. In the case of a war being declared the data passed will be boolean true.
- I do not now remember whether "team1" will be the team that initiated the war/peace change, or merely the lower-numbered team ID number.
-----------------------------------------------------------------------------
When you "subscribe" a function to a "hook" you need one of two syntax methods, but I prefer the one I will show:
Code:
Events.WarStateChanged.Add(SomeFunctionName)
This will "subscribe" whatever function we define as
SomeFunctionName to the event "hook", and function
SomeFunctionName will be activated with the pertinent argument data every time a war-state changes in-game.
Code:
function SomeFunctionName(Team1, Team2, War)
if (War == false) then
print("Someone Made Peace")
end
end
Events.WarStateChanged.Add(SomeFunctionName)
As written this does not actually do much other than print to the log whenever the change in war-status between two teams is not a declaration of war.
-----------------------------------------------------------------------------
Note that instead of putting in
(TeamID team1, TeamID team2, bool war) with a desired value on the line that starts the function definition, I merely state variable-names this particular function will use for the three arguments the gamecore passes to the hooked function, ie,
(Team1, Team2, War). You can call the variables you are going to use within the function anything you want since these names are really only data-holders for the info the game passes to the function. So I could also call the names of the three arguments
Code:
function SomeFunctionName(Cheeseburgers, Hamburgers, Tomato)
So long as I use these variable names properly within the function I am making (ie, correct for the data that is passed to each argument-variable from the gamecore) all will still work. I can therefore do
Code:
function SomeFunctionName(Cheeseburgers, Hamburgers, Tomato)
if (Tomato == false) then
print("Someone Made Peace")
end
end
Events.WarStateChanged.Add(SomeFunctionName)
As a general rule you should assign variable-names in your function defining line that make sense for the type of data that the gamecore passes for that argument.
-----------------------------------------------------------------------------
As to the code you posted:
Code:
local civilizationID = GameInfoTypes["CIVILIZATION_COSTA_RICA"]
function PeaceDealBonus(playerID)
local pTeam = Teams[teamID]
for teamID = 0, GameDefines.MAX_CIV_TEAMS - 1 do
if pPlayer ~= nil and player:GetCivilizationType() == civilizationID then
CostaRica = pTeam
break
end
end
local AliveTeamCount = pGame:CountCivTeamsAlive()
local Gold = math.floor(2000 / AliveTeamCount)
for CostaRica do
pTeam:ChangeGold(Gold)
end
end
Events.WarStateChanged(false war) --could change to 'peace'
Your code will not work as written given your misunderstanding of how hooks, listener functions, and argument names work. But you also have some more basic problems:
- Here you are attempting to create a team object variable
Code:
local pTeam = Teams[teamID]
But this cannot work since you are using an undefined variable called teamID.
- Here you are attempting to use two different player object variable-names (pPlayer and player), neither of which have been previously defined, and are therefore assigned a value of "nil" by lua:
Code:
if pPlayer ~= nil and player:GetCivilizationType() == civilizationID then
- Here you are defining a variable called CostaRica but it will be given a value of "nil" since you are setting it equal to another variable that will have a value of "nil" as mentioned before
- This has three different incorrect usages:
Code:
local AliveTeamCount = pGame:CountCivTeamsAlive()
- pGame has never been defined anywhere and therefore has a value of "nil"
- "Game" methods do not require nor want an "object" variable, and are always stated as "Game." because there is never more than one game at a time.
- Game methods use "." syntax instead of ":" syntax so the correct way to access that info is
Code:
local AliveTeamCount = Game.CountCivTeamsAlive()
- Here you are attempting to throw an object variable into a for loop as its "limiter":
Code:
for CostaRica do
pTeam:ChangeGold(Gold)
end
This is both uneccessary and would not work anyway. You would simply just state
However, see the next item:
- There is no "Team" method called ChangeGold() so you cannot do
Also, since as noted above, pTeam is holding a value of "nil", you cannot run any "Team" methods on it: lua will simply generate an error from attempting to "Index" a nil value. What you want to change a player's gold is the player method
Code:
PlayerObjectVariableName:ChangeGold(Gold)
But you first need to have a valid player object variable name defined, with a valid value -- you then stick this valid player object variable name in place of the variable-name I called PlayerObjectVariableName for example purposes.
- This would cause the game to generate a fatal file syntax error because it is telling the game to assign a function called false war as a "listener" subscribed to the Events.WarStateChanged hook-event
Code:
Events.WarStateChanged(false war)
No such function with that name exists within the lua file.
-----------------------------------------------------------------------------
Assuming I understand what you are currently going for, I would write the code as:
Code:
local civilizationID = GameInfoTypes["CIVILIZATION_COSTA_RICA"]
--create boolean flag for whether peace effect applies when one of players making peace is a Costa Rica player
local bApplyWhenCostaRicaInvolved = false
--create tables and boolean to track active Costa Rica players
local tCostaRicaPlayerIDs, tCostaRicaTeamIDs, bCostaRicaActive = {}, {}, false
--get the Costa Rica player's ID and Team ID numbers and stick these in the lua tables
for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
local pLoopPlayer = Players[iPlayer]
if pLoopPlayer:IsEverAlive() and (pLoopPlayer:GetCivilizationType() == civilizationID) then
local iLoopTeam = pLoopPlayer:GetTeam()
table.insert(tCostaRicaPlayerIDs, {PlayerID=iPlayer, TeamID=iLoopTeam})
if not tCostaRicaTeamIDs[iLoopTeam] then
tCostaRicaTeamIDs[iLoopTeam] = {}
end
table.insert(tCostaRicaTeamIDs[iLoopTeam], iPlayer)
bCostaRicaActive = true
end
end
function PeaceTreatySigned(Team1, Team2, War)
if (War == false) then
print("Someone Made Peace")
local bExecuteEffect = false
local Gold = math.floor(2000 / Game.CountCivTeamsAlive())
if (bApplyWhenCostaRicaInvolved == true) then
bExecuteEffect = true
else --this will run when (bApplyWhenCostaRicaInvolved == false)
if (not tCostaRicaTeamIDs[Team1]) and (not tCostaRicaTeamIDs[Team2]) then
bExecuteEffect = true
end
end
if (bExecuteEffect == true) then
for key,Data in ipairs(tCostaRicaPlayerIDs) do
local pPlayer = Players[Data.PlayerID]
pPlayer:ChangeGold(Gold)
end
end
end
end
function OnLoadScreenClose()
Events.WarStateChanged.Add(PeaceTreatySigned)
end
if (bCostaRicaActive == true) then
--delay actual event hook to the Events.LoadScreenClose so that game reload does not cause the code to fire
--the code will also never execute if Costa Rica is not part of the current game
Events.LoadScreenClose.Add(OnLoadScreenClose)
end
Since City-States also have Teams and follow their allies into war (and peace), you'll get multiple firings of the code if the players involved in the peace deal are allied to city-states, which may or may not be over-powered. The code as written does not account for issues related to city-states following Major players into war and peace.