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

[DISCONTINUED] Help with making resources obsolete?

Discussion in 'Civ5 - Creation & Customization' started by TheOneHitPupper, Jul 26, 2019.

  1. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    39
    I'm trying to make a tech tree overhaul mod and have certain early-game resources that I want to disappear/change to another resource from the map. This is the code I have so far.

    Code:
    GameEvents.TeamSetHasTech.Add(function(iTeam, iTech, bAdopted)
        local pTeam = Teams[iTeam]
        local iPlayer = Game.GetActivePlayer()
        local pPlayer = Players[iPlayer]
        if iTech == GameInfoTypes.TECH_BIOLOGY then     
            print ("Obsolete");
            pTeam(ChangeResource(pPlot))     
        end
    end
    
    
    function ChangeResource(pPlot)
        if (pPlot:GetResourceType() == GameInfoTypes.RESOURCE_IRON) then        --Get resource type
            print ("ChangeResource: iron found");
            local quantity = {}
                quantity[1] = 1;
                quantity[2] = 1;
                quantity[3] = 1;
                quantity[4] = 1;
                quantity[5] = 2;
                quantity[6] = 2;
                quantity[7] = 2;
                quantity[8] = 3;
            print ("ChangeResource: quantity set");
            local spawn = {}
                spawn[1] = GameInfoTypes.RESOURCE_PEARLS;
                spawn[2] = GameInfoTypes.RESOURCE_CRAB;
                spawn[3] = GameInfoTypes.RESOURCE_FISH;
                spawn[4] = GameInfoTypes.RESOURCE_WHALE;
                spawn[5] = GameInfoTypes.RESOURCE_OIL;
            print ("ChangeResource: resource set");
            pPlot:SetResourceType(spawn[math.random(1,5)], quantity[math.random(1,8)]);
            print ("ChangeResource: new resource spawned");
        end
    end
    I have Iron set as the resource for testing purposes. It doesn't seem to execute at all. None of the print lines are making their way into the Lua.log and I'm at a loss. I'm sure there's multiple errors in my code as I struggle with Lua. Anyone have any ideas?
     
  2. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    6,449
    Location:
    Illinois, USA
    Fatal syntax error here:
    Code:
    GameEvents.TeamSetHasTech.Add(function(iTeam, iTech, bAdopted)
        local pTeam = Teams[iTeam]
        local iPlayer = Game.GetActivePlayer()
        local pPlayer = Players[iPlayer]
        if iTech == GameInfoTypes.TECH_BIOLOGY then     
            print ("Obsolete");
            pTeam(ChangeResource(pPlot))     
        end
    end
    You have no closing ")" character where needed so the game is attempting to parse your entire file as one long function and is not succeeding. Corrected code for the missing ")":
    Code:
    GameEvents.TeamSetHasTech.Add(function(iTeam, iTech, bAdopted)
        local pTeam = Teams[iTeam]
        local iPlayer = Game.GetActivePlayer()
        local pPlayer = Players[iPlayer]
        if iTech == GameInfoTypes.TECH_BIOLOGY then     
            print ("Obsolete");
            pTeam(ChangeResource(pPlot))     
        end
    end)
    -----------------------------------

    Neither of these lines accomplish anything:
    Code:
        local iPlayer = Game.GetActivePlayer()
        local pPlayer = Players[iPlayer]
    You define a player object based on the human player in the game, and then never actually use the object for anything.

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

    This is also fatal syntax:
    Code:
    pTeam(ChangeResource(pPlot))
    1. You are attempting to tell the game to use a "Team" method called "ChangeResource()" because that is the way lua will interpret that line of code, if it were syntaxed correctly.
    2. Since there is no "Team" method called "ChangeResource()" you would get a fatal nil value error even if you alterred your code to
      Code:
      pTeam:ChangeResource(pPlot)
    3. You are defining a function called "ChangeResource" but a function is not the same as an object method.
    4. In order to "call" a function you do not attempt to "attach" the function to an object, you just directly activate the function, like this:
      Code:
      GameEvents.TeamSetHasTech.Add(function(iTeam, iTech, bAdopted)
          local pTeam = Teams[iTeam]
          local iPlayer = Game.GetActivePlayer()
          local pPlayer = Players[iPlayer]
          if iTech == GameInfoTypes.TECH_BIOLOGY then     
              print ("Obsolete");
              ChangeResource(pPlot)     
          end
      end)
    5. I would not use "TeamSetHasTech". I would use "TeamTechResearched". I don't anymore remember all the ins and outs between the two hook-events, but I know "TeamTechResearched" will work in the way desired.
    6. Regardless of which event-hook you use, it is necessary to look through all the players in the game to determine if they are members of the team.
      • "Game.GetActivePlayer()" will always give you the ID # of the Human Player in a Single Player game, and in a Multi-Player game such as a Hot-Seat game will give you the ID # of the human player currently taking their turn. It will not necessarily give you an ID # for a player that is even a member of the team that researched the given technology.
    7. The last problem(s) here are that (a) you are referencing a plot object called "pPlot" but that plot-object is never defined anywhere, so lua interprets that variable not as a pointer to a map-plot, but as a nil value. And, (b), you would need to examine all plots owned by the player (ie, the member(s) of the team) and alter the resource(s) as needed.

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

    Code:
    function ChangeResource(pPlot)
        if (pPlot:GetResourceType() == GameInfoTypes.RESOURCE_IRON) then        --Get resource type
            print ("ChangeResource: iron found");
            local quantity = {}
                quantity[1] = 1;
                quantity[2] = 1;
                quantity[3] = 1;
                quantity[4] = 1;
                quantity[5] = 2;
                quantity[6] = 2;
                quantity[7] = 2;
                quantity[8] = 3;
            print ("ChangeResource: quantity set");
            local spawn = {}
                spawn[1] = GameInfoTypes.RESOURCE_PEARLS;
                spawn[2] = GameInfoTypes.RESOURCE_CRAB;
                spawn[3] = GameInfoTypes.RESOURCE_FISH;
                spawn[4] = GameInfoTypes.RESOURCE_WHALE;
                spawn[5] = GameInfoTypes.RESOURCE_OIL;
            print ("ChangeResource: resource set");
            pPlot:SetResourceType(spawn[math.random(1,5)], quantity[math.random(1,8)]);
            print ("ChangeResource: new resource spawned");
        end
    end
    1. As previously mentioned you are passing a nil value to this function in the "pPlot" argument, so the function will never do anything except generate a fatal syntax error for attempting to "Index" a nil value.
    2. No plot that could have iron on it should ever have a sea resource placed on the same plot.
    3. When altering the resource that is on the plot via an lua script it is necessary first to remove any improvement that may be on the plot. The order usually needed is:
      1. Remove improvement
        Code:
        pPlot:SetImprovementType(-1)
      2. remove resource
        Code:
        pPlot:SetResourceType(-1);
      3. place new resource
      4. replace improvement if the improvement is valid for the new resource
     
    TheOneHitPupper likes this.
  3. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    39
    Ok so I've changed the script to

    Code:
    GameEvents.TeamTechResearched.Add(function(iTeam, iTech, bAdopted)
        local pTeam = Teams[iTeam]
        if iTech == GameInfoTypes.TECH_BIOLOGY then  
            print ("Obsolete");
            ChangeResource(pPlot)
        end
    end)
    
    
    function ChangeResource(pPlot)
        if (pPlot:GetResourceType() == GameInfoTypes.RESOURCE_IRON) then
            pPlot:SetImprovementType(-1)
            pPlot:SetResourceType(-1);
            print ("ChangeResource: iron deleted");
            local quantity = {}
                quantity[1] = 1;
                quantity[2] = 1;
                quantity[3] = 1;
                quantity[4] = 1;
                quantity[5] = 2;
                quantity[6] = 2;
                quantity[7] = 2;
                quantity[8] = 3;
            print ("ChangeResource: quantity set");
            local spawn = {}
                spawn[1] = GameInfoTypes.RESOURCE_GOLD;
                spawn[2] = GameInfoTypes.RESOURCE_COPPER;
            print ("ChangeResource: resource set");
            pPlot:SetResourceType(spawn[math.random(1,2)], quantity[math.random(1,8)]);
            print ("ChangeResource: new resource spawned");
        end
    end
    
    
    
    So I changed the GameEvents function to TeamTechResearched instead and removed the unnecessary lines. As for the ChangeResource(pPlot) function, I've added in the resource and improvement being removed provision you mentioned. Lastly, I'm unsure how to examine and define all of the tiles that the player owns so that I can replace the pPlot variable and make it work.
     
  4. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,360
    Location:
    Near Portsmouth, UK
    Unfortunately it's more complicated than that. If the plot is owned by a city (and most will be), you need to
    a) if the tile is being worked, remove the worker.
    b) if the tile is improved, remove the improvement
    c) remove the tile from being owned by the city
    d) remove the resource
    e) add the new resource
    f) make the tile owned by the city
    g) add any required improvement
    h) work the tile if need be
    (This is how I remember it, the full logic is in IGE, cut down logic for horses etc can be found in my Herdsmen mod)

    Note, that you cannot do this for the tile the city is on, so if the city was founded on the resource you cannot change it.

    Note also, that if you do this for the AI, any units and/or buildings that require the resource will now put the AI "out of resource" with all the associated penalties - and the AI really doesn't understand what to do about this
     
    TheOneHitPupper likes this.
  5. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    39
    Dang looks like it probably isn't worth the effort if it'll confuse the AI. Yet another mod idea stored away haha. Appreciate the help guys!
     
  6. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,360
    Location:
    Near Portsmouth, UK
    (For completeness …) Forgot to add that if there's a worker on the plot currently building an improvement, you'll need to cancel their action
     
  7. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    6,449
    Location:
    Illinois, USA
    Yeah, I had forgotten the need to do all that other, er, "stuff". I remember now it's why I stopped making code for altering existing plot resources that were owned or being worked by a city.
     
    TheOneHitPupper likes this.
  8. TheOneHitPupper

    TheOneHitPupper Chieftain

    Joined:
    Jun 15, 2017
    Messages:
    39
    Right? The last project I was working on had similar problems. Too complicated for not much pay-off imo.
     

Share This Page