[DISCONTINUED] Help with making resources obsolete?

TheOneHitPupper

Chieftain
Joined
Jun 15, 2017
Messages
98
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?
 
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
 
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

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.
 
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.

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
 
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
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!
 
Unfortunately it's more complicated than that ...

(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
 
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.
 
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.
Right? The last project I was working on had similar problems. Too complicated for not much pay-off imo.
 
Top Bottom