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

DLL - Various Mod Components

Discussion in 'Civ5 - Mod Components' started by whoward69, Nov 4, 2012.

  1. ifLaMaster

    ifLaMaster Chieftain

    Joined:
    Jan 21, 2015
    Messages:
    24
    Oh, i see. Well, at least it work. :)
     
  2. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,532
    Location:
    Near Portsmouth, UK
    Two new GameEvents in v88 for handling the World Congress / UN resolutions.

    The first to override what resolution(s) an AI will propose
    GameEvents.ResolutionProposing.Add(function(iPlayer, iLeague) return false; end)

    The second to override what proposal(s) (including Host and World Leader) an AI will vote for
    GameEvents.ResolutionVoting.Add(function(iPlayer, iLeague) return false; end)

    You can either reprogam the default (DLL hard-coded) AI's logic for proposing/voting in the World Congress, or TC modders can completely repurpose the World Congress when used with event (added in v51)
    GameEvents.ResolutionResult.Add(function(iResolution, iChoice, bEnact, bPassed) end)

    All are enabled via the EVENTS_RESOLUTIONS option, both new ones bring interesting and exciting new ways to crash the DLL - so take care with them!


    As a (cut-down) example, the following changes the way the AI votes in the WC from being concerned with what it gains from each proposal to a more politically orientated one (the AI will tend to vote with its allies and against its enemies). See "Resolutions - Political Voting" for the complete code.

    Spoiler :
    Code:
        
    local iResolutionWorldLeader = GameInfoTypes.RESOLUTION_DIPLOMATIC_VICTORY
    local iResolutionHost = GameInfoTypes.RESOLUTION_CHANGE_LEAGUE_HOST
    local iResolutionEmbargo = GameInfoTypes.RESOLUTION_PLAYER_EMBARGO
    
    local sDecisionYesNo = "RESOLUTION_DECISION_YES_OR_NO"
    
    local kChoiceNo = 0;
    local kChoiceYes = 1;
    
    --
    -- [B]Main voting functions[/B] - World Leader, Host and Proposals
    -- Return true if ALL remaining votes used
    --
    function [B]CastVotesForWorldLeader[/B](iPlayer, iLeague, proposal)
      local pLeague = Game.GetLeague(iLeague)
      local iNumVotes = pLeague:GetRemainingVotesForMember(iPlayer)
      local iProposedPlayer = -1
      print(string.format("CastVotesForWorldLeader: %s with %i votes", Players[iPlayer]:GetName(), iNumVotes))
    
      ------
      ------ FOR TESTING ONLY, USE THE SAME DECISION MAKING PROCESS AS FOR THE HOST
      ------
      return CastVotesForHost(iPlayer, iLeague, proposal)
    end
    
    function [B]CastVotesForHost[/B](iPlayer, iLeague, proposal)
      local pLeague = Game.GetLeague(iLeague)
      local iCurrentHost = pLeague:GetHostMember()
      local iNumVotes = pLeague:GetRemainingVotesForMember(iPlayer)
      local iProposedPlayer = -1
      print(string.format("CastVotesForHost: %s with %i votes", Players[iPlayer]:GetName(), iNumVotes))
    
      -- Set iProposedPlayer to our preferred host, or leave at -1 for the standard (DLL hard-coded) AI decision
      if (iCurrentHost == iPlayer) then
        -- I'm the host, always vote for myself
        iProposedPlayer = iCurrentHost
      else
        local pPlayer = Players[iPlayer]
    
        if (pPlayer:IsDoF(iCurrentHost)) then
          -- I have a DoF with the current host, so vote for them
          iProposedPlayer = iCurrentHost
        else
          -- Including myself, find the player I have a DoF with who has the largest number of votes (in the case of a tie, the strongest) and vote for them
          iProposedPlayer = iPlayer
          local iMostVotes = iNumVotes
    
          local iDecision = GameInfo.ResolutionDecisions[GameInfo.Resolutions[proposal.ID].VoterDecision].ID
          for _, iChoice in ipairs(pLeague:GetChoicesForDecision(iDecision, iPlayer)) do
            if (iChoice ~= iPlayer) then
              if (pPlayer:IsDoF(iChoice)) then
                local iVotes = pLeague:GetRemainingVotesForMember(iChoice)
    
                -- I have a DoF with this player, are they in a better position to win?
                if (iVotes > iMostVotes or (iVotes == iMostVotes and Players[iChoice]:GetPower() > Players[iProposedPlayer]:GetPower())) then
                  iProposedPlayer = iChoice
                  iMostVotes = iVotes
                end
              end
            end
          end
        end
      end
    
      if (iProposedPlayer and iProposedPlayer ~= -1) then
        print(string.format("  voting for %i (%s)", iProposedPlayer, Players[iProposedPlayer]:GetName()))
        pLeague:DoVoteEnact(proposal.ID, iPlayer, iNumVotes, iProposedPlayer)
        return true
      end
    
      return false
    end
    
    function [B]CastVotesForProposals[/B](iPlayer, iLeague, enactProposals, repealProposals)
      local pLeague = Game.GetLeague(iLeague)
      local iNumVotes = pLeague:GetRemainingVotesForMember(iPlayer)
      print(string.format("CastVotesForProposals: %s with %i votes", Players[iPlayer]:GetName(), iNumVotes))
    
      -- If not all votes are cast, the default logic in the DLL will allocate the rest
      local bVoted = (
        CastVotesAgainstEnactEmbargoMe(iPlayer, pLeague, enactProposals) or
        CastVotesForEnactMyProposal(iPlayer, pLeague, enactProposals) or
        CastVotesForRepealMyProposal(iPlayer, pLeague, repealProposals)
      )
    
      return bVoted
    end
    
    
    --
    -- [B]Sub-functions for voting [/B]for/against specific proposals.
    -- Return true if ALL remaining votes used
    --
    function [I]CastVotesAgainstEnactEmbargoMe[/I](iPlayer, pLeague, proposals)
      local iNumVotes = pLeague:GetRemainingVotesForMember(iPlayer)
    
      local temp = GetProposalsByTypeOnPlayer(proposals, iResolutionEmbargo, iPlayer)
    
      if (#temp > 0) then
        -- Vote against an embargo on me!
        print(string.format("%s voting AGAINST an ENACT of an embargo on them", Players[iPlayer]:GetName()))
        pLeague:DoVoteEnact(temp[1].ID, iPlayer, iNumVotes, kChoiceNo)
        return true
      end
    
      return false
    end
    
    function [I]CastVotesForEnactMyProposal[/I](iPlayer, pLeague, proposals)
      local iNumVotes = pLeague:GetRemainingVotesForMember(iPlayer)
    
      local proposal = GetProposalByPlayer(proposals, iPlayer)
    
      if (proposal and IsYesNoDecision(proposal)) then
        -- Vote for my proposal
        print(string.format("%s voting FOR their own proposal (ENACT)", Players[iPlayer]:GetName()))
        pLeague:DoVoteEnact(proposal.ID, iPlayer, iNumVotes, kChoiceYes)
        return true
      end
    
      return false
    end
    
    function [I]CastVotesForRepealMyProposal[/I](iPlayer, pLeague, proposals)
      local iNumVotes = pLeague:GetRemainingVotesForMember(iPlayer)
    
      local proposal = GetProposalByPlayer(proposals, iPlayer)
    
      if (proposal and IsYesNoDecision(proposal)) then
        -- Vote for my proposal
        print(string.format("%s voting FOR their own proposal (REPEAL)", Players[iPlayer]:GetName()))
        pLeague:DoVoteRepeal(proposal.ID, iPlayer, iNumVotes, kChoiceYes)
        return true
      end
    
      return false
    end
    
    
    --
    -- [B]Voting helper functions[/B]
    --
    function [I]GetProposalByPlayer[/I](proposals, iPlayer)
      for _, proposal in ipairs(proposals) do
        if (proposal.ProposalPlayer == iPlayer) then
          return proposal
        end
      end
    
      return nil
    end
    
    function [I]GetProposalsByTypeOnPlayer[/I](proposals, iType, iPlayer)
      local temp = {}
    
      for _, proposal in ipairs(proposals) do
        if (proposal.Type == iType and proposal.ProposerDecision == iPlayer) then
          table.insert(temp, proposal)
        end
      end
    
      return temp
    end
    
    function [I]IsYesNoDecision[/I](proposal)
      return (GameInfo.Resolutions[proposal.Type].VoterDecision == sDecisionYesNo)
    end
    
    
    --
    -- [B]Main proposing function[/B]
    -- Return true if ALL remaining proposals used
    --
    function [B]Propose[/B](iPlayer, pLeague)
      local bProposed = (
        ProposeRepealEmbargoMe(iPlayer, pLeague) or
        ProposeRepealEmbargoHost(iPlayer, pLeague) or
        ProposeEnactEmbargoHost(iPlayer, pLeague)
      )
      
      return bProposed
    end
    
    
    --
    -- [B]Sub-functions for specific proposals[/B]
    -- Return true if all proposals made
    --
    function [I]ProposeRepealEmbargoMe[/I](iPlayer, pLeague)
      if (pLeague:IsPlayerEmbargoed(iPlayer)) then
        RepealEmbargo(iPlayer, pLeague, iPlayer)
      end
    
      return (pLeague:GetRemainingProposalsForMember(iPlayer) == 0)
    end
    
    function [I]ProposeRepealEmbargoHost[/I](iPlayer, pLeague)
      local iCurrentHost = pLeague:GetHostMember()
    
      if (iCurrentHost ~= iPlayer and pLeague:IsPlayerEmbargoed(iCurrentHost)) then
        local pPlayer = Players[iPlayer]
    
        if (pPlayer:IsDoF(iCurrentHost)) then
            RepealEmbargo(iPlayer, pLeague, iCurrentHost)
        end
      end
    
      return (pLeague:GetRemainingProposalsForMember(iPlayer) == 0)
    end
    
    function [I]ProposeEnactEmbargoHost[/I](iPlayer, pLeague)
      local iCurrentHost = pLeague:GetHostMember()
    
      if (iCurrentHost ~= iPlayer and not pLeague:IsPlayerEmbargoed(iCurrentHost)) then
        local pPlayer = Players[iPlayer]
    
        -- If iPlayer is at war with, or really hates, the host ...
        if (pPlayer:IsAtWarWith(iCurrentHost) or pPlayer:GetMajorCivApproach(iCurrentHost) == MajorCivApproachTypes.MAJOR_CIV_APPROACH_HOSTILE) then
            EnactEmbargo(iPlayer, pLeague, iCurrentHost)
        end
      end
    
      return (pLeague:GetRemainingProposalsForMember(iPlayer) == 0)
    end
    
    
    --
    -- [B]Proposal helper functions[/B]
    --
    function [I]EnactEmbargo[/I](iPlayer, pLeague, iEmbargoedPlayer)
      if (pLeague:CanProposeEnact(iResolutionEmbargo, iPlayer, iEmbargoedPlayer)) then
        print(string.format("%s proposing to ENACT an embargo on %s", Players[iPlayer]:GetName(), Players[iEmbargoedPlayer]:GetName()))
        pLeague:DoProposeEnact(iResolutionEmbargo, iPlayer, iEmbargoedPlayer)
      end
    end
    
    function [I]RepealEmbargo[/I](iPlayer, pLeague, iEmbargoedPlayer)
      local iProposal
    
      for _, proposal in ipairs(pLeague:GetActiveResolutions()) do
        if (proposal.Type == iResolutionEmbargo and proposal.ProposerDecision == iEmbargoedPlayer) then
          iProposal = proposal.ID
          break
        end
      end
    
      if (iProposal and pLeague:CanProposeRepeal(iProposal, iPlayer)) then
        print(string.format("%s proposing to REPEAL an embargo on %s", Players[iPlayer]:GetName(), Players[iEmbargoedPlayer]:GetName()))
        pLeague:DoProposeRepeal(iProposal, iPlayer)
      end
    end
    
    
    --
    -- [B]Main event handlers[/B]
    --
    function [B]OnResolutionProposing[/B](iPlayer, iLeague)
      print(string.format("OnResolutionProposing(%s)", Players[iPlayer]:GetName()))
      local pLeague = Game.GetLeague(iLeague)
    
      return Propose(iPlayer, pLeague)
    end
    GameEvents.ResolutionProposing.Add(OnResolutionProposing)
    
    function [B]OnResolutionVoting[/B](iPlayer, iLeague)
      print(string.format("OnResolutionVoting(%s)", Players[iPlayer]:GetName()))
      local pLeague = Game.GetLeague(iLeague)
    
      local enactProposals = pLeague:GetEnactProposals()
      local repealProposals = pLeague:GetRepealProposals()
      local iProposal = (#enactProposals == 1) and enactProposals[1].Type
    
      local bVoted
      if (#enactProposals == 1 and #repealProposals == 0 and (iProposal == iResolutionWorldLeader or iProposal == iResolutionHost)) then
        if (iProposal == iResolutionWorldLeader) then
          bVoted = CastVotesForWorldLeader(iPlayer, iLeague, enactProposals[1])
        else
          bVoted = CastVotesForHost(iPlayer, iLeague, enactProposals[1])
        end
      else
        bVoted = CastVotesForProposals(iPlayer, iLeague, enactProposals, repealProposals)
      end
    
      return bReturn
    end
    GameEvents.ResolutionVoting.Add(OnResolutionVoting)
    
     
  3. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,532
    Location:
    Near Portsmouth, UK
    v88 uploaded to my web-site and GitHub

    For changes, see post above
     
  4. Serp

    Serp King

    Joined:
    Apr 1, 2015
    Messages:
    646
    Is there a mod that adjusts the NaturalWonderFirstFinderGold Bonus to the game speed?
    At the moment for spain it is always 500, regardless of the gamespeed.

    I thought about modifying the NaturalWonderPopUp.lua with help of GameEvents.NaturalWonderDiscovered (getting the set amount and multiply it with gamespeed), but here again the problem is, that a popup only works in singleplayer. In mulitplayer I'm sure the "OnPopUp" function is never called, so I don't know a way to get the initial gold amount a player should get...

    Do you know a solution?
     
  5. Serp

    Serp King

    Joined:
    Apr 1, 2015
    Messages:
    646
    Where exactly can I see all the new functions you added? I mean functions like GetXY you added to DLL.
    Is there any function that checks/returns all adjacent plots? I would like to check if a city is adjacent to a specific plot, without the need to add all the plotmath...

    edit:
    and how does your UI-diary mod work? I only see the diary options on the top right, but where is the diary itself?
     
  6. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,532
    Location:
    Near Portsmouth, UK
    No one place, they are in various posts across these forums

    Easiest way to find them all is to search CvLua*.h for LUAAPIEXTN, but the ones you're interested in are

    Code:
    	LUAAPIEXTN(IsOnFeature, bool, iFeatureType);
    	LUAAPIEXTN(IsAdjacentToFeature, bool, iFeatureType);
    	LUAAPIEXTN(IsWithinDistanceOfFeature, bool, iFeatureType, iDistance);
    	LUAAPIEXTN(IsOnImprovement, bool, iImprovementType);
    	LUAAPIEXTN(IsAdjacentToImprovement, bool, iImprovementType);
    	LUAAPIEXTN(IsWithinDistanceOfImprovement, bool, iImprovementType, iDistance);
    	LUAAPIEXTN(IsOnPlotType, bool, iPlotType);
    	LUAAPIEXTN(IsAdjacentToPlotType, bool, iPlotType);
    	LUAAPIEXTN(IsWithinDistanceOfPlotType, bool, iPlotType, iDistance);
    	LUAAPIEXTN(IsOnResource, bool, iResourceType);
    	LUAAPIEXTN(IsAdjacentToResource, bool, iResourceType);
    	LUAAPIEXTN(IsWithinDistanceOfResource, bool, iResourceType, iDistance);
    	LUAAPIEXTN(IsOnTerrain, bool, iTerrainType);
    	LUAAPIEXTN(IsAdjacentToTerrain, bool, iTerrainType);
    	LUAAPIEXTN(IsWithinDistanceOfTerrain, bool, iTerrainType, iDistance);
    	LUAAPIEXTN(CountFeature, int, iFeature);
    	LUAAPIEXTN(CountWorkedFeature, int, iFeature);
    	LUAAPIEXTN(CountImprovement, int, iImprovement);
    	LUAAPIEXTN(CountWorkedImprovement, int, iImprovement);
    	LUAAPIEXTN(CountPlotType, int, iPlotType);
    	LUAAPIEXTN(CountWorkedPlotType, int, iPlotType);
    	LUAAPIEXTN(CountResource, int, iResource);
    	LUAAPIEXTN(CountWorkedResource, int, iResource);
    	LUAAPIEXTN(CountTerrain, int, iTerrain);
    	LUAAPIEXTN(CountWorkedTerrain, int, iTerrain);
    
     
  7. Serp

    Serp King

    Joined:
    Apr 1, 2015
    Messages:
    646
    thank you :)

    But as far as I see, there is nothing to find out if there is a player city within a given radius...
    Only terrain, ressource, feature, plottype and improvement =/
     
  8. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,532
    Location:
    Near Portsmouth, UK
    I sometimes wonder why I write this stuff ;)

    And you can avoid the "plot maths" by using the plot iterator helper functions I wrote some years back
     
  9. Serp

    Serp King

    Joined:
    Apr 1, 2015
    Messages:
    646
    To be honest, often your sentences are quite short and we are not 100% clear what you mean ;)
    E.g this sentence, I first thought I could see tooltips when I hover over the date IN the diary. Not that the tooltips showing up when hovering over the date ARE the diary...
    I got it now?

    Thank you very much ! :)
    Yes you wrote alot great stuff!

    Maybe make another thread, post there a list of links to great stuff like this and pin the thread in your signature? :)
     
  10. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,532
    Location:
    Near Portsmouth, UK
    Yeah, it was as much a dig at myself as anyone - don't forget I'm British and we only do sarcasm as humour :D

    Like this?
     
  11. Serp

    Serp King

    Joined:
    Apr 1, 2015
    Messages:
    646
    Bookmarked, thanks :)

    About the NaturalWonderFirstFinderGold from Spain:
    I set this value in database to 0 and distribute this gold bonus in lua only, depending on gamespeed and send a generic notification now.
    Of course this won't be compatible to any mods that change these database values, but I don't know a better solution.
     
  12. poooh

    poooh Chieftain

    Joined:
    Feb 21, 2013
    Messages:
    18
    Location:
    The East Pole
    Hello,

    Is there any way to control a Guild Great Work/Artifact? The guild slots aren't available in Culture menu.
     
  13. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,532
    Location:
    Near Portsmouth, UK
  14. Serp

    Serp King

    Joined:
    Apr 1, 2015
    Messages:
    646
    Hey whoward :)

    Could you please take look at this list
    http://forums.civfanatics.com/showpost.php?p=14357088&postcount=125
    And tell me if you know any of your mods, that is not compatible for multiplayer? E.g uses ActivePlayer to do some game changes or simular ?
    Of course it could be also an mistake I made, but if you know that any of these won't work, it would be good to know :)
     
  15. qqqbbb

    qqqbbb Prince

    Joined:
    Sep 25, 2010
    Messages:
    530
    pPlayer:CountAllResource(iResourceType) does not return correct value on BuildFinished event when you get new resource by building citadel.
    When you build a citadel, BuildFinished event fires before you get new plots. Can this be fixed?
     
  16. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,532
    Location:
    Near Portsmouth, UK
    Use the PlayerBuilt event
     
  17. Serp

    Serp King

    Joined:
    Apr 1, 2015
    Messages:
    646
    Were should I post possible bugs from the "AI - MP Diplomacy" mod from JaiDerHerr?
    Here or should I try to contact JdH directly, but were.. is he at this forum?

    Someone reported at my modpack thread:
     
  18. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,532
    Location:
    Near Portsmouth, UK
    This.
     
  19. seamus2010

    seamus2010 Chieftain

    Joined:
    Jun 23, 2013
    Messages:
    66
    I still need an answer to this question. WARMONGER_THREAT_AGGRIEVED_PERCENT doesn't seem to do anything for me.
     
  20. Serp

    Serp King

    Joined:
    Apr 1, 2015
    Messages:
    646
    Hey whoward :)
    I found out that the mod that causes desync is ironically the
    AI - MP Diplomacy mod.

    Could you please take a look at your implementation, if something there causes the problem?
    Everytime when a player accepts an offer from AI, we will get the loading screen.
    Also without accepting it, there is every few rounds (3-5) a loading screen (maybe because AI trades with AI?).
    After I deactivated this mod, we had no more loading screens.

    If there is nothing about your implementation, could you please tell me how to contact JdH ? I wrote him at http://civforum.de/ , but he wasn't active there over a year =/
     

Share This Page