Using LUA to prevent unit upgrade?

Discussion in 'Civ5 - Creation & Customization' started by sman1975, Jun 21, 2018.

Tags:
  1. sman1975

    sman1975 Emperor

    Joined:
    Aug 27, 2016
    Messages:
    1,246
    Location:
    Dallas, TX
    Greetings,

    I'm working on a mod that adds units throughout the tech tree, for example, it adds 8 UUs, one for each Era of the normal game.

    I'd like to make it possible to upgrade a unit to the next Era's version, once a civ discovers the prereq tech (pretty easy to do).

    I'd also like to limit the number of each Era's units (also easy to do using the MaxPlayerInstances element).

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

    My problem is that I'd like to limit the total number of units at 3 for each Era, for a max of 24 total units, assuming you never upgraded any units.

    Unfortunately, when it's possible to upgrade a unit, the game lets you do this - and does not check the MaxPlayerInstances numbers before upgrading the unit.

    This means I can build 3 "ancient" units. When I get to "classical" I can build 3 "classical" units, then upgrade the 3 "ancient" units. I now have 6 "classical" units.

    Ultimately, I can end up with 24 "Information" units if I plan accordingly. This is definitely game breaking, as these latter units are pretty OP.

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

    I can think of some LUA ways of preventing a player for "producing" a given Era unit if there are already too many fielded. But I still can't figure out a way of preventing an upgrade if there are too many of that Era's units already in the game.

    Does anyone have any suggestions on how to pull this off?

    Thanks!
     
  2. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,570
    Location:
    Near Portsmouth, UK
  3. sman1975

    sman1975 Emperor

    Joined:
    Aug 27, 2016
    Messages:
    1,246
    Location:
    Dallas, TX
    Thank you, Mr. whoward69! I didn't see this event in the modiki, and forgot to look at that extended list of events in the reference you sent. Great tip, BTW!

    I looked over the example in your "Units - Multiple Upgrades" mod. Here is the admittedly bare-bones/suboptimal solution I got working. It limits a civ's ability to upgrading units to a total of 3 of the higher unit. I'll expand it later to put in the limits on specific units later, but here is the basic function:

    Code:
    g_iTotalUnitsPerClass = 3
    
    function OnCanHaveAnyUpgrade(iPlayer, iUnit)                                                                    -- Function determines if an upgrade is possible, based on number of higher units
        local pPlayer = Players[iPlayer]                                                                        -- Set the player pointer
        local pUnit = pPlayer:GetUnitByID(iUnit)                                                                -- Set the unit pointer
        local iUpgradeUnitType = pUnit:GetUpgradeUnitType()                                                        -- Get the upgrade unit type
        local iUpgradeUnitClass = GameInfo.Units[iUpgradeUnitType].Class                                        -- Get the class of the upgrade unit
        local iUpgradeUnitClassType = GameInfo.UnitClasses["" .. iUpgradeUnitClass .. ""].ID                    -- Convert the class key to the ID
        local iUpgradeUnitClassCount = pPlayer:GetUnitClassCount("" .. iUpgradeUnitClassType .. "")    or g_iTotalUnitsPerClass        -- Get the total upgrade unit class count        
        if iUpgradeUnitClassCount >= g_iTotalUnitsPerClass then                                                    -- If the number of upgrade units is more than the amount allowed, then...
            return false                                                                                        -- Return false: no more upgrades are allowed
        end
        return true                                                                                                -- Return true, if the number of upgrade units is less than the limit
    end
    GameEvents.CanHaveAnyUpgrade.Add(OnCanHaveAnyUpgrade)

    The function works exactly as I want it to, except for one small UI problem: the tooltip on the Unit Panel on the now grayed-out "upgrade" button. It shows the same text as it does when there's no restriction on upgrading the unit.

    Here is a picture of the issue:

    upload_2018-6-22_14-5-4.jpeg

    Is there any way, short of replacing UnitPanel.lua, to update that tooltip with a "too many units" error message, or simply call it "good enough" and then a day?

    Thanks!
     
  4. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    7,241
    Location:
    Illinois, USA
    1. Somewhat simplified
      Code:
      g_iTotalUnitsPerClass = 3
      
      function OnCanHaveAnyUpgrade(iPlayer, iUnit)							-- Function determines if an upgrade is possible, based on number of higher units
          local pPlayer = Players[iPlayer]								-- Set the player pointer
          local pUnit = pPlayer:GetUnitByID(iUnit)							-- Set the unit pointer
          local iUpgradeUnitType = pUnit:GetUpgradeUnitType()						-- Get the upgrade unit type
          local sUpgradeUnitClass = GameInfo.Units[iUpgradeUnitType].Class				-- Get the class of the upgrade unit
          local iUpgradeUnitClassCount = pPlayer:GetUnitClassCount(GameInfoTypes[sUpgradeUnitClass])	-- Get the total upgrade unit class count        
          if iUpgradeUnitClassCount >= g_iTotalUnitsPerClass then					-- If the number of upgrade units is more than the amount allowed, then...
              return false										-- Return false: no more upgrades are allowed
          end
          return true											-- Return true, if the number of upgrade units is less than the limit
      end
      GameEvents.CanHaveAnyUpgrade.Add(OnCanHaveAnyUpgrade)
    2. You don't need the syntax like here
      Code:
      "" .. iUpgradeUnitClass .. ""
      You can directly state the viariable name you have inserted either a text string or an ID # into, so long as the string or the ID # exists within the table.
    3. If you did this you'd get a nil value error because there's no such thing as UNIT_CHEESEBURGLER
      Code:
      local iUnitType = GameInfoTypes.UNIT_CHEESEBURGLER
      local sUnitClass = GameInfo.Units[iUnitType].Class
      local iUnitClassID = GameInfoTypes[sUnitClass]
      print(iUnitClassID)
      But this is fine
      Code:
      local iUnitType = GameInfoTypes.UNIT_SWORDSMAN
      local sUnitClass = GameInfo.Units[iUnitType].Class
      local iUnitClassID = GameInfoTypes[sUnitClass]
      print(iUnitClassID)
    4. For the issue with the unit panel, you'd have to re-write the unit-panel lua file
     
    sman1975 likes this.
  5. sman1975

    sman1975 Emperor

    Joined:
    Aug 27, 2016
    Messages:
    1,246
    Location:
    Dallas, TX
    @LeeS - appreciate the help optimizing the code. I put in the changes and, surprise-surprise, it worked beautifully... :lol:

    And thanks also for letting me know what I had suspected: there simply isn't a way to update that "upgrade unit" tooltip without rewriting the UnitPanel.lua. I know that a lot of mods replace that UI already, so one should only add a change like that if it's somehow worth breaking compatibility with a vast number of very popular mods. In this particular case (an inadequate tooltip), it's not.

    Thanks again - appreciate the help learning how to write better code!
     

Share This Page