Get an error with attempting to read a setting

Place to get help with not working mods / modding interface.
Sesame_Slayer
Burner Inserter
Burner Inserter
Posts: 14
Joined: Wed Aug 10, 2022 10:12 pm
Contact:

Get an error with attempting to read a setting

Post by Sesame_Slayer »

I have been trying to make a mod to either move all effects from the logistic system tech to logistic robotics, or simply remove utility science pack as both a prerequisite and needed pack, and change the count from 500 to 150, with these modes interchangeable via settings. I get an error I had gotten before with mismatched parenthesis, but there is none, and it claims that the "earlierlogisticsmainsetting" on line 13 is the error, even though the same line is in line 2, except with "merge" instead of "changepack". If there is any other errors in the code, it would be nice to mention them, as it seems no matter what I fix, there is always a problem. Please note I am not good at modding, and the error is probably obvious.

Code: Select all

script.on_init(function()
    if settings.global["earlierlogisticsmainsetting"].value == "merge" then
        table.insert(data.raw["technology"]["logistic-robotics"].effects, {type = "unlock-recipe",recipe = "logistic-chest-active-provider"})
        table.insert(data.raw["technology"]["logistic-robotics"].effects, {type = "unlock-recipe",recipe = "logistic-chest-buffer"})
        table.insert(data.raw["technology"]["logistic-robotics"].effects, {type = "unlock-recipe",recipe = "logistic-chest-requester"})
        if data.raw.technology["logistic-system"] then
	    data.raw.technology["logistic-system"] = null
        end
    end
end)

script.on_init(function()
    if settings.global["earlierlogisticsmainsetting"].value == "changepack" then
        if data.raw.technology["logistic-system"] then
            data.raw.technology["logistic-system"].prerequisites =
            {
              "logistic-robotics",
              "chemical-science-pack",
            }
            data.raw.technology["logistic-system"].unit.count = 150
            data.raw.technology["logistic-system"].unit.ingredients =
            {
                {"automation-science-pack", 1},
                {"logistic-science-pack", 1},
                {"chemical-science-pack", 1}
            }
        end
    end
end)
Edit: I have also browsed the forums for solutions, but none of them worked.
Half the time, I'm half asleep.
Pi-C
Smart Inserter
Smart Inserter
Posts: 1725
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Get an error with attempting to read a setting

Post by Pi-C »

Sesame_Slayer wrote: Mon Aug 29, 2022 10:30 pm I have been trying to make a mod to either move all effects from the logistic system tech to logistic robotics, or simply remove utility science pack as both a prerequisite and needed pack, and change the count from 500 to 150, with these modes interchangeable via settings.
What type of settings are you using? This concerns the definition of prototypes, so setting_type should be "startup" instead of "runtime-global".
I get an error I had gotten before with mismatched parenthesis, but there is none, and it claims that the "earlierlogisticsmainsetting" on line 13 is the error, even though the same line is in line 2, except with "merge" instead of "changepack".
In the first block you define a function that should be called when the game is initialized. The second block overwrites that with another function. When the game starts, only the second function will be run, so naturally it won't complain about errors from the function in your first block.
If there is any other errors in the code, it would be nice to mention them, as it seems no matter what I fix, there is always a problem. Please note I am not good at modding, and the error is probably obvious.
You should read this tutorial on modding, and you should definitely read about the data life cycle, and when you're done, go back to start and read about the data life cycle again and again. If you want to start modding Factorio, that's probably the most important text you can read. :-)

Code: Select all

script.on_init(function()
    if settings.global["earlierlogisticsmainsetting"].value == "merge" then
        table.insert(data.raw["technology"]["logistic-robotics"].effects, {type = "unlock-recipe",recipe = "logistic-chest-active-provider"})
        table.insert(data.raw["technology"]["logistic-robotics"].effects, {type = "unlock-recipe",recipe = "logistic-chest-buffer"})
        table.insert(data.raw["technology"]["logistic-robotics"].effects, {type = "unlock-recipe",recipe = "logistic-chest-requester"})
        if data.raw.technology["logistic-system"] then
	    data.raw.technology["logistic-system"] = null
        end
    end
end)
The most obvious mistake here is that you want to modify prototypes during the control stage. You've defined a handler for script.on_init() -- but this doesn't exist before the control stage, while prototypes are defined in the data stage. So, put your code in data.lua, get rid of the control stage wrapper, and correct the setting type:

Code: Select all

if settings.startup["earlierlogisticsmainsetting"].value == "merge" then
        table.insert(data.raw["technology"]["logistic-robotics"].effects, {type = "unlock-recipe",recipe = "logistic-chest-active-provider"})
        table.insert(data.raw["technology"]["logistic-robotics"].effects, {type = "unlock-recipe",recipe = "logistic-chest-buffer"})
        table.insert(data.raw["technology"]["logistic-robotics"].effects, {type = "unlock-recipe",recipe = "logistic-chest-requester"})
        if data.raw.technology["logistic-system"] then
	    data.raw.technology["logistic-system"] = null
        end
end
That's just the first step. As you've demonstrated yourself:

Code: Select all

        if data.raw.technology["logistic-system"] then
	    data.raw.technology["logistic-system"] = null
        end
mods may remove stuff that you take for granted. So why are you so sure that data.raw["technology"]["logistic-robotics"].effects really exists? You're not alone, and if somebody is playing with your mod, chances are they will have other mods loaded as well. Don't ever take anything for granted but make sure the things you want to access really exist!

Code: Select all

local my_setting = settings.startup["earlierlogisticsmainsetting"]
if my_setting and my_setting.value == "merge" then

  local tech = data.raw["technology"]["logistic-robotics"]

  if tech then
    tech.effects = tech.effects or {}

    table.insert(tech.effects, {type = "unlock-recipe",recipe = "logistic-chest-active-provider"})
    table.insert(tech.effects, {type = "unlock-recipe",recipe = "logistic-chest-buffer"})
    table.insert(tech.effects, {type = "unlock-recipe",recipe = "logistic-chest-requester"})
  end

  if data.raw.technology["logistic-system"] then
    data.raw.technology["logistic-system"] = null
  end
end
About "logistic-system": Don't overwrite the technology! You're not alone, other mods may expect that the technology exists and could break if you removed it! Instead, you should disable and hide it:

Code: Select all

  tech = data.raw.technology["logistic-system"]
  if tech then
    tech.enabled = false
    tech.hidden = true
  end
Here's the complete code for your first setting:

Code: Select all

local my_setting = settings.startup["earlierlogisticsmainsetting"]
if my_setting and my_setting.value == "merge" then

  local tech = data.raw.technology["logistic-robotics"]

  if tech then
    tech.effects = tech.effects or {}

    table.insert(tech.effects, {type = "unlock-recipe", recipe = "logistic-chest-active-provider"})
    table.insert(tech.effects, {type = "unlock-recipe", recipe = "logistic-chest-buffer"})
    table.insert(tech.effects, {type = "unlock-recipe", recipe = "logistic-chest-requester"})
  end

  tech = data.raw.technology.["logistic-system"]
  if tech then
    tech.enabled = false
    tech.hidden = true
  end
end
I'll leave fixing the code for the second part to you as a practical exercise. :-D

By the way, your old code for removing "logistic-system" probably contained an error:

Code: Select all

    data.raw.technology["logistic-system"] = null
There is no such thing as "null" in Lua, it's called "nil". Nevertheless, this would have worked incidentally: The game would regard "null" as the name of a variable. But as that variable never was defined, it would actually have the value "nil".
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
Sesame_Slayer
Burner Inserter
Burner Inserter
Posts: 14
Joined: Wed Aug 10, 2022 10:12 pm
Contact:

Re: Get an error with attempting to read a setting

Post by Sesame_Slayer »

Thanks, this has been a great help. The setting type is startup, it's a string setting. The settings tutorial didn't separate the methods for each type, so I used that. The code for removing a technology I found on the forums, on a 3-year old post. I looked for a way to check if the technology has any other ones requiring it, but gave up. Perhaps for the merge setting, I could leave the tech there, but remove the effects, in case mods want to use it. I assume the thing for changing the count in the 2nd setting will be an error.

However, I get an error in the 14th line (tech = data.raw.technology.["logistic-system"]) saying that:

Code: Select all

<name> expected near '['
I assume this is due to the "...technology.[logistic..." instead of "...technology[logistic..."

fixed. This mod is done.
Half the time, I'm half asleep.
Sesame_Slayer
Burner Inserter
Burner Inserter
Posts: 14
Joined: Wed Aug 10, 2022 10:12 pm
Contact:

Re: Get an error with attempting to read a setting

Post by Sesame_Slayer »

I've received a suggestion for it asking to add another mod's tech (crux chests) to it. How would I go about adding more technologies? redefine tech to the new tech, add your code to it, repeat that with the other tech, and disable and hide the techs? I don't really know what half this code does, because I sort of suck at reading code, and I don't know how to edit this to add more techs. also, in the code for inserting effects into Logistics Robotics, I think I can simplify it to just have one line saying table.insert(tech.effects), but I hate the process of bug testing, so I'll ask if that will work too.

Edit: putting table.insert(tech.effects) doesn't work. I don't get errors with this code, but none of the effects are transferred. how would I go about this? the changepack mode works fine. Additionally, effects other than the 3 logistics chests were actually not transferred, which is a big problem.
data.lua:

Code: Select all

local my_setting = settings.startup["earlierlogisticsmainsetting"]
if my_setting and my_setting.value == "merge" then

  local tech = data.raw.technology["logistic-robotics"]

  if tech then
    tech.effects = tech.effects or {}

    table.insert(tech.effects, {type = "unlock-recipe", recipe = "logistic-chest-buffer"})
  end

  tech = data.raw.technology["logistic-system"]
  if tech then
    tech.enabled = false
    tech.hidden = true
  end

  if mods["cruxchests"] then
    tech = data.raw.technology["cruxchests-tech2"]
    if tech then
      tech.enabled = false
      tech.hidden = true
    end

    tech = data.raw.technology["cruxchests-tech3"]
    if tech then
      tech.enabled = false
      tech.hidden = true
    end
  end
end

local my_setting = settings.startup["earlierlogisticsmainsetting"]
if my_setting and my_setting.value == "changepack" then

  tech = data.raw.technology["logistic-system"]

  if tech then
    tech.prerequisites =
    {
      "logistic-robotics",
      "chemical-science-pack",
    }
    tech.unit.count = 150
    tech.unit.ingredients =
    {
      {"automation-science-pack", 1},
      {"logistic-science-pack", 1},
      {"chemical-science-pack", 1}
    }
  end

  if mods["cruxchests"] then

    tech = data.raw.technology["cruxchests-tech3"]

    if tech then
      tech.unit.ingredients =
      {
        {"automation-science-pack", 1},
        {"logistic-science-pack", 1},
        {"chemical-science-pack", 1}
      }
    end
  end
end
Half the time, I'm half asleep.
Post Reply

Return to “Modding help”