msakuta / Factorio-LateUpgrades-Mod

A Mod for Factorio that adds many upgrades for late game
0 stars 2 forks source link

More configurable mod #4

Open OvermindDL1 opened 8 years ago

OvermindDL1 commented 8 years ago

In the file ./prototypes/technology/common.lua in the function createupgrade it sets the prerequisites via:

    prerequisites = {params.neededscience},

First problem I see is that a given upgrade could only have one prerequisite, which is probably fine in most cases but it might be better to do this instead:

    prerequisites = params.neededscience,

And in all the upgrade file wrap the existing pre-requisite up with {}.

However, have you thought about restructuring the mod to be more 'generally' configurable instead of specific sections like this, to instead of being called as it is to be called like this instead (based on the logistic-robot-speed.lua and logistic-robot-stacksize.lua files due to their different exponential styles):

-- This would be some helper file, just a couple examples, extend as wanted

function mult(m)
  return function(level, previousValue)
    return previousValue + (level * m)
  end
end

function expo(e)
  return function(level, previousValue)
    return math.floor(previousValue * (2 ^ (level * e)))
  end
end

-- This could be in the config.lua file, lots of lines like this for different researches

extendResearch(5, 25, "logistic-robot-speed-", {
  time=mult(10),
  count=expo(1/3),
  modifier=mult(0.05)
  }

extendResearch(5, 25, "worker-robots-storage-", {
  time=mult(10),
  count=expo(1/2),
  modifier=mult(0.05)
  }

-- and so forth more

Where extendResearch(template, final, baseName, options) or so, the template is the 'template' to copy, so since "logistic-robot-speed-5" exists it will then clone that, change it to 6, since it is not '1' it will update the pre-reqs from the '4' to '5', leaving the rest alone, then it will apply the above functions of options.time, options.count, options.modifier, and whatever other options you want to supply (with reasonable defaults for non-existing ones). Once it made 6 then it would make 7 by using 6 as the template (could just recursively call yourself until template>final then early return). This pattern would let it be completely configurable within the config file, keeps it small and readable, lets it be more expandable for other research lines that other mods may add, and if someone wants to do something custom they could just define the function inline like count=function(level, previousValue) previousValue * level end, or whatever they may want. And if someone wants to, say, add science-pack-4 starting on worker-robots-storage research 10 then they could just do extendResearch(5, 9, "worker-robots-storage-", {...etc...}) then add their own special 10 as normal factorio-lua way then do extendResearch(10, 25, "worker-robots-storage-", {...etc...}) to start using their new level 10 as the new template with their special research (although it would probably be better to have an option in extendResearch to add, remove, or completely override existing ingredients so you could do something like this instead of defining a whole new recipe extendResearch(9, 25, "worker-robots-storage-", {...etcOtherOptions... ingredient={add={{"science-pack-4", 1},}}) as this would allow an easy way to override starting right after your template level).

It would probably also be nice to ignore already existing researches entirely if detected (with an option to override defaulted to false) so it would fit properly within other mod setups.

This would make it a highly customizable and easy to mod setup though. :-)

msakuta commented 7 years ago

The first part of your suggestion is easy.

--- a/prototypes/technology/common.lua
+++ b/prototypes/technology/common.lua
@@ -13,7 +13,7 @@ function createupgrade(level, params)
                modifier = params.modifier
            }
        },
-       prerequisites = {params.neededscience},
+       prerequisites = params.prerequisites or {params.neededscience},
        unit =
        {
            ingredients = {

It would use prerequisites field if params has one, otherwise compatible with before. No other files need to be modified. Actually I don't like that Factorio API name (prerequisites) and helper function's name (neededscience) differ in the first place, but I was lazy enough not to fix it when I copy-pasted from another source. I would drop support of neededscience format and rewrite everything to prerequisites because it's more straightforward and consistent, especially for those people who have experience with modding Factorio.

However, the latter half of your suggestion is a big deal, so I would need some time to see if it would work or appropriate. Your extendResearch seems nice and concise, even has potential of making everything into single file, but I'm not sure if mult and expo function-object-returning-functions are intuitive for newcomers. I'd like it to be easy to comprehend and modify, even for those not into Lua scripting. In this regard, count = math.floor(CountFactor * 100 * 2 ^ (i / 3)) is not the most beautiful expression out there, but the reader should get an intuition that it is a formula and editing factors would cause expected results.

And I'm not an expert on modding, either. I don't know if there's a way to get existing technology recipes and effects (the recipe table is passed to data:extend() and consumed on the fly). If I could, I might be able to use them as basis of extrapolated higher level technologies, which can be a good approach for adapting to other mods and future Factorio versions, but could I? Also I have a concern that some of the technology series have unreasonably high or low numbers of requirements for the maximum level, probably because they are hand-crafted. So just extrapolating the maximum level might not be appropriate. What I would want is a method that somehow 'fits' a curve to existing levels and reasonably extrapolate to the extreme levels. For now, hand-picking factors and bases of exponent seems not the worst method to avoid implications.

If you're in a hurry, I would merge the first patch and postpone thinking about the latter.

OvermindDL1 commented 7 years ago

Not really in a hurry, I just see a lot of possibilities for this mod, it is a great idea. :-)

And I'm not an expert on modding, either. I don't know if there's a way to get existing technology recipes and effects (the recipe table is passed to data:extend() and consumed on the fly). If I could, I might be able to use them as basis of extrapolated higher level technologies, which can be a good approach for adapting to other mods and future Factorio versions, but could I?

Why yes, yes you can. :-) LUA I think is a horrible language, but its design is very easy, and given that everything in it is either a primitive type (number/double, string) or a compound type (function/closure, table). Given that, data is a table. So for an example, bullet-damage (since it is first), you know where you do data:extend({blah1, blah2, blah3})? Well what that does is it 'extends' the data table with the tables that you passed in, overwriting existing data if it exists. Knowing that now you know that if you inject a table definition of, say type = "technology", then you know it will go to data.technology and it will be a list inside that, which you can look things up by name, such as data.technology["bullet-damage-1"] or so (I might be slightly off on the syntax, but it is like that). So not only can you put stuff 'in' to the data table, you can also examine it all you want, or you could even dump it to the log so you can see its entire contents at the time you dumped it. :-)

Now based on that, if you do a soft requirement (putting '? ' in front of a mod requirement in your info file) it requires that the other mod is loaded before yours if it exists, else it ignores it. So if you soft require the various bobs mods then you can test in the data table for his special technology and extend/modify it as you wish, and if it does not exist then the mods are not loaded so then just do nothing. :-)

Your extendResearch seems nice and concise, even has potential of making everything into single file, but I'm not sure if mult and expo function-object-returning-functions are intuitive for newcomers. I'd like it to be easy to comprehend and modify, even for those not into Lua scripting. In this regard, count = math.floor(CountFactor * 100 * 2 ^ (i / 3)) is not the most beautiful expression out there, but the reader should get an intuition that it is a formula and editing factors would cause expected results.

Perhaps, I am big of functional programming (calling functions to return functions and treating functions as data). I find them easier to teach to newbies than many language styles, as well as they are SUBSTANTIALLY more expressive in less code (as you saw in my example). And if you make enough helper functions like the mult one then it makes it really easy for newbies to add new definitions. If someone wants to do something more advanced then they probably know a little bit of lua and could just function(blah) stuff end inline in place of a mult call. :-)