Will-o'-the-Wisps updated (2)

by Pi-C

A glowing enigmatic life form was found to inhabit alien forests at night. Based on the update by mk-fg to the original mod by Betep3akata.

Content
3 years ago
0.18 - 1.0
10
Enemies

g Couple minor diffs from 0.3.3

3 years ago

Hey,

When running "diff -r" on mods just now to find any new fixes to grab (merged as https://github.com/mk-fg/games/commit/d5f11da ), thought to comment on couple diffs I've noticed there, in case you might want to tweak those.

 function zones.get_wisp_trees_anywhere(count, pollution_factor)
   -- Return up to N random trees from same
   --  pollution-weighted-random forest_radius area for spawning wisps around.
-  local wisp_trees, n, chunk, area, trees, k = {}
+  local wisp_trees, n, chunk, area, trees = {}
   while next(ForestArea) do
-    k = utils.pick_weight(get_forest_spawn_chances(pollution_factor))
+    local k = utils.pick_weight(get_forest_spawn_chances(pollution_factor))
     chunk, area = ChunkMap[k], ForestArea[k]
     trees = chunk and area
       and chunk.surface.find_entities_filtered{type='tree', area=area}

This is a different way to fix same thing, but generally you might want to declare lua variables before loops, as lua essentially creates new context on "local".
I.e. it's kinda like with local k do { ... }, while if you declare it before loop, it's less stuff to run on each loop iteration, as such context will be created before entering it just once.
Really minor and likely irrelevant optimization though, just thought to mention as I've noticed it anyway.

+  for e, event in ipairs({
+    "on_built_entity",
+    "on_robot_built_entity",
+    "script_raised_built"
+  }) do
+    script.set_event_filter(defines.events[event], on_built_entity_filter)
+  end

Maybe script_raised_revive should be here as well. Added it myself to 0.3.4 too.

+-- We need to get at the functions stored in config.lua because they can't be used in
+-- the global table anymore since Factorio 0.18.28! Everything else will be overwritten
+-- in zones.init_refs().
+--~ local conf
+local conf = require('config')

Probably leftover from earlier, and don't think it was needed or should've worked.
I.e. it was overidden on init-refs with gloabl conf mapping anyway, no functions stored there were called from zones.lua, and in control.lua they were called from conf_base anyway (just copied to "conf" for no good reason).

diff -uw -r ./prototypes/changes.lua ../_tmp/Will-o-the-Wisps_updated-2_0.18.6/prototypes/changes.lua
--- ./prototypes/changes.lua    2020-08-21 13:41:49.863972152 +0500
+++ ../_tmp/Will-o-the-Wisps_updated-2_0.18.6/prototypes/changes.lua  2020-01-21 20:51:27.000000000 +0500
@@ -25,16 +25,21 @@
                if proto.resistances then
                        if preset then table.insert(proto.resistances, preset)
                        else
-                               for _, resist in pairs(proto.resistances) do if resist.type == 'acid' then
+                               for _, acid_resist in pairs(proto.resistances) do
+                                       if acid_resist.type == 'acid' then goto acid_resist_found end end
+                               acid_resist = nil ::acid_resist_found::
+                               if acid_resist then
                                        table.insert( proto.resistances,
                                                {type='corrosion', decrease=resist.decrease, percent=resist.percent} )
-                                       break
-                       end end end
-               elseif preset and proto.max_health and proto.max_health > 0 then
+                               end
+                       end
+               elseif preset then
+                       if proto.max_health and proto.max_health > 0 then
                        proto.resistances = {}
                        table.insert(proto.resistances, preset)
                end
        end
+       end

        for cat_name, cat in pairs(data.raw) do for proto_name, proto in pairs(cat) do
                local preset = corrosion_immunity

This whole diff hunk is missing.
Iirc there's a minor logic fix here as well as fix for undeclared variables.

diff -uw -r ./libs/utils.lua ../_tmp/Will-o-the-Wisps_updated-2_0.18.6/libs/utils.lua
--- ./libs/utils.lua    2020-08-21 14:20:49.393084088 +0500
+++ ../_tmp/Will-o-the-Wisps_updated-2_0.18.6/libs/utils.lua  2020-01-21 20:51:27.000000000 +0500
@@ -53,7 +53,7 @@
 function utils.log(msg, ...)
        if not conf.debug_log then return end
        local log_func = conf.debug_log_direct and print or log
-       log_func(utils.fmt_ticks(game and game.ticks_played)..' :: '..utils.fmt(msg, ...))
+       log_func(utils.fmt_ticks(game and game.tick)..' :: '..utils.fmt(msg, ...))
 end

 function utils.error(msg, ...) error(utils.fmt(msg, ...)) end

Also missing change here, I think game.tick changed to game.ticks_played in some factorio version - there's now ticks_played + ticks_somethingelse iirc, instead of just one value.
Only relevant for timestamps in debug logging though, so no big deal.

Might want to rm whole README.md file, as it seem to be just outdated here.
I keep and edit description text there and paste it into web form (so that it can be versioned/tracked on github), but here it seem to be unnecessary old file.

If you have git repo for mod somewhere (github, gitlab, bitbucket, etc), can probably post these as a pull request there, so that you don't need to merge them manually.
But again, just minor diffs, thought that I might as well report them somewhere, since I've been going through diff again anyway.

Cheers!

3 years ago

Darn, noticed this too late! Anyway, I've just synced my mod with your update. Not really useful because I also added a conflict against my fork and a dependency on your mod. About the only original change was adding the strings for wisp-red-replication-factor to the German locale (probably not the best translation, but better than a missing key).

3 years ago

Um, but won't that dependency install and activate both mods, at the same time?
Not sure if that'd even work right, as they do add entities and other stuff under same names. Looks like a bug.

Good point on de locale.
I thought that english labels/descriptions will be used as a fallback there, but guess not, which is a bit tricky, as I can't really update those well myself.
But should at least insert same english strings (with something like ";; TODO: translate this") next to them in the future, and copy current ones from here.

3 years ago

Also, "wisp-red-replication-factor" seem to be missing under [mod-setting-name] in de locale, probably a bug?
I.e. here - https://github.com/mk-fg/games/commit/583d814#diff-2e0b217dd18b1d34321b85cc19faf0f8R46-R47

3 years ago

Um, but won't that dependency install and activate both mods, at the same time?
Not sure if that'd even work right, as they do add entities and other stuff under same names. Looks like a bug.

Updating my fork will also activate your mod. After restarting the game, both mods will be selected (checkbox is active), but my fork will be displayed in red because it conflicts with itself. Thus, the game doesn't activate it, and the player should unselect the fork -- but that's only for looks, the effect will be the same.

Good point on de locale.
I thought that english labels/descriptions will be used as a fallback there, but guess not, which is a bit tricky, as I can't really update those well myself.

The English locales will be used as fallback, but it doesn't look nice if there's an untranslated setting when all others have a translation.

3 years ago

Updating my fork will also activate your mod. After restarting the game ... displayed in red because it conflicts with itself.

Ah, didn't catch that self-conflict at first, that's a crazy hack if I ever seen one :)

The English locales will be used as fallback, but it doesn't look nice if there's an untranslated setting when all others have a translation.

Fair enough, guess I shouldn't just copy-paste english stuff there then.

3 years ago
(updated 3 years ago)

Updating my fork will also activate your mod. After restarting the game ... displayed in red because it conflicts with itself.

Ah, didn't catch that self-conflict at first, that's a crazy hack if I ever seen one :)

It has the advantage that you don't have to add a conflict against my fork. If it should ever become necessary to revive it, I won't depend on you to remove that conflict (which you couldn't do because I'd only need to revive the fork if you aren't available to change your mod) and can do that on my end. :-)

The English locales will be used as fallback, but it doesn't look nice if there's an untranslated setting when all others have a translation.

Fair enough, guess I shouldn't just copy-paste english stuff there then.

Depends. I do include the English strings in the locale files for Russian or other languages I don't know well enough, so that translators can find untranslated strings more easily. (Bio Industries has a long list of names and descriptions that need to be translated, so it's easy to miss one otherwise.)

Anyway, here's the missing string:

[mod-setting-name]
wisp-red-replication-factor=Replikationsfaktor für rote Irrlichter
3 years ago
(updated 3 years ago)

wisp-red-replication-factor=Replikationsfaktor für rote Irrlichter

Was thinking of going with "Rotes Irrlicht replikationsfaktor", but that looks more native.

It's actually also a difference I've noticed with more english people and my approach to english (and Lua and other prog-langs too, to be fair) - people like to put a lot of cruft in-between and all around meaningful words, but guess that's how proper human languages should work wrt increased redundancy, so that skim-reading or half-listening works well on them.

3 years ago

wisp-red-replication-factor=Replikationsfaktor für rote Irrlichter

Was thinking of going with "Rotes Irrlicht replikationsfaktor", but that looks more native.

Especially as all nouns are capitalized in German, so that would be a series of only capitalized words. Also, the focus should be on "Replikationsfaktor" here, not on the red wisps, that's why it should be the first word (and you'd probably need some punctuation to separate the two more clearly, like parentheses, a colon, comma, or dash).

It's actually also a difference I've noticed with more english people and my approach to english (and Lua and other prog-langs too, to be fair) - people like to put a lot of cruft in-between and all around meaningful words, but guess that's how proper human languages should work wrt increased redundancy, so that skim-reading or half-listening works well on them.

Yes, I didn't find your code easy to read! I usually split even a simple statement like "if x>y then return end" in three lines so I can easily see where the block ends. Just added a bug yesterday by inserting a "missing" end because I hadn't noticed that it already was at the end of a line -- and that was in my own code which I'm supposed to know a bit. :-)

3 years ago
(updated 3 years ago)

Yes, I didn't find your code easy to read! I usually split even a simple statement like "if x>y then return end" in three lines so I can easily see where the block ends.

Yeah, I tend to just use indentation for that, i.e. if something is indented, that need an "end", otherwise nope.

And have irrational dislike for "end ladders" like:

...
      end
    end
  end
end

It's like flooding my code window with pointless spam, which I have to scroll through and take effort to filter-out like 1000s of times a day.

Actually, also have a good example of this stuff from y-day - https://e.var.nz/scr-20200903161012.png (it's the hidden diff here) - that's before/after (and "after" actually does more stuff in it!).
Idk how people enjoy parsing important bits from all that noise, but oh well, everyone is different I guess.

3 years ago

Oh oh, also, I had a random unrelated bonus question!

As you've worked with fire mechanics in factorio, is there an easy way to make fires go out after a time, and not burn everything until there's no fuel?

I was thinking to make a "simple" weather mod which would add random lightning strikes in polluted areas where there're no player buildings (to not be annoying), and not just animations, but with the purpose of starting random fires - think https://www.youtube.com/watch?v=iMfj2cgsoRI or https://www.google.com/search?q=rimworld+lightning+strikes+fires+site:www.reddit.com , and imagine what will also happen if this lightning strikes in a dense forest during long night with this mod installed...

BUT the problem I see there is that after couple hours of the game, there will just be no forests, as that's how compound probabilities work.
So wonder if there's an easy - and maybe even built-in - way to make at least some fires go out and expire after a while, maybe you know already?

3 years ago

Yes, end ladders aren't nice, and long-distance scrolling isn't nice either. If only my editor would support something like brace-matching (mark one and its counterpart will be highlighted) for command blocks (loops, if-then etc)! That would make it so much easier to see if something is used in the block where it was defined or out of scope …

3 years ago
(updated 3 years ago)

So wonder if there's an easy - and maybe even built-in - way to make at least some fires go out and expire after a while, maybe you know already?

See here -- fires have these properties that determine their lifetime:

  • burnt_patch_lifetime
  • maximum_lifetime
  • (initial_lifetime)

After the visible flames have expired, burnt_patch_lifetime starts, so the fire entity will still exist. This thread is about the confusing issue that apparently dead fires were still recognized by the game.

To prevent that your forests burn down completely, you could also set spread_delay, maximum_spread_count, and lifetime_increase_by in the prototype.

Handling fire is difficult because the entities don't have a unit_number. You'd have to store the entities when they are created, so you can call destroy() on them.

3 years ago

Oh, nice that even flames themselves are moddable, was afraid that they might be an entirely special mechanic, working in it's own way.
That seem to be enough tunables to probably make the idea work. Thanks for the info!

3 years ago

You're welcome! Would be nice if you'd post a link once the weather mod is ready. :-)

3 years ago

Well, if it will ever be ready too.

I suspect that no matter how you limit the fires, only good way to balance destruction is to cheat and monitor the map for burn/alive tree counts and only invoke the zeus once that balance is shifted away from some limit, either by generating more map or whatever tree-growing mod or contraption.
(like, keeping that robot-garden mod in check - imagine poor things planting those trees relentlessly, only for such mod to check when it's time to burn them all down)

3 years ago
(updated 3 years ago)

Making it would probably be a good excuse to finally add here a fire-spawned orange benzin wisps with a long-range flammenwerfer...

3 years ago

I really should get to work on my water turrets mod again! :-D

3 years ago

Added Wildfire mod, which starts fires but doesn't do weather, as latter raises too many issues (like why there's no rain, why lightning won't strike metal electric towers and such, has to be animated, nice effects are hard, etc etc) - simple self-ignition should be enough to make things more "interesting".

3 years ago

Thanks for the info! Just downloaded and will try it out now. :-)

I wonder how that will work with Maps. I add some loot there to all tree prototypes (as well as spawners/worms), as an incentive to go out exploring. The probability that a tree will give you loot is already quite low (still, killing a forest means killing many individual entities, so you'll probably find a map or two each time you clear a patch of reasonable size), and if the entities died from damage by fire or explosion, small and regular maps will be removed (they "burn") while regular maps will be replaced with a smaller ("singed") version.

After a quick view at your code, it seems that fires really could start anywhere on the known map, whether a player, turret, or vehicle is near or not. So I guess it could happen that a forest burns down at one end, without anybody noticing, and when a player does come into the area, there's loot on the ground for no obvious reason. I could just ignore that (nature provided, player just got lucky), or I could let maps on the ground expire after a while (meaning I'd have to store a list of maps in global and remove maps that have been picked up or expired). There may be a third option: If you'd create a force for the wild fires, I could check if a tree was killed by a regular fire or by a wildfire. (That would work for the fires you create -- but if they spread, would the new fires inherit the force?) What would you suggest?

3 years ago

One alternative might be to drop loot only if a player is nearby.
Given that chance of spawning a loot isn't high to begin with, and there're only couple players to check distance to, probably shouldn't be a problem even with nukes.
Will check if force applies to fires on kills, as that'd certainly be an easy tweak as well.

3 years ago

Added on_death handler and created fires with "wildfire" force, and event.cause.force.name indeed seem to return "wildfire", so guess these fires keep initial force name and can be distinguished by that.

I also did check which force is attributed to player-started fires, and it seem to be "player" (player's force), so if you'll be checking cause-force there, it'd probably be best to not check for "wildfire", "space-meteorites" or any other mod-added forces, but check if it's force of one of the players instead.
Iirc "cause" in on_death can also be nil, and wisps mod handles that case, which I think was related to a bug report from space exploration mod there, but I don't remember when exactly it happens, maybe when mod deletes or kills an entity or something.

3 years ago

Added on_death handler and created fires with "wildfire" force, and event.cause.force.name indeed seem to return "wildfire", so guess these fires keep initial force name and can be distinguished by that.

Great, thanks!

I also did check which force is attributed to player-started fires, and it seem to be "player" (player's force), so if you'll be checking cause-force there, it'd probably be best to not check for "wildfire", "space-meteorites" or any other mod-added forces, but check if it's force of one of the players instead.

There are mods that allow players to change their force, so these could also have players. Checking for table_size(force.players)>0 should take care of that.

Iirc "cause" in on_death can also be nil, and wisps mod handles that case, which I think was related to a bug report from space exploration mod there, but I don't remember when exactly it happens, maybe when mod deletes or kills an entity or something.

If an entity is shot at, you have an immediate cause. If somebody throws some poison capsules and an enemy dies from that some time later, the cause would be nil, if I remember correctly. Not sure what would happen if an artillery turret shoots at something and is killed before the projectile reaches its target. My guess is there still would be a cause, but it wouldn't be valid.

3 years ago

table_size(force.players)>0

if next(force.players) then ... should also work for tables with or without counter iirc.

3 years ago
(updated 3 years ago)

(EDIT: Removed -- couldn't read the settings explanation correctly because font was too small on this computer; figured it out after looking at the code.)

New response