Resolution to grant buildings?

TheOneHitPupper

Chieftain
Joined
Jun 15, 2017
Messages
98
There is no column or table under Resolutions that would grant the player a building once a resolution is passed/repealed. I've tried to make a workaround through lua but can't get it to work. This is what I have so far:
Code:
local NukeResolution = GameInfoTypes.RESOLUTION_NUCLEAR_NON_PROLIFERATION
local iEnrichmentFacility = GameInfoTypes.BUILDING_ENRICHMENT_FACILITY_DUMMY

print("GrantBuilding Function")
function ResolutionPassed(iResolution, iChoice, bEnact, bPassed)
    if NukeResolution then
        if bEnact and bPassed then
            pCity:SetNumRealBuilding(iEnrichmentFacility, 1)
            print("Adding in the Non-Proliferation Building function.")
        end
        if not bEnact and bPassed then
            pCity:SetNumRealBuilding(iEnrichmentFacility, 0)
            print("Removing the Non-Proliferation Building function.")
        end
    end
end

GameEvents.ResolutionResult.Add(ResolutionPassed)

I see that the script is being loaded in-game, but the GameEvent isn't firing correctly.

My goal is to have a dummy building given to players once the Nuclear Non-Proliferation Treaty resolution is passed. This dummy building will bar the player and AI to build Enrichment Facilities in the future.
 
The ResolutionResult GameEvent was added in my DLL (and anything based off it), if the event isn't firing, you almost certainly haven't enabled the EVENTS_RESOLUTIONS option
 
The ResolutionResult GameEvent was added in my DLL (and anything based off it), if the event isn't firing, you almost certainly haven't enabled the EVENTS_RESOLUTIONS option
I'm building the mod around the Community Patch mod with your DLL. How do I go about enabling EVENTS_RESOLUTIONS?
 
Your code is also never asking whether the resolution is the one you are interested in. You are merely asking whether "RESOLUTION_NUCLEAR_NON_PROLIFERATION" has been added as a valid resolution in the game database.

If "RESOLUTION_NUCLEAR_NON_PROLIFERATION" has been added to the game database, variable "NukeResolution" will have an integer ID value rather than a value of nil or boolean false.


This asks not whether the value currently stored for variable "NukeResolution" is equal to "GameInfoTypes.RESOLUTION_NUCLEAR_NON_PROLIFERATION" but instead asks whether the value held within the variable is nil or boolean false:
Code:
if NukeResolution then

An lua syntax of
Code:
if Something then
is evaluated as a boolean true statement so long as the value held within "Something" is neither nil nor boolean false. The statement will be evaluated as boolean true if the value held within the variable is numerical -1, numerical 27, text "false", text "true", is an lua table, is boolean true, or anything else that is not nil or boolean false.

You are never asking whether "NukeResolution" is equal to the passed integer ID value for "iResolution".
 
Your code is also never asking whether the resolution is the one you are interested in. You are merely asking whether "RESOLUTION_NUCLEAR_NON_PROLIFERATION" has been added as a valid resolution in the game database.

If "RESOLUTION_NUCLEAR_NON_PROLIFERATION" has been added to the game database, variable "NukeResolution" will have an integer ID value rather than a value of nil or boolean false.


This asks not whether the value currently stored for variable "NukeResolution" is equal to "GameInfoTypes.RESOLUTION_NUCLEAR_NON_PROLIFERATION" but instead asks whether the value held within the variable is nil or boolean false:
Code:
if NukeResolution then

An lua syntax of
Code:
if Something then
is evaluated as a boolean true statement so long as the value held within "Something" is neither nil nor boolean false. The statement will be evaluated as boolean true if the value held within the variable is numerical -1, numerical 27, text "false", text "true", is an lua table, is boolean true, or anything else that is not nil or boolean false.

You are never asking whether "NukeResolution" is equal to the passed integer ID value for "iResolution".
So I changed it to
Code:
local iResolution = GameInfoTypes.RESOLUTION_NUCLEAR_NON_PROLIFERATION
local iEnrichmentFacility = GameInfoTypes.BUILDING_ENRICHMENT_FACILITY_DUMMY

print("GrantBuilding Function")
function ResolutionPassed(iResolution, iChoice, bEnact, bPassed)
    if iResolution then
        if bEnact and bPassed then
            pCity:SetNumRealBuilding(iEnrichmentFacility, 1)
            print("Adding in the Non-Proliferation Building function.")
        end
        if not bEnact and bPassed then
            pCity:SetNumRealBuilding(iEnrichmentFacility, 0)
            print("Removing the Non-Proliferation Building function.")
        end
    end
end

GameEvents.ResolutionResult.Add(ResolutionPassed)
with the
Code:
if iResolution then
instead.

The lua log was showing a syntax error before, but now the game seems to accept the script. However, the function still isn't being executed. I'm not sure if I'm using the right GameEvent or if I need to enable an option in the DLL like whoward said.
 
IIRC

Code:
<?xml version="1.0" encoding="utf-8"?>
<GameData>
	<CustomModOptions>
		<Update>
			<Where Name="EVENTS_RESOLUTIONS"/>
			<Set Value="1"/>
		</Update>
	</CustomModOptions>
</GameData>
 
Since enabling EVENTS_RESOLUTIONS, the function fires and it correctly detects when the Resolution is enacted. The building is still not being granted. I'm having trouble with the syntax regarding the SetNumRealBuilding part. Here's what I have now:
Code:
local iEnrichmentFacility = GameInfoTypes.BUILDING_ENRICHMENT_FACILITY_DUMMY
local pPlayer = Players[iPlayer]

print("GrantBuilding Function")
function ResolutionPassed(iResolution, iChoice, bEnact, bPassed)
    if iResolution == GameInfoTypes.RESOLUTION_NUCLEAR_NON_PROLIFERATION then
        print("Resolution recognized as NNP")
        if bPassed then
            print("NNP Resolution passed")
            for pCity in pPlayer:Cities() do
                pCity:SetNumRealBuilding(iEnrichmentFacility, 1);
            end
            print("Adding in the NNP Building")
        end
        if not bPassed then
            print("NNP Resolution not passed")
            return
            print("Removing the NNP Building")
        end
    end
end

GameEvents.ResolutionResult.Add(ResolutionPassed)

I keep getting this error in my lua.log

Code:
[2239790.438] GrantBuilding: Resolution recognized as NNP
[2239790.454] GrantBuilding: NNP Resolution passed
[2239790.454] Runtime Error: F:\Documents\My Games\Sid Meier's Civilization 5\MODS\Tech\MoreTech (v1)\Resolutions/GrantBuilding.lua:10: attempt to index upvalue 'pPlayer' (a nil value)
 
You can never define a player object like this as you have at the root level of the lua script:
Code:
local pPlayer = Players[iPlayer]
"iPlayer" has no pre-assigned value and will be a nil value, so your code is saying
Code:
local pPlayer = Players[nil]
You need to execute a loop through all valid player Id #'s in the game, retrieveing the player object for each of these player ID #'s, determine whether that "pPlayer" object-variable is referencing a player who actually still alive and part of the game, and is not a Barbarian, and then execute through that player's cities with the Cities loop of
Code:
for pCity in pPlayer:Cities() do
You need to do this inside function ResolutionPassed after you have determined that the resolution is the one you are interested in.
 
So this is what I have now
Code:
local iEnrichmentFacility = GameInfoTypes.BUILDING_ENRICHMENT_FACILITY_DUMMY

print("GrantBuilding Function")
function ResolutionPassed(iResolution, iChoice, bEnact, bPassed)
    if iResolution == GameInfoTypes.RESOLUTION_NUCLEAR_NON_PROLIFERATION then
        print("Resolution recognized as NNP")
        if bEnact and bPassed then
            print("NNP Resolution passed")
            local pPlayer;
            for iPlayer=0, GameDefines.MAX_MAJOR_CIVS-1 do
                local Player = Players[iPlayer];
                if Player:IsAlive() then
                    if Player:GetCivilizationType() == civilizationID then
                        pPlayer = Player;
                        for pCity in pPlayer:Cities() do
                            pCity:SetNumRealBuilding(iEnrichmentFacility, 1);
                        end
                    end
                end
            end
            print("Adding in the NNP Building")
        end
        if not bEnact and bPassed then
            print("NNP Resolution not passed")
            return
            print("Removing the NNP Building")
        end
    end
end

GameEvents.ResolutionResult.Add(ResolutionPassed)

The Lua.log shows no errors and prints this
Code:
[2319534.235] GrantBuilding: Resolution recognized as NNP
[2319534.235] GrantBuilding: NNP Resolution passed
[2319534.235] GrantBuilding: Adding in the NNP Building

The building still isn't being given and I don't know why. It also seems like the script doesn't tell the difference from when the resolution is passed or if it fails and always executes through bEnact and bPassed.
 
change to
Code:
for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
This ensures the game's lua engine is not interpreting "GameDefines.MAX_MAJOR_CIVS-1" as all one variable name with a nil value. A for loop will not necessarily give an error in the log for there being a nil value in the limiter fields but the for loop will also not do anything. The game ought not to be seeing "GameDefines.MAX_MAJOR_CIVS-1" as all one long variable name, but I always provide spaces just to be sure within my own code.

What is in variable "civilizationID" ?
 
I've changed the variable above and removed the civilizationID line. The code runs and grants players the dummy building. The only problem I'm having now is that it doesn't differentiate when the resolution is passed or if it fails and gives the dummy building indiscriminately. The if bEnact and bPassed statements seem to be being ignored.

Code:
local iEnrichmentFacility = GameInfoTypes.BUILDING_ENRICHMENT_FACILITY_DUMMY

print("GrantBuilding Function")
function ResolutionPassed(iResolution, iChoice, bEnact, bPassed)
    if iResolution == GameInfoTypes.RESOLUTION_NUCLEAR_NON_PROLIFERATION then
        print("Resolution recognized as NNP")
        if bEnact and bPassed then
            print("NNP Resolution passed")
            local pPlayer;
            for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
                local Player = Players[iPlayer];
                if Player:IsAlive() then
                    pPlayer = Player;
                    for pCity in pPlayer:Cities() do
                        pCity:SetNumRealBuilding(iEnrichmentFacility, 1);
                    end
                end
            end
            print("Adding in the NNP Building")
        end
        if not bEnact and bPassed then
            print("NNP Resolution not passed")
            return
            print("Removing the NNP Building")
        end
    end
end

GameEvents.ResolutionResult.Add(ResolutionPassed)
 
Last edited:
Code:
print("bEnact is " .. tostring(bEnact))
print("bPassed is " .. tostring(bPassed))
This will cause a print line to be made in the lua log to tell you what the values of the two passed arguments actually are.

You need to use print statements as error logging tools a bit more throughout your code when it is not behaving as you expect.

Since what you are experiencing calls into question what you are getting for the two arguments, you need to string them so that you get a usable message telling you what variable is set to what. You cannot concatenate a Boolean or a nil with a text string for example so you need to use the "tostring(x)" syntax to translate whatever it is you are getting for those argument variables into text which can then be strung together with the rest of the print command to make is easier to understand which argument is getting which value. If you are getting "1" or "0" instead of Boolean true or false, for example, that in and of itself would explain why your code seems to be ignoring the values of these two argument variables.

You should also pull the data for "iChoice" and print it into the log because lua hooks receive argument data in specified orders regardless of what you name the argument-variables. You could be using misleading argument variable names because the order the four pieces of data are sent might not be what you/your code is expecting. Generally William's code tends to send the data in the order he has documented, but William is (horrors!) human and sometimes makes errors like the rest of us mortal types.
--------------------------------

And as an FYI this line
Code:
if not bEnact and bPassed then
is not going to give you what you appear to think it is. The "not" will only be applied on the first variable, not on both.
 
Last edited:
I've added print statements
Code:
local iEnrichmentFacility = GameInfoTypes.BUILDING_ENRICHMENT_FACILITY

print("GrantBuilding Function")
function ResolutionPassed(iResolution, iChoice, bEnact, bPassed)
    if iResolution == GameInfoTypes.RESOLUTION_NUCLEAR_NON_PROLIFERATION then
        print("Resolution recognized as NNP")
        if bEnact and bPassed then
            print("bEnact is " .. tostring(bEnact))
            print("iChoice is " .. tostring(iChoice))
            print("bPassed is " .. tostring(bPassed))
            local pPlayer;
            for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1 do
                local Player = Players[iPlayer];
                if Player:IsAlive() then
                    pPlayer = Player;
                    for pCity in pPlayer:Cities() do
                        pCity:SetNumRealBuilding(iEnrichmentFacility, 1);
                    end
                end
            end
            print("Adding in the NNP Building")
        end
        if not bEnact and not bPassed then
            return
        end
    end
end

GameEvents.ResolutionResult.Add(ResolutionPassed)

The Lua.log shows this whether the resolution passes or fails
Code:
[2347881.360] GrantBuilding: Resolution recognized as NNP
[2347881.360] GrantBuilding: bEnact is -1
[2347881.360] GrantBuilding: iChoice is 0
[2347881.360] GrantBuilding: bPassed is true
[2347881.360] GrantBuilding: Adding in the NNP Building
 
With bEnact equal to -1 and bPassed equal to Boolean true, this conditional querry is always going to be evaluated to Boolean true and the code within the "then" clause is going to be executed:
Code:
if bEnact and bPassed then
This is because neither bEnact nor bPassed are Boolean false and neither are nil.

This explains why your code is not operating the way you would expect so far as the logic within the lua script is concerned.

The larger problem is that the hook event is sending parameter data from the gamecore that isn't usable or is not meant to be used in the manner you are attempting to use it. Unfortunately it would appear to the former -- the hook event is sending gorsnitch to all listener functions.
 
That's what I feared. This is the post from whoward outlining the GameEvent from above. I have found a possible other option in getting this to work from a post by Enginseer here, but I'm not sure how to use IsResolutionPassed correctly.

upload_2018-11-30_11-34-39-png.510678


This post by Enginseer is the only reference to IsResolutionPassed used that I could find. Here's the function that he wrote:
Code:
function EverydayDiscoveringSomethingBrandNew(iPlayer, iCS, iGold, iUnitType, iPlotX, iPlotY)
    local pPlayer = Players[iPlayer]
    if pPlayer:GetEventChoiceCooldown(iSidon) ~= 0 then
        local iInfluence = OSFrog(10, 20)*(pPlayer:GetCurrentEra()+1)
        if iInfluence > 100 then iInfluence = 100 end
        Players[LostSidon]:ChangeMinorCivFriendshipWithMajor(Players[iPlayer], iInfluence)
        if pPlayer:GetEventChoiceCooldown(iSidon) > 2 and Game.IsResolutionPassed(iSphere, LostSidon) then
            Game.DoEnactResolution(iSphere, LostSidon, iPlayer)
        end
        if pPlayer:IsHuman() then
            pPlayer:AddNotification(NotificationTypes.NOTIFICATION_MET_MINOR, "You have pleased the leaders of Sidon with your diplomacy on other city-states earning you " .. iInfluence .. " [ICON_INFLUENCE] Influence with Sidon!", "Neighborhood Watch", pPlayer:GetCapitalCity():GetX(), pPlayer:GetCapitalCity():GetY())
        end
    end
end

GameEvents.PlayerBullied.Add(EverydayDiscoveringSomethingBrandNew)
 
I've added print statements
The Lua.log shows this whether the resolution passes or fails
Code:
[2347881.360] GrantBuilding: bEnact is -1

This is surprising, as the C++ code is
Code:
GAMEEVENTINVOKE_HOOK(GAMEEVENT_ResolutionResult, pProposal->GetType(), iDecision, true, pProposal->IsPassed(GetVotesSpentThisSession()));
GAMEEVENTINVOKE_HOOK(GAMEEVENT_ResolutionResult, pProposal->GetType(), pProposal->GetProposerDecision()->GetDecision(), false, pProposal->IsPassed(iTotalSessionVotes));
(The first parameter in the code is the event to call, then the second C++ parameter becomes the first Lua parameter, etc)
And the values passed to bEnact are "boolean true" or "boolean false". Similiar code is used for other events and these come through as "Lua true" and "Lua false", so no sure what's going on here.

However, if you're sure the value for bEnact is -1, it will always be -1 so you can test for that instead. (If this is the case, I also suspect you're getting 0 instead of false, so the test should be "bEnact ~= 0")


EDIT: As an update, if C++ Boolean true and false really aren't coming out as Lua true and false, then the following events are also suffering the same issue
CityBoughtPlot
CityConstructed
CityCreated
CityPrepared
CityTrained
MinorAlliesChanged
MinorFriendsChanged
MinorGift
PlayerGoldenAge
QuestSendNotification
QuestStart
ResolutionResult
UnitCaptured
UnitUpgraded
 
Last edited:
Back
Top Bottom