Editing effects of every module

Place to get help with not working mods / modding interface.
Schmee
Manual Inserter
Manual Inserter
Posts: 3
Joined: Fri Jul 26, 2024 10:55 am
Contact:

Editing effects of every module

Post by Schmee »

As the title says I'm trying to edit the positive and negative effects of every module in the game, including ones added by other mods. I have two versions of the mod, one of them works fine and the other doesn't.

This version only affects the vanilla modules, I've tested it and it works fine:

Code: Select all

--data.lua

m = settings.startup["module-good-multiplier"].value
n = settings.startup["module-bad-multiplier"].value

data.raw["module"]["effectivity-module"].effect = {
  consumption = {bonus = -0.3*m}
}

data.raw["module"]["effectivity-module-2"].effect = {
  consumption = {bonus = -0.4*m}
}

data.raw["module"]["effectivity-module-3"].effect = {
  consumption = {bonus = -0.5*m}
}

data.raw["module"]["productivity-module"].effect = {
  consumption = {bonus = 0.4*n},
  pollution = {bonus = 0.05*n},
  productivity = {bonus = 0.04*m},
  speed = {bonus = -0.15*n}
}

data.raw["module"]["productivity-module-2"].effect = {
  consumption = {bonus = 0.6*n},
  pollution = {bonus = 0.075*n},
  productivity = {bonus = 0.06*m},
  speed = {bonus = -0.15*n}
}

data.raw["module"]["productivity-module-3"].effect = {
  consumption = {bonus = 0.8*n},
  pollution = {bonus = 0.1*n},
  productivity = {bonus = 0.1*m},
  speed = {bonus = -0.15*n}
}

data.raw["module"]["speed-module"].effect = {
  consumption = {bonus = 0.5*n},
  speed = {bonus = 0.2*m}
}

data.raw["module"]["speed-module-2"].effect = {
  consumption = {bonus = 0.6*n},
  speed = {bonus = 0.3*m}
}

data.raw["module"]["speed-module-3"].effect = {
  consumption = {bonus = 0.7*n},
  speed = {bonus = 0.5*m}
}
However this doesn't account for modules added by other mods. So I made this version:

Code: Select all

--data.lua

m = settings.startup["module-good-multiplier"].value
n = settings.startup["module-bad-multiplier"].value

for k, x in ipairs(data.raw.module) do
  if (x.effect.consumption.bonus > 0) then 
    x.effect.consumption.bonus = x.effect.consumption.bonus * n
  elseif (x.effect.consumption.bonus < 0) then 
    x.effect.consumption.bonus = x.effect.consumption.bonus * m
  end
  if (x.effect.pollution.bonus > 0) then 
    x.effect.pollution.bonus = x.effect.pollution.bonus * n
  elseif (x.effect.pollution.bonus < 0) then 
    x.effect.pollution.bonus = x.effect.pollution.bonus * m
  end
  if (x.effect.speed.bonus > 0) then 
    x.effect.speed.bonus = x.effect.speed.bonus * m
  elseif (x.effect.speed.bonus < 0) then 
    x.effect.speed.bonus = x.effect.speed.bonus * n
  end
  if (x.effect.productivity.bonus > 0) then 
    x.effect.productivity.bonus = x.effect.productivity.bonus * m
  elseif (x.effect.productivity.bonus < 0) then 
    x.effect.productivity.bonus = x.effect.productivity.bonus * n
  end
end
This version doesn't work, the mod will successfully load but none of the modules change their effects, not even the vanilla ones.

Any advice on how to do this?
robot256
Smart Inserter
Smart Inserter
Posts: 1018
Joined: Sun Mar 17, 2019 1:52 am
Contact:

Re: Editing effects of every module

Post by robot256 »

1) The x table in the loop may not actually be linked to the table in data.raw. At the end of your for loop, try adding the line

Code: Select all

data.raw.module[k]=x
2) Since you want to edit stats of existing prototypes, try changing your filename from data.lua to data-final-fixes.lua . That way it will run after most other mods have added things in the data and data-updates phases.
Schmee
Manual Inserter
Manual Inserter
Posts: 3
Joined: Fri Jul 26, 2024 10:55 am
Contact:

Re: Editing effects of every module

Post by Schmee »

I've done both of those, and the mod still does nothing. I tried Ctrl-Shift-F on a module and it doesn't seem to have been affected by the mod at all.

I think the issue has to come from the way I'm iterating through the lua table, I have the syntax wrong or something. If I'm checking the 'effect' property of something without an 'effect', it would return Nil and the lua code would basically skip all the If statements.
Pi-C
Smart Inserter
Smart Inserter
Posts: 1742
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Editing effects of every module

Post by Pi-C »

Schmee wrote: Fri Jul 26, 2024 11:05 am

Code: Select all

for k, x in ipairs(data.raw.module) do
	…
end
This version doesn't work, the mod will successfully load but none of the modules change their effects, not even the vanilla ones.

Any advice on how to do this?
Try this instead:

Code: Select all

for k, x in pairs(data.raw.module) do
	…
end
You can use 'ipairs' for arrays indexed with subsequent numbers:

Code: Select all

local test = {}

-- Create table {3, 6, 9, 12, 15}
for i = 1, 5 do
  test[i] = i * 3
end

-- Write to log: '1: 3', '2: 6', …
for k, v in ipairs(test) do
  log(k..": "..v)
end
But the tables in data.raw[type] are indexed by name! The way 'ipairs' works is, it is looking for the field with index '1' (a number, not a string!) first, then increments the index by 1, then looks for the field with the new index, … As the table is indexed with string values, a field indexed with number 1 is not found, so the 'ipairs' returns nil and the code inside the for-loop is never reached. Using 'pairs' instead of 'ipairs', you can iterate all table fields -- whatever their index.

Related, there is another distinction between arrays indexed with subsequent numbers and tables with other indexes. Whenever you can use 'ipairs', you can get the number of elements in the array with '#array_name'. Whenever you must use 'pairs', you must use 'table_size(table_name)' instead.

EDIT: Why use 'ipairs' at all if it won't work all the time? Because it's more efficient than 'pairs' (iterating over a known list of indexes is easier than iterating over arbitrary indexes)! If you use it correctly, your mod will be a bit more efficient as well. It's safe to use when you know that you have an array indexed with subsequent numbers -- for example the results of LuaSurface::find_entities().

If you haven't done so yet, you should read up on the Factorio-specific Lua modifications.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
Schmee
Manual Inserter
Manual Inserter
Posts: 3
Joined: Fri Jul 26, 2024 10:55 am
Contact:

Re: Editing effects of every module

Post by Schmee »

Thank you, that solved it! It now works with vanilla modules and SE modules, and presumably any other mod's modules too.

I had to check if each type of module effect existed before I changed the bonus, otherwise it refused to load. But this is the working version:

Code: Select all

--data-final-fixes.lua

m = settings.startup["module-good-multiplier"].value
n = settings.startup["module-bad-multiplier"].value

for k, x in pairs(data.raw.module) do
  if x.effect.consumption then
    if (x.effect.consumption.bonus > 0) then 
      x.effect.consumption.bonus = x.effect.consumption.bonus * n
    else 
      x.effect.consumption.bonus = x.effect.consumption.bonus * m
    end
  end
  if x.effect.pollution then
    if (x.effect.pollution.bonus > 0) then 
      x.effect.pollution.bonus = x.effect.pollution.bonus * n
    else 
      x.effect.pollution.bonus = x.effect.pollution.bonus * m
    end
  end
  if x.effect.speed then
    if (x.effect.speed.bonus > 0) then 
      x.effect.speed.bonus = x.effect.speed.bonus * m
    else 
      x.effect.speed.bonus = x.effect.speed.bonus * n
    end
  end
  if x.effect.productivity then
    if (x.effect.productivity.bonus > 0) then 
      x.effect.productivity.bonus = x.effect.productivity.bonus * m
    else 
      x.effect.productivity.bonus = x.effect.productivity.bonus * n
    end
  end
  data.raw.module[k]=x
end
Pi-C
Smart Inserter
Smart Inserter
Posts: 1742
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Editing effects of every module

Post by Pi-C »

Schmee wrote: Sat Jul 27, 2024 7:17 am

Code: Select all

for k, x in pairs(data.raw.module) do
  …
  data.raw.module[k]=x
end
You don't need

Code: Select all

data.raw.module[k]=x
here!
robot256 wrote: Fri Jul 26, 2024 2:09 pm 1) The x table in the loop may not actually be linked to the table in data.raw. At the end of your for loop, try adding the line

Code: Select all

data.raw.module[k]=x
Agreed, it's easy to mess up things by working with an unlinked table. But assigning values should always work:

Code: Select all

for k, v in pairs(some_table) do
	v = v + 1
end
What will cause problems is removing elements:

Code: Select all

-- Not working as expected
for k, v in pairs(some_table) do 
  if v > 100 then
    v = nil		-- Unlinks v and sets it to nil, but doesn't affect some_table
  end
end
  
-- Will work as expected
for k, v in pairs(some_table) do 
  if v > 100 then
    some_table[k] = nil  -- Actually clears the field in some_table
  end
end
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
Post Reply

Return to “Modding help”