1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Resolution to grant buildings?

Discussion in 'Civ5 - Creation & Customization' started by TheOneHitPupper, Feb 22, 2020.

  1. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    84
    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.
     
  2. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,399
    Location:
    Near Portsmouth, UK
    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
     
  3. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    84
    I'm building the mod around the Community Patch mod with your DLL. How do I go about enabling EVENTS_RESOLUTIONS?
     
  4. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    6,751
    Location:
    Illinois, USA
    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".
     
  5. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    84
    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.
     
  6. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,399
    Location:
    Near Portsmouth, UK
    IIRC

    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <GameData>
    	<CustomModOptions>
    		<Update>
    			<Where Name="EVENTS_RESOLUTIONS"/>
    			<Set Value="1"/>
    		</Update>
    	</CustomModOptions>
    </GameData>
    
     
  7. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    84
    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)
    
     
  8. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    6,751
    Location:
    Illinois, USA
    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.
     
  9. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    84
    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.
     
  10. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    6,751
    Location:
    Illinois, USA
    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" ?
     
  11. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    84
    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: Feb 23, 2020
  12. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    6,751
    Location:
    Illinois, USA
    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: Feb 23, 2020
  13. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    84
    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
     
  14. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    6,751
    Location:
    Illinois, USA
    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.
     
  15. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    84
    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.



    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)
     
  16. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,399
    Location:
    Near Portsmouth, UK
    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: Feb 26, 2020

Share This Page